diff --git a/zh-cn/device-dev/bundles/Readme-CN.md b/zh-cn/device-dev/bundles/Readme-CN.md index 6b1ae76002fff938ab4b3098621a85736b7756c9..7233ea64d4297bef0816b08f413009882a6e3a64 100755 --- a/zh-cn/device-dev/bundles/Readme-CN.md +++ b/zh-cn/device-dev/bundles/Readme-CN.md @@ -1,20 +1,12 @@ -# 组件开发 - -- [组件开发规范](组件开发规范.md) - - [概述](概述.md) - - [组件构成](组件构成.md) - - [组件管理](组件管理.md) - - [组件版本](组件版本.md) - - [发行版](发行版.md) - - [环境变量说明](环境变量说明.md) - -- [组件开发指南](组件开发指南.md) - - [概述](概述-0.md) - - [准备工作](准备工作.md) - - [组件开发](组件开发.md) - -- [组件开发示例](组件开发示例.md) - - [HPM介绍](HPM介绍.md) - - [环境准备](环境准备.md) - - [操作实例](操作实例.md) +# 组件开发指南 + +- [组件开发规范](bundles-standard-rules.md) +- [组件开发指南](bundles-guide.md) + - [组件开发指南](bundles-guide-overview.md) + - [准备工作](bundles-guide-prepare.md) + - [组件开发](bundles-guide-develop.md) +- [组件开发示例](bundles-demo.md) + - [HPM介绍](bundles-demo-hpmdescription.md) + - [环境准备](bundles-demo-environment.md) + - [操作实例](bundles-demo-devsample.md) diff --git a/zh-cn/device-dev/bundles/bundles-demo-devsample.md b/zh-cn/device-dev/bundles/bundles-demo-devsample.md new file mode 100644 index 0000000000000000000000000000000000000000..1de6091e00561003efb769708a6dd5af62bd3f24 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-demo-devsample.md @@ -0,0 +1,54 @@ +# 操作实例 + +环境准备好后,接下来本文以Hi3861平台为例,演示如何利用HPM进行组件的安装、编译和打包。 + +1. 执行以下命令,初始化安装目录(目录名可自行设置): + + ``` + mkdir test3861 + cd test3861 + hpm init -t dist + ``` + + 初始化成功则显示: + + ``` + Initialization finished. + ``` + +2. 安装wifi\_iot发行版。 + + ``` + hpm install @ohos/wifi_iot + ``` + + 安装成功则显示: + + ``` + Installed. + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >Hi3516平台采用下述命令: + >``` + >hpm install @ohos/ip_camera_hi3516dv300 + >``` + >Hi3518平台采用下述命令: + >``` + >hpm install @ohos/ip_camera_hi3518ev300 + >``` + +3. 编译打包 + + ``` + hpm dist + ``` + + 编译成功会显示: + + ``` + {{name}}: distribution building completed. + ``` + +4. 上述所有命令执行成功后,在 ./out 目录下会生成编译结果,开发者可以将编译结果烧录到对应的开发板上进行测试。 + diff --git a/zh-cn/device-dev/bundles/bundles-demo-environment.md b/zh-cn/device-dev/bundles/bundles-demo-environment.md new file mode 100644 index 0000000000000000000000000000000000000000..1a05b2a302aa04390d4b294e784f30f07ebc0e72 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-demo-environment.md @@ -0,0 +1,139 @@ +# 环境准备 + +- [linux服务器](#section20979554791) +- [安装Node.js](#section9954105413153) +- [安装HPM](#section15937194904819) +- [安装python环境](#section1621819180417) +- [安装文件打包工具](#section77617165913) +- [安装SCons](#section20558439191516) + +## linux服务器 + +准备一台装有Ubuntu 16.04 及以上 64 位系统的linux服务器(hpm是支持windows的,但是目前OpenHarmony开源的Hi3861、Hi3516、Hi3518三个解决方案都只支持Ubuntu)。 + +将linux shell改为bash: + +``` +ls -l $(which sh) +# 如果指向的不是bash,则按以下方式修改: +# 方法一:执行以下命令,然后选择no +dpkg-reconfigure dash +# 方法二:先删除sh,再重新创建软连接 +rm -f /bin/sh +ln -s bash /bin/sh +``` + +## 安装Node.js + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果配置的源的nodejs版本太低,可以执行以下语句后再执行apt-get install: +>``` +>curl -L https://deb.nodesource.com/setup_12.x | bash +>``` + +推荐安装 Node.js 12.x (包含 npm 6.14.4)或更高版本(推荐 12.13.0+): + +``` +sudo apt-get install nodejs +sudo apt-get install npm +``` + +查看版本: + +``` +node --version # 查看nodejs版本 +npm --version # 查看npm版本 +``` + +## 安装HPM + +通过 Node.js 自带的 npm(使用默认的源 https://registry.npmjs.org/ )安装 hpm-cli 命令行工具: + +``` +npm install -g @ohos/hpm-cli +``` + +安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: + +``` +hpm config +``` + +上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: + +``` +registry = https://hpm.harmonyos.com # hpm注册中心地址,下载组件必须 +strictSsl = true # 通过https连接时,是否需要校验证书 +http_proxy = http://your-proxy-server:port # 配置HTTP代理 +https_proxy = http://your-proxy-server:port # 配置HTTPS代理 +``` + +hpm-cli的命令介绍可以参考:[hpm操作命令](bundles-standard-rules.md) + +## 安装python环境 + +需使用python3.7以上版本,采用以下命令进行安装: + +``` +sudo apt-get install python3.8 +sudo apt-get install python3-pip +sudo pip3 install setuptools +sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>上述方式适用Hi3518和Hi3516两种平台,针对Hi3861平台采用以下方式安装python环境: +>``` +>sudo apt-get install python3.8 +>sudo apt-get install python3-pip +>sudo pip3 install setuptools +>sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 +>sudo pip3 install pycryptodome +>sudo pip3 install six --upgrade --ignore-installed six +>sudo pip3 install ecdsa +>``` + +如果当前系统中既存在python2又存在python3,参考以下方法将默认python修改为python3: + +``` +ll `which python` +rm /usr/bin/python +ln -s python3.8 /usr/bin/python +``` + +## 安装文件打包工具 + +采用以下命令进行安装: + +``` +which mkfs.vfat # 如果没找到,执行以下命令安装 +sudo apt-get install dosfstools +which mcopy # 如果没找到,执行以下命令安装 +sudo apt-get install mtools +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>Hi3518和Hi3516两种平台需要安装打包工具,Hi3861平台不需要。 + +## 安装SCons + +1. 打开Linux编译服务器终端。 +2. 运行如下命令,安装SCons安装包。 + + ``` + python3 -m pip install scons + ``` + +3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 + + ``` + scons -v + ``` + + **图 1** SCons安装成功界面,版本要求3.0.4以上 + ![](figure/SCons安装成功界面-版本要求3-0-4以上-21.png "SCons安装成功界面-版本要求3-0-4以上-21") + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>Hi3861平台需要安装SCons,Hi3518和Hi3516两种平台不需要。 + diff --git "a/zh-cn/device-dev/bundles/HPM\344\273\213\347\273\215.md" b/zh-cn/device-dev/bundles/bundles-demo-hpmdescription.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/bundles/HPM\344\273\213\347\273\215.md" rename to zh-cn/device-dev/bundles/bundles-demo-hpmdescription.md diff --git a/zh-cn/device-dev/bundles/bundles-demo.md b/zh-cn/device-dev/bundles/bundles-demo.md new file mode 100644 index 0000000000000000000000000000000000000000..bcdc877e6dd00f49a3195ff4443a08de52917a1c --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-demo.md @@ -0,0 +1,9 @@ +# 组件开发示例 + +- **[HPM介绍](bundles-demo-hpmdescription.md)** + +- **[环境准备](bundles-demo-environment.md)** + +- **[操作实例](bundles-demo-devsample.md)** + + diff --git a/zh-cn/device-dev/bundles/bundles-guide-develop.md b/zh-cn/device-dev/bundles/bundles-guide-develop.md new file mode 100644 index 0000000000000000000000000000000000000000..bc462fd12dceefd0cb04dcfbdccf97a8412c6027 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide-develop.md @@ -0,0 +1,240 @@ +# 组件开发 + +- [创建OpenHarmony组件](#section1976410130540) +- [新建组件](#section717481119145) +- [改造组件](#section102861955201410) +- [从模板创建组件](#section15882846181510) +- [编译组件](#section136732148541) +- [定义编译脚本](#section10274147111610) +- [执行编译](#section879301916172) +- [定义发行版](#section413216495619) +- [定义脚本](#section11503171219190) +- [发行](#section4694125521912) +- [烧录](#section1746331545413) +- [运行调试](#section6742131615549) + +## 创建OpenHarmony组件 + +创建OpenHarmony组件有如下几种方式: + +- 从头开发一个全新的组件。 +- 将一个现有的非组件的代码改造成组件。 +- hpm提供了一些组件模板方便快速创建组件。 + +## 新建组件 + +通常情况下,[HPM网站](https://hpm.harmonyOS.com)上能找到您开发常用的组件,如果现有的组件不能完全满足开发,这时可以自己动手开发一个组件。 + +如果您愿意,可以将组件发布到HPM的仓库中供其他用户使用。假设要在D:/source目录下新建一个全新的组件my-bundle: + +可以使用hpm init 创建该组件的脚手架代码,例如,进入D:/source目录,执行如下命令: + +``` +hpm init -t default -d demo my-bundle +``` + +会在 source 目录下生成如下文件: + +``` +mybundle +├── bundle.json # 组件元数据描述文件 +├── example # 测试组件功能的示例 +│ └── main.c +├── include # 组件的内部头文件 +│ └── mybundle.h +├── README.md # 组件的简要说明 +└── src # 组件的源代码 + └─ mybundle.c +``` + +接下来根据您的业务需要,实现组件内部的功能代码,完成代码开发后,通过git将代码(包括bundle.json文件)提交到组件代码托管仓库中(如gitee)。 + +## 改造组件 + +如果您已经有了代码,只是还不满足OpenHarmony的组件结构,需要改造成为hpm的组件包,只需要在当前要改造的代码目录下(例如mybundle2),执行如下命令,会提示您输入组件名称和版本。 + +``` +hpm init +``` + +1. 输入名称后回车(如mybundle2)。 +2. 输入版本后(如1.0.0)回车,在当前组件目录下会生成一个bundle.json文件。 +3. 打开bundle.json文件再添加其他的描述,这时候他已经是一个具备可发布的组件了。 + + ``` + $ hpm init + Your bundle will be created in dirname E:\demo\mybundle2 + ? bundle name mybundel2 + ? version 1.0.0 + Init finished! + ``` + + +1. 打开bundle.json文件修改其他信息(如作者,代码仓库,代码目录,命令脚本,依赖组件等),如下: + + ``` + { + "name": "mybundle2", + "version": "1.0.0", + "publishAs": "source", + "dirs":{ + ".":[ + "README.md" + ], + "src":[ + "test.c" + ], + "header":[ + "header/test.h" + ], + "src/common":[ + "src/common/foobar.txt" + ] + }, + "scripts": { + "build": "make -${args}" + }, + "dependencies": { + "@ohos/cjson": "^1.0.0", + "@ohos/": "^1.2.0" + } + } + ``` + + +## 从模板创建组件 + +hpm 除了提供了默认模板 default和simple两个简单的模板之外,其他模板均存储在服务器端。 + +可以使用命令hpm search -t template 从服务器端搜索模板。 + +![](figure/zh-cn_image_0000001051452177.png) + +根据description简要中的描述,找到适合的模板,基于模板可以快速创建一个组件的脚手架,执行如下初始化命令(指定-t -d 参数)。 + +``` +hpm init -t {templatename} -d dir name +``` + +- \{templatename\} :指的是模板名称。 +- -d 后面的参数dir:是要创建的组件所存放的路径。 +- name:为要创建的组件名称。 + +## 编译组件 + +完成代码开发后,需要对组件进行编译。hpm提供了命令集成的能力,您可以选择任意的适合项目的编译工具(如make,gcc,gn等等)。只需在当前项目的bundle.json文件中定义scripts脚本中的build命令,就可以通过执行hpm build执行编译。 + +## 定义编译脚本 + +以编译一个app目录下helloworld可执行文件为例: + +``` +app +├── BUILD.gn +├── include +│ └── helloworld.h +└── src + └── helloworld.c +``` + +在helloworld.c同级目录下新建一个BUILD.gn + +``` +touch BUILD.gn +vim BUILD.gn +``` + +以下是BUILD.gn的样例,仅供参考 + +``` +executable("hello_world") { + sources = [ + "src/helloworld.c" + ] + + include_dirs = [ + "include" + ] +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- “executable”是gn内置模板,可以用“gn help executable ”查看使用方法。 +>- “sources ”是源码路径,“include\_dirs ”是头文件路径。 + +## 执行编译 + +在当前文件夹下,执行编译命令: + +``` +hpm build +``` + +在完成一系列的编译动作后,显示build succeed。检查编译的输出结果: + +![](figure/zh-cn_image_0000001051770876.png) + +## 定义发行版 + +发行版是将一组组件组合起来的,编译生成可以运行的OpenHarmony解决方案,里面包含了较多依赖的组件,以及以脚本形式描述如何完整编译、链接这些组件。 + +## 定义脚本 + +bundle.json中定义 + +``` +{ +"name": "my_dist", +"version": "1.0.0", +"publishAs": "distribution", +"scripts": { +"dist": "make -${args}" + }, +"base": { +"name": "dist-bundle", +"version": "1.0.0" + }, +"envs": { +"args": "x86" + }, +"dependencies": { +} +} +``` + +## 发行 + +在当前发行版根目录下,执行如下命令。 + +``` +hpm dist +``` + +hpm-cli工具会自动执行编译,打包操作,将根据scripts定义的dist脚本生成镜像文件,如: + +``` +out +|-xxdist.img +|-xx.file +``` + +## 烧录 + +发行版的编译结果可以烧录到设备中运行,例如使用hiburn工具进行烧录。在发行版的bundle.json文件配置烧录参数。 + +``` +"scripts": { +"flash": "{$DEP_HIBURN}/hiburn" +}, +``` + +配置烧录相关的参数(参考烧录工具的说明进行配置)。 + +``` +hpm run flash +``` + +## 运行调试 + +将发行版的镜像烧录到设备中后,就可以启动运行调试了,由于运行调试和具体的开发板和IDE调试工具相关,此处不再详细描述。 + diff --git a/zh-cn/device-dev/bundles/bundles-guide-overview.md b/zh-cn/device-dev/bundles/bundles-guide-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..332a8fc00782f0ca9db5bbe4668e3ad6d68f38ef --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide-overview.md @@ -0,0 +1,54 @@ +# 概述 + +本章节将简要介绍如何开发OpenHarmony组件和发行版,并通过命令行工具方式完成组件创建、开发、编译、烧录、调试等开发过程。 + +- 一个组件(bundle)通常和一个代码仓库对应,在代码的基础上增加bundle.json、README文件、LICENSE描述文件。 +- 一个发行版(distribution)是由多个组件构成的。发行版中集合了一个完整系统的各种组件(如驱动、内核、框架、应用),可以用于设备的烧录。 + +**表 1** 组件和发行版的差异对比 + + + + + + + + + + + + + + + + + + + + + + + + +

异同点

+

组件

+

发行版

+

应用场景

+

面向功能特性开发

+

面向系统开发

+

内容

+

功能或特性的实现代码或二进制库

+

依赖的组件清单及编译构建脚本

+

完整程度

+

操作系统的一部分

+

一个完整操作系统版本

+

编译后结果

+

组件包

+

系统镜像

+
+ +**图 1** 组件和发行版的构成 + + +![](figure/组件0924.png) + diff --git a/zh-cn/device-dev/bundles/bundles-guide-prepare.md b/zh-cn/device-dev/bundles/bundles-guide-prepare.md new file mode 100644 index 0000000000000000000000000000000000000000..4068e7d7bee57afd03cd3098b97e923dc16edb66 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide-prepare.md @@ -0,0 +1,84 @@ +# 准备工作 + +- [硬件要求](#section98535485518) +- [安装Node.js和hpm命令行工具](#section106591616205311) +- [更改hpm的配置(可选)](#section71821165412) +- [下载OpenHarmony代码](#section102338221707) +- [安装开发依赖的组件](#section19233183315020) + +## 硬件要求 + +- 准备设备开发的开发板(如Hi3861、Hi3516DV300、Hi3518EV300) +- 主机电脑(Windows工作台) +- Linux服务器 + +**图 1** 硬件环境连接关系 +![](figure/硬件环境连接关系.png "硬件环境连接关系") + +## 安装Node.js和hpm命令行工具 + +1. 安装Node.js。 + + 从官网下载并在本地安装Node.js. + + 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 + +2. 通过Node.js自带的npm安装hpm-cli命令行工具。执行以下命令: + + ``` + npm install -g @ohos/hpm-cli + ``` + +3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 + + ``` + hpm -V 或 hpm --version + ``` + +4. (可选)如果需要升级hpm版本,请执行如下命令: + + ``` + npm update -g @ohos/hpm-cli + ``` + + +## 更改hpm的配置(可选) + +安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: + +``` +hpm config +``` + +上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: + +``` +registry = https://hpm.harmonyos.com/hpm/registry/api # hpm注册中心地址,下载组件必须 +login = https://hpm.harmonyos.com/hpm/auth/pk # hpm处理登录地址,发布组件必须 +loginUser = {your-account} # 配置hpm登录账号,发布组件必须 +shellPath = C:\WINDOWS\System32\cmd.exe # hpm命令执行使用的shell +globalRepo = C:\Users\yourname\.global # 配置全局安装的组件存放路径 +http_proxy = http://your-proxy-server:port # 配置HTTP代理 +https_proxy = http://your-proxy-server:port # 配置HTTPS代理 +``` + +hpm-cli的命令介绍可以参考:[hpm操作命令](bundles-guide-overview.md) + +## 下载OpenHarmony代码 + +参考[《源码获取》](../get-code/sourcecode-acquire.md)。 + +## 安装开发依赖的组件 + +hpm包管理器将常用开发开发工具(如烧录,编译,压缩等)也发布成了组件。可以通过如下命令方式进行安装,执行完该命令后,系统会自动将开发依赖的工具下载安装,且这些组件只需全局安装一次。 + +``` +hpm i -g @ohos/llvm +hpm i -g @ohos/ninja +hpm i -g @ohos/gn +hpm i -g @ohos/hc_gen +hpm i -g @ohos/sysroot +``` + +这是一组开发工具的组件包(如包含gn,ninja等工具),有了这些开发态的组件,就可以进行常规的源码组件的开发了。 + diff --git a/zh-cn/device-dev/bundles/bundles-guide.md b/zh-cn/device-dev/bundles/bundles-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..ca5ee5824bee855bc41e9c5d0bf758fee2e29041 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-guide.md @@ -0,0 +1,9 @@ +# 组件开发指南 + +- **[概述](bundles-guide-overview.md)** + +- **[准备工作](bundles-guide-prepare.md)** + +- **[组件开发](bundles-guide-develop.md)** + + diff --git a/zh-cn/device-dev/bundles/bundles-standard-rules.md b/zh-cn/device-dev/bundles/bundles-standard-rules.md new file mode 100644 index 0000000000000000000000000000000000000000..350c2f80db60eba6fe7f2a4b1adf5b304ff5e8b8 --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles-standard-rules.md @@ -0,0 +1,549 @@ +# 组件开发规范 + +- [概述](#section1725818533344) + - [定义](#section4821219183514) + - [组件划分原则](#section1089794263513) + - [组件依赖](#section25701647163710) + +- [组件构成](#section185538333914) + - [代码文件](#section8431268393) + - [说明文件](#section168121548173914) + - [元数据描述文件](#section7107181819406) + +- [组件管理](#section32061634104110) + - [依赖关系](#section791115242423) + - [hpm操作命令参考](#section1183205411429) + +- [组件版本](#section12612142864316) + - [版本号命名规范](#section1487612416432) + - [版本发布](#section1548171014440) + +- [发行版](#section1264139114413) +- [环境变量说明](#section15352105174512) + +## 概述 + +本文档将介绍组件的基本概念以及如何按照规范定义组件。 + +### 定义 + +OpenHarmony软件以组件\(bundle\)作为基本单元,从系统角度看,凡是运行在OpenHarmony上的软件都可以定义为组件;一般来讲,根据组件的应用范围,可以分为: + +- 板级组件:如board、arch、mcu这些与设备硬件相关的组件。 +- 系统组件:一组独立功能的集合,如内核、文件系统、框架等。 +- 应用组件:直接面向用户提供服务的应用\(如wifi\_iot,ip\_camera\)。 + +从形式上看,组件是为复用而生,一切可以复用的模块都可以定义为组件,可以分为: + +- 源代码 +- 二进制 +- 代码片段 +- 发行版 + +### 组件划分原则 + +原则上应尽可能划分为细颗粒度的组件,以满足最大限度的复用。主要考虑以下几点: + +- 独立性:组件的功能应该相对独立,支持独立编译,可以单独对外提供接口和服务; +- 耦合性:如果组件必须依赖其他的组件,才能对外提供服务,应考虑和被依赖的组件合并为一个组件。 +- 相关性:如果一组组件共同完成一项功能,且没有被其他组件依赖,未来也没有被依赖的可能,则可以考虑合并为一个组件。 + +### 组件依赖 + +组件的依赖关系分为两种:必选依赖和可选依赖。 + +- 必选依赖:是指组件A在完成某个功能时,必须引入组件B,调用B的接口或服务配合才能完成。称B为A的必选依赖。 +- 可选依赖:是在组件A在完成某个功能时,可以引入组件C,也可以引入组件D。C和D可以相互替换,称C和D为A的可选依赖。 + +## 组件构成 + +一个组件包一般包含如下内容: + +- 组件包的代码或库(src目录下的代码文件) +- ohos\_bundles文件夹(存放依赖的组件,安装组件时自动生成,无需提交到代码库) +- 组件包的说明文件\(README.md\) +- 组件包元数据声明文件\(bundle.json\) +- 开源许可文件\(LICENSE\) + + ``` + my-bundle + |_ohos_bundles + |_src + |_bundle.json + |_README.md + |_LICENSE + ``` + + +### 代码文件 + +组件的代码文件和普通的代码目录没有差异。但要注意的是,组件中对外暴露的接口(头文件),会被其他组件所引用,需要单独在bundle.json的dirs中声明。 + +### 说明文件 + +README.md,为markdown格式的描述关于组件自述说明文件。([语法参考](https://www.markdownguide.org/getting-started/)\) + +为了帮助他人在hpm上找到该组件,并更方便的使用它,在组件的根目录中包含一个README文件。 + +README文件可能包括如何安装,配置和使用组件包中的实例代码说明,以及可能会对用户有所帮助的任何其他信息。 + +每个组件的自述文件将显示在hpm系统的组件详情页面的描述中。 + +### 元数据描述文件 + +bundle.json文件是对当前组件的元数据描述,每个组件中必须包含一个bundle.json文件。 + +``` +{ + "name": "@myorg/demo-bundle", + "version": "1.0.0", + "license": "MIT", + "description": "bundle description", + "keywords": ["hos"], + "tags": ["applications", "drivers"], + "author": {"name":"","email":"","url":""}, + "contributors":[{"name":"","email":"","url":""},{"name":"","email":"","url":""}], + "homepage": "http://www.foo.bar.com", + "repository": "https://git@gitee.com:foo/bar.git", + "publishAs": "code-segment", + "segment":{ + "destPath":"/the/dest/path" + }, + "dirs": { + "src": ["src/**/*.c"], + "headers": ["headers/**/*.h"], + "bin": ["bin/**/*.o"] + }, + "scripts": { + "build": "make" + }, + "envs": {}, + "ohos": { + "os": "2.0.0", + "board": "hi3516", + "kernel": "liteos-a" + }, + "rom": "10240", + "ram": "1024", + "dependencies": { + "@myorg/net":"1.0.0" + } +} +``` + +bundle.json文件具有如下功能: + +- name:定义组件的名称,放到组织下, 以@开头,/分割,如:@myorg/mybundle + +- version:定义组件版本号,如1.0.0,需满足semver的标准。 + +- description:一句话对组件进行简要的描述。 +- dependencies:定义组件的依赖组件。 + +- envs: 定义组件编译时所需要的参数,包括全局参数以及依赖所需的参数。 + +- scripts:定义在当前组件下能够执行的命令(如编译,构建,测试,烧录等)。 + +- publishAs:定义组件的发布类型(source:源码,binary:二进制,distribution:发行版,code-segment:代码片段)。 + +- segment: 仅针对code-segment类型的组件,定义组件的目标路径(即安装后,组件包中包含的文件复制到的目标路径) +- dirs:定义发布时打包的目录结构(如头文件)。 + +- ram&rom:统计相关信息:预计占用ROM和RAM信息。 +- ohos:描述OpenHarmony系统版本、开发板及内核的匹配关系(多个请用英文逗号的“,”分割)。 +- 定义其他扩展信息:作者,主页,代码仓库,许可协议,标签,关键字。 +- 对于发行版类型,还有个base,可以定义继承自的发行版。 + +## 组件管理 + +### 依赖关系 + +生成基础bundle.json以后,需要继续添加组件依赖来实现更复杂的功能。此时需要知道所依赖组件的名称和版本号,并且把它们定义在bundle.json里面的dependencies字段中。 + +``` +{ + "name": "my-bundle", + "version": "1.0.0", + "dependencies": { + "net": "1.0.0" + } +} +``` + +上述示例中,my-bundle组件依赖于net 1.0.0组件。在全局安装了 hpm CLI 工具之后,执行如下命令可以从远端仓库获取到依赖: + +``` +hpm install +``` + +依赖获取以后,会保存到当前组件根目录下到ohos\_bundles文件夹中。组件以及依赖之间会形成一个依赖关系的树状结构。全局安装了 hpm CLI 工具之后,在组件根目录下执行如下命令: + +``` +username@server MINGW64 /f/showcase/demo/demo +$ hpm list ++--demo@1.0.0 +| +--@huawei/media@1.0.2 +| +--@demo/sport_hi3518ev300_liteos_a@1.0.0 +| | +--@demo/app@4.0.1 +| | | +--@demo/build@4.0.1 +| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 +| | +--@demo/liteos_a@4.0.0 +| | | +--@demo/third_party_fatfs@4.0.0 +| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 +| | +--@demo/init@4.0.0 +| | +--@demo/dist_tools@4.0.0 +``` + +还可以使用可视化的形式,来查看当前组件的依赖关系,执行如下命令: + +``` +hpm ui +``` + +会在本地启动一个web服务(默认会打开浏览器并进入项目页),点击侧边栏的项目依赖图标,打开页面,可以看到项目的依赖组件列表,点击右侧按钮切换到树状视图,就可以看到依赖关系的图形化展示\(如下图\)。 + +**图 1** 组件包依赖关系图 + + +![](figure/zh-cn_image_0000001173313501.png) + +### hpm操作命令参考 + +组件的全生命周期管理,可以通过hpm命令工具进行操作,hpm的操作命令如下(详细帮助可以执行 hpm -h学习): + +**表 1** hpm操作命令 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

命令类别

+

命令行

+

含义说明

+

版本查询

+

hpm -V 或 hpm --version

+

查看hpm-cli 版本号。

+

帮助查询

+

hpm -h 或 hpm --version

+

查看命令列表及帮助。

+

hpm -h

+

查看命令帮助。

+

创建

+

+

hpm init bundle

+

创建组件工程。

+

hpm init -t template

+

根据模板创建脚手架工程。

+

安装

+

+

hpm install 或hpm i

+

安装bundle.json中依赖的组件。

+

hpm install bundle@version

+

安装指定组件版本。

+

卸载

+

+

hpm uninstall bundle

+

删除depedencies依赖的组件。

+

hpm remove 或hpm rm bundlename

+

删除depedencies依赖的组件。

+

查看

+

+

hpm list 或者 hpm ls

+

显示当前组件/发行版所有的组件树。

+

hpm dependencies

+

生成当前组件/发行版依赖关系数据(在hpm ui也集成了该命令的调用,可以图形化的展示)

+

搜索

+

hpm search name

+

搜索组件,--json,可以以json格式输出 -type 可以设置搜索组件的类型,包括bundle,distribution,code-segment三种。

+

设置hpm配置项

+

hpm config set key value

+

设置配置值,如服务器地址,网络代理。

+

hpm config delete key

+

删除配置。

+

更新

+

+

hpm update

+

更新当前组件依赖的组件的版本。

+

hpm check-update

+

检查依赖的组件版本是否有更新。

+

编译

+

+

hpm build

+

编译组件/发行版。

+

hpm dist

+

针对发行版(distribution),发行版编译构建(依赖bundle.json的scripts中的dist脚本)。

+

打包

+

hpm pack

+

本地组件打包依赖。

+

烧录

+

hpm run flash

+

烧录固件(依赖bundle.json的scripts中的flash脚本)。

+

发布

+

hpm publish

+

发布组件,发布的组件在仓库中必须唯一,且版本唯一(需要账号登录)。

+

执行扩展命令

+

hpm run

+

执行bundle.json文件中定义的scripts脚本命令,支持多个命令可用 && 连接。

+

解压包

+

hpm extract

+

解压文件. 支持格式'zip','tar','tgz' 和'.tar.gz'

+

启动图形化界面

+

hpm ui

+

本地启动HPM UI,可通过-p参数指定端口,Windows平台下会启动默认的浏览器打开

+

多语言切换

+

hpm lang

+

切换中英文操作界面(同时支持命令行和UI)

+

转换为hpm包格式

+

hpm x2h

+

将一个maven格式或npm格式包转换成hpm的包格式,并发布到HPM

+

代码段还原或清理

+

hpm code clean|restore

+

针对依赖的代码段(code-segment)组件,执行清理或还原操作(即根据segment.destPath执行拷贝/删除操作)

+

生成秘钥

+

hpm gen-keys

+

生成公钥/私钥对,将公钥配置到HPM服务端,可以实现hpm-cli 免密登录,发布组件。

+

生成第三方开源说明

+

hpm gen-notice

+

根据每个组件的说明,生成一份合并后的第三方开源说明的合并文件。

+
+ +## 组件版本 + +### 版本号命名规范 + +名称需要为全小写字母,中间可以使用中划线或者下划线分隔。比如 "bundle", "my\_bundle"。 + +版本号的格式为 "主版本号.次版本号.修订号" 或 "主版本号.次版本号.修订号-先行版本号",比如 "1.0.0", "1.0.0-beta",详细规格可以参考 [https://semver.org](https://semver.org/)。 + +### 版本发布 + +为了使组件能被其他开发者使用,组件需要上传到远端仓库。组件上传使用如下命令: + +``` +hpm publish +``` + +命令执行以后,系统会对的整个依赖关系进行检查,下载缺失依赖组件。依赖检查完成后,如果发布类型为binary,系统会对整个组件进行编译,生成二进制文件,然后打包上传。如果使其他上传类型,则直接根据定义的打包规则进行打包,然后上传。 + +注意:发布组件需要用户账号登录,需要先拥有hpm的系统账号后,并注册组织,申请组织认证通过后,才拥有发布的权限。 + +## 发行版 + +发行版通常是将一系列组件组合起来,成为编译可以运行的OpenHarmony解决方案镜像,里面包含了多个依赖的组件,以及脚本,用于描述如何完整编译、链接这些组件。 + +发行版本身通常不需要包含功能实现代码,仅包含bundle.json描述(设置publishAs为distribution)和一些编译脚本组成。 + +因为发行版编译的过程需要系统提供环境变量,所以发行版使用scripts脚本中内置的dist命令: + +``` +{ + "publishAs":"distribution", + "scripts": { + "dist": "script compile command" + } +} +``` + +编译执行使用如下命令: + +``` +hpm dist +``` + +重新定义一个发行版所具有的功能是一个复杂的过程,所以系统允许对发行版进行继承,从而在现有功能的基础上进行定制。继承发行版需要在bundle.json中定义base字段。 + +``` +{ + "base": { + "name": "dist_wifi_iot", + "version": "1.0.0" + } +} +``` + +上述定义表明当前组件继承自发行版组件dist-wifi-iot 1.0.0。 + +发行版由很多的依赖组件组成,通过bundle.json中的dependencies段来描述,有些依赖是必须的,有些依赖则是根据可以需求增加或删除的。bundle.json中名称前带有?的依赖表示可选依赖,继承它的发行版,可以移除掉该可选组件,再增加别的组件进行替换。 + +``` +{ + "dependencies": { + "?my_bundle": "1.0.0" + } +} +``` + +上述声明表示my\_bundle依赖可以被移除。如果想要移除my\_bundle,在上层依赖方需要使用excludes关键字来进行定义 + +``` +{ + "excludes": [ "my_bundle" ] +} +``` + +依赖被移除后,就不会参入组件的构建过程。只有标记为可选的依赖才能够被移除,强行移除未被标记的依赖会出现错误提示。 + +## 环境变量说明 + +组件在编译的过程中需要依赖系统提供的环境变量来自定义输出,链接所需二进制文件等等。这里提出的环境变量均指根据需求把所需变量注入脚本执行的上下文中。所以在脚本中可以直接获取到变量的值。下面介绍当前系统存在的几种环境变量。 + +全局变量由bundle.json中的envs属性来定义。整个组件中的依赖都可以获取到全局变量定义的值。 + +``` +{ + "envs": { + "compileEnv": "arm" + } +} +``` + +不同组件在引入依赖的过程中可以传入不同的参数,从而使依赖的编译可以满足当前组件的需求。依赖中定义的参数可以在对应依赖脚本执行的上下文中获取到。 + +``` +{ + "dependencies": { + "my-bundle": { + "version": "1.0.0", + "mode": "debug" + } + } +} +``` + +组件在链接二进制文件的时候,需要知道二进制文件在依赖中的路径,所以依赖的路径会作为环境变量传入编译组件中。 + +传入的环境变量的格式为DEP\_BundleName,BundleName为依赖的名称,例如 DEP\_first\_bundle。 + +依赖中可以定义标签,对引入的依赖进行分组。在脚本中可以根据标签,获得这一组依赖的路径。定义的标签以\#开头,具体定义的方式为: + +``` +{ + "dependencies": { + "#tool": { + "first-bundle": "1.0.0", + "second-bundle": "1.0.0" + }, + "#drivers": { + "xx-bundle": "1.0.0", + "yy-bundle": "1.0.0" + } + } +} +``` + +系统中存在两个固定环境变量: + +- DEP\_OHOS\_BUNDLES:表示ohos\_bundles文件夹所在的路径。 +- DEP\_BUNDLE\_BASE:表示最外层组件的路径。 + diff --git a/zh-cn/device-dev/bundles/bundles.md b/zh-cn/device-dev/bundles/bundles.md new file mode 100644 index 0000000000000000000000000000000000000000..9c560fca9d5b6ac9381ebc8dbc3a11de2eaba84b --- /dev/null +++ b/zh-cn/device-dev/bundles/bundles.md @@ -0,0 +1,9 @@ +# 组件开发指南 + +- **[组件开发规范](bundles-standard-rules.md)** + +- **[组件开发指南](bundles-guide.md)** + +- **[组件开发示例](bundles-demo.md)** + + diff --git "a/zh-cn/device-dev/bundles/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" "b/zh-cn/device-dev/bundles/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212-21.png" similarity index 100% rename from "zh-cn/device-dev/bundles/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" rename to "zh-cn/device-dev/bundles/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212-21.png" diff --git a/zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051452177.png b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051452177.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051452177.png rename to zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051452177.png diff --git a/zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051770876.png b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051770876.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/figures/zh-cn_image_0000001051770876.png rename to zh-cn/device-dev/bundles/figure/zh-cn_image_0000001051770876.png diff --git a/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001173313501.png b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001173313501.png new file mode 100644 index 0000000000000000000000000000000000000000..bc682a3dbd7e3de6a83a7292d9c6942c43909c98 Binary files /dev/null and b/zh-cn/device-dev/bundles/figure/zh-cn_image_0000001173313501.png differ diff --git "a/zh-cn/device-dev/bundles/figures/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" "b/zh-cn/device-dev/bundles/figure/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/bundles/figures/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" rename to "zh-cn/device-dev/bundles/figure/\347\241\254\344\273\266\347\216\257\345\242\203\350\277\236\346\216\245\345\205\263\347\263\273.png" diff --git "a/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\2660924.png" "b/zh-cn/device-dev/bundles/figure/\347\273\204\344\273\2660924.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/bundles/figures/\347\273\204\344\273\2660924.png" rename to "zh-cn/device-dev/bundles/figure/\347\273\204\344\273\2660924.png" diff --git "a/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\266\345\214\205\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.png" "b/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\266\345\214\205\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.png" deleted file mode 100755 index 1b936a2cbc95d3f9d7ddab0187305c3d0c486b0a..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/bundles/figures/\347\273\204\344\273\266\345\214\205\344\276\235\350\265\226\345\205\263\347\263\273\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/bundles/\345\207\206\345\244\207\345\267\245\344\275\234.md" "b/zh-cn/device-dev/bundles/\345\207\206\345\244\207\345\267\245\344\275\234.md" deleted file mode 100755 index 981e7e299a86af578bde9dfdb0e7807acfad0aa8..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\345\207\206\345\244\207\345\267\245\344\275\234.md" +++ /dev/null @@ -1,84 +0,0 @@ -# 准备工作 - -- [硬件要求](#section98535485518) -- [安装Node.js和hpm命令行工具](#section106591616205311) -- [更改hpm的配置(可选)](#section71821165412) -- [下载OpenHarmony代码](#section102338221707) -- [安装开发依赖的组件](#section19233183315020) - -## 硬件要求 - -- 准备设备开发的开发板(如Hi3861、Hi3516DV300、Hi3518EV300) -- 主机电脑(Windows工作台) -- Linux服务器 - -**图 1** 硬件环境连接关系 -![](figures/硬件环境连接关系.png "硬件环境连接关系") - -## 安装Node.js和hpm命令行工具 - -1. 安装Node.js。 - - 从官网下载并在本地安装Node.js. - - 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 - -2. 通过Node.js自带的npm安装hpm-cli命令行工具。执行以下命令: - - ``` - npm install -g @ohos/hpm-cli - ``` - -3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 - - ``` - hpm -V 或 hpm --version - ``` - -4. (可选)如果需要升级hpm版本,请执行如下命令: - - ``` - npm update -g @ohos/hpm-cli - ``` - - -## 更改hpm的配置(可选) - -安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: - -``` -hpm config -``` - -上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: - -``` -registry = https://hpm.harmonyos.com/hpm/registry/api # hpm注册中心地址,下载组件必须 -login = https://hpm.harmonyos.com/hpm/auth/pk # hpm处理登录地址,发布组件必须 -loginUser = {your-account} # 配置hpm登录账号,发布组件必须 -shellPath = C:\WINDOWS\System32\cmd.exe # hpm命令执行使用的shell -globalRepo = C:\Users\yourname\.global # 配置全局安装的组件存放路径 -http_proxy = http://your-proxy-server:port # 配置HTTP代理 -https_proxy = http://your-proxy-server:port # 配置HTTPS代理 -``` - -hpm-cli的命令介绍可以参考:[hpm操作命令](组件管理.md) - -## 下载OpenHarmony代码 - -参考[《源码获取》](../get-code/源码获取.md) - -## 安装开发依赖的组件 - -hpm包管理器将常用开发开发工具(如烧录,编译,压缩等)也发布成了组件。可以通过如下命令方式进行安装,执行完该命令后,系统会自动将开发依赖的工具下载安装,且这些组件只需全局安装一次。 - -``` -hpm i -g @ohos/llvm -hpm i -g @ohos/ninja -hpm i -g @ohos/gn -hpm i -g @ohos/hc_gen -hpm i -g @ohos/sysroot -``` - -这是一组开发工具的组件包(如包含gn,ninja等工具),有了这些开发态的组件,就可以进行常规的源码组件的开发了。 - diff --git "a/zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" "b/zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" deleted file mode 100755 index 00640e559945546ce8b17badb65e388934290751..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\345\217\221\350\241\214\347\211\210.md" +++ /dev/null @@ -1,56 +0,0 @@ -# 发行版 - -发行版通常是将一系列组件组合起来,成为编译可以运行的OpenHarmony解决方案镜像,里面包含了多个依赖的组件,以及脚本,用于描述如何完整编译、链接这些组件。 - -发行版本身通常不需要包含功能实现代码,仅包含bundle.json描述(设置publishAs为distribution)和一些编译脚本组成。 - -因为发行版编译的过程需要系统提供环境变量,所以发行版使用scripts脚本中内置的dist命令: - -``` -{ - "publishAs":"distribution", - "scripts": { - "dist": "script compile command" - } -} -``` - -编译执行使用如下命令: - -``` -hpm dist -``` - -重新定义一个发行版所具有的功能是一个复杂的过程,所以系统允许对发行版进行继承,从而在现有功能的基础上进行定制。继承发行版需要在bundle.json中定义base字段。 - -``` -{ - "base": { - "name": "dist_wifi_iot", - "version": "1.0.0" - } -} -``` - -上述定义表明当前组件继承自发行版组件dist-wifi-iot 1.0.0。 - -发行版由很多的依赖组件组成,通过bundle.json中的dependencies段来描述,有些依赖是必须的,有些依赖则是根据可以需求增加或删除的。bundle.json中名称前带有?的依赖表示可选依赖,继承它的发行版,可以移除掉该可选组件,再增加别的组件进行替换。 - -``` -{ - "dependencies": { - "?my_bundle": "1.0.0" - } -} -``` - -上述声明表示my\_bundle依赖可以被移除。如果想要移除my\_bundle,在上层依赖方需要使用excludes关键字来进行定义 - -``` -{ - "excludes": [ "my_bundle" ] -} -``` - -依赖被移除后,就不会参入组件的构建过程。只有标记为可选的依赖才能够被移除,强行移除未被标记的依赖会出现错误提示。 - diff --git "a/zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" "b/zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" deleted file mode 100755 index d49c4267cc6a997708e0018a61fded11f6bdb2bd..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\346\223\215\344\275\234\345\256\236\344\276\213.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 操作实例 - -环境准备好后,接下来本文以Hi3861平台为例,演示如何利用HPM进行组件的安装、编译和打包。 - -1. 执行以下命令,初始化安装目录(目录名可自行设置): - - ``` - mkdir test3861 - cd test3861 - hpm init -t dist - ``` - - 初始化成功则显示: - - ``` - Initialization finished. - ``` - -2. 安装wifi\_iot发行版。 - - ``` - hpm install @ohos/wifi_iot - ``` - - 安装成功则显示: - - ``` - Installed. - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >Hi3516平台采用下述命令: - >``` - >hpm install @ohos/ip_camera_hi3516dv300 - >``` - >Hi3518平台采用下述命令: - >``` - >hpm install @ohos/ip_camera_hi3518ev300 - >``` - -3. 编译打包 - - ``` - hpm dist - ``` - - 编译成功会显示: - - ``` - {{name}}: distribution building completed. - ``` - -4. 上述所有命令执行成功后,在 ./out 目录下会生成编译结果,开发者可以将编译结果烧录到对应的开发板上进行测试。 - diff --git "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" deleted file mode 100755 index 758ec2fb9fd0d18aa4df95bfc0355d7c307429ef..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 概述 - -本章节将简要介绍如何开发OpenHarmony组件和发行版,并通过命令行工具方式完成组件创建、开发、编译、烧录、调试等开发过程。 - -- 一个组件(bundle)通常和一个代码仓库对应,在代码的基础上增加bundle.json、README文件、LICENSE描述文件。 -- 一个发行版(distribution)是由多个组件构成的。发行版中集合了一个完整系统的各种组件(如驱动、内核、框架、应用),可以用于设备的烧录。 - -**表 1** 组件和发行版的差异对比 - - - - - - - - - - - - - - - - - - - - - - - - -

异同点

-

组件

-

发行版

-

应用场景

-

面向功能特性开发

-

面向系统开发

-

内容

-

功能或特性的实现代码或二进制库

-

依赖的组件清单及编译构建脚本

-

完整程度

-

操作系统的一部分

-

一个完整操作系统版本

-

编译后结果

-

组件包

-

系统镜像

-
- -**图 1** 组件和发行版的构成 - - -![](figures/组件0924.png) - diff --git "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" deleted file mode 100755 index 2eea128f92a994c5b63625ee824d4bf4abc14fc1..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,38 +0,0 @@ -# 概述 - -- [定义](#section177563344911) -- [组件划分原则](#section2487162541016) -- [组件依赖](#section185955409107) - -本文档将介绍组件的基本概念以及如何按照规范定义组件。 - -## 定义 - -OpenHarmony软件以组件\(bundle\)作为基本单元,从系统角度看,凡是运行在OpenHarmony上的软件都可以定义为组件;一般来讲,根据组件的应用范围,可以分为: - -- 板级组件:如board、arch、mcu这些与设备硬件相关的组件。 -- 系统组件:一组独立功能的集合,如内核、文件系统、框架等。 -- 应用组件:直接面向用户提供服务的应用\(如wifi\_iot,ip\_camera\)。 - -从形式上看,组件是为复用而生,一切可以复用的模块都可以定义为组件,可以分为: - -- 源代码 -- 二进制 -- 代码片段 -- 发行版 - -## 组件划分原则 - -原则上应尽可能划分为细颗粒度的组件,以满足最大限度的复用。主要考虑以下几点: - -- 独立性:组件的功能应该相对独立,支持独立编译,可以单独对外提供接口和服务; -- 耦合性:如果组件必须依赖其他的组件,才能对外提供服务,应考虑和被依赖的组件合并为一个组件。 -- 相关性:如果一组组件共同完成一项功能,且没有被其他组件依赖,未来也没有被依赖的可能,则可以考虑合并为一个组件。 - -## 组件依赖 - -组件的依赖关系分为两种:必选依赖和可选依赖。 - -- 必选依赖:是指组件A在完成某个功能时,必须引入组件B,调用B的接口或服务配合才能完成。称B为A的必选依赖。 -- 可选依赖:是在组件A在完成某个功能时,可以引入组件C,也可以引入组件D。C和D可以相互替换,称C和D为A的可选依赖。 - diff --git "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100755 index d4d5662f297230dcd45cd8706b239be7fada4e65..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,139 +0,0 @@ -# 环境准备 - -- [linux服务器](#section20979554791) -- [安装Node.js](#section9954105413153) -- [安装HPM](#section15937194904819) -- [安装python环境](#section1621819180417) -- [安装文件打包工具](#section77617165913) -- [安装SCons](#section20558439191516) - -## linux服务器 - -准备一台装有Ubuntu 16.04 及以上 64 位系统的linux服务器(hpm是支持windows的,但是目前OpenHarmony开源的Hi3861、Hi3516、Hi3518三个解决方案都只支持Ubuntu)。 - -将linux shell改为bash: - -``` -ls -l $(which sh) -# 如果指向的不是bash,则按以下方式修改: -# 方法一:执行以下命令,然后选择no -dpkg-reconfigure dash -# 方法二:先删除sh,再重新创建软连接 -rm -f /bin/sh -ln -s bash /bin/sh -``` - -## 安装Node.js - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果配置的源的nodejs版本太低,可以执行以下语句后再执行apt-get install: ->``` ->curl -L https://deb.nodesource.com/setup_12.x | bash ->``` - -推荐安装 Node.js 12.x (包含 npm 6.14.4)或更高版本(推荐 12.13.0+): - -``` -sudo apt-get install nodejs -sudo apt-get install npm -``` - -查看版本: - -``` -node --version # 查看nodejs版本 -npm --version # 查看npm版本 -``` - -## 安装HPM - -通过 Node.js 自带的 npm(使用默认的源 https://registry.npmjs.org/ )安装 hpm-cli 命令行工具: - -``` -npm install -g @ohos/hpm-cli -``` - -安装完hpm-cli命令行工具后,执行以下命令可以查看hpm配置: - -``` -hpm config -``` - -上述命令执行后将会显示hpm的默认配置,您可以根据自己的喜好对默认配置进行修改,以下是hpm的常用配置: - -``` -registry = https://hpm.harmonyos.com # hpm注册中心地址,下载组件必须 -strictSsl = true # 通过https连接时,是否需要校验证书 -http_proxy = http://your-proxy-server:port # 配置HTTP代理 -https_proxy = http://your-proxy-server:port # 配置HTTPS代理 -``` - -hpm-cli的命令介绍可以参考:[hpm操作命令](组件管理.md) - -## 安装python环境 - -需使用python3.7以上版本,采用以下命令进行安装: - -``` -sudo apt-get install python3.8 -sudo apt-get install python3-pip -sudo pip3 install setuptools -sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->上述方式适用Hi3518和Hi3516两种平台,针对Hi3861平台采用以下方式安装python环境: ->``` ->sudo apt-get install python3.8 ->sudo apt-get install python3-pip ->sudo pip3 install setuptools ->sudo pip3 install kconfiglib # 建议安装kconfiglib 13.2.0+版本 ->sudo pip3 install pycryptodome ->sudo pip3 install six --upgrade --ignore-installed six ->sudo pip3 install ecdsa ->``` - -如果当前系统中既存在python2又存在python3,参考以下方法将默认python修改为python3: - -``` -ll `which python` -rm /usr/bin/python -ln -s python3.8 /usr/bin/python -``` - -## 安装文件打包工具 - -采用以下命令进行安装: - -``` -which mkfs.vfat # 如果没找到,执行以下命令安装 -sudo apt-get install dosfstools -which mcopy # 如果没找到,执行以下命令安装 -sudo apt-get install mtools -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->Hi3518和Hi3516两种平台需要安装打包工具,Hi3861平台不需要。 - -## 安装SCons - -1. 打开Linux编译服务器终端。 -2. 运行如下命令,安装SCons安装包。 - - ``` - python3 -m pip install scons - ``` - -3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 - - ``` - scons -v - ``` - - **图 1** SCons安装成功界面,版本要求3.0.4以上 - ![](figures/SCons安装成功界面-版本要求3-0-4以上.png "SCons安装成功界面-版本要求3-0-4以上") - - ->![](public_sys-resources/icon-note.gif) **说明:** ->Hi3861平台需要安装SCons,Hi3518和Hi3516两种平台不需要。 - diff --git "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" "b/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" deleted file mode 100755 index 1ebf8fb99e32dc1c0394271881de47afba0d47a4..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\216\257\345\242\203\345\217\230\351\207\217\350\257\264\346\230\216.md" +++ /dev/null @@ -1,53 +0,0 @@ -# 环境变量说明 - -组件在编译的过程中需要依赖系统提供的环境变量来自定义输出,链接所需二进制文件等等。这里提出的环境变量均指根据需求把所需变量注入脚本执行的上下文中。所以在脚本中可以直接获取到变量的值。下面介绍当前系统存在的几种环境变量。全局变量 - -全局变量由bundle.json中的envs属性来定义。整个组件中的依赖都可以获取到全局变量定义的值。 - -``` -{ - "envs": { - "compileEnv": "arm" - } -} -``` - -不同组件在引入依赖的过程中可以传入不同的参数,从而使依赖的编译可以满足当前组件的需求。依赖中定义的参数可以在对应依赖脚本执行的上下文中获取到。 - -``` -{ - "dependencies": { - "my-bundle": { - "version": "1.0.0", - "mode": "debug" - } - } -} -``` - -组件在链接二进制文件的时候,需要知道二进制文件在依赖中的路径,所以依赖的路径会作为环境变量传入编译组件中。 - -传入的环境变量的格式为DEP\_BundleName,BundleName为依赖的名称,例如 DEP\_first\_bundle。 - -依赖中可以定义标签,对引入的依赖进行分组。在脚本中可以根据标签,获得这一组依赖的路径。定义的标签以\#开头,具体定义的方式为: - -``` -{ - "dependencies": { - "#tool": { - "first-bundle": "1.0.0", - "second-bundle": "1.0.0" - }, - "#drivers": { - "xx-bundle": "1.0.0", - "yy-bundle": "1.0.0" - } - } -} -``` - -系统中存在两个固定环境变量: - -- DEP\_OHOS\_BUNDLES:表示ohos\_bundles文件夹所在的路径。 -- DEP\_BUNDLE\_BASE:表示最外层组件的路径。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" deleted file mode 100755 index 292c88d6d2cc329d255c12fe1d118009d84ee82d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221.md" +++ /dev/null @@ -1,241 +0,0 @@ -# 组件开发 - -- [创建OpenHarmony组件](#section1976410130540) -- [新建组件](#section717481119145) -- [改造组件](#section102861955201410) -- [从模板创建组件](#section15882846181510) -- [编译组件](#section136732148541) -- [定义编译脚本](#section10274147111610) -- [执行编译](#section879301916172) -- [定义发行版](#section413216495619) -- [定义脚本](#section11503171219190) -- [发行](#section4694125521912) -- [烧录](#section1746331545413) -- [运行调试](#section6742131615549) - -## 创建OpenHarmony组件 - -创建OpenHarmony组件有如下几种方式: - -- 从头开发一个全新的组件。 -- 将一个现有的非组件的代码改造成组件。 - -- hpm提供了一些组件模板方便快速创建组件。 - -## 新建组件 - -通常情况下,[HPM网站](https://hpm.harmonyOS.com)上能找到您开发常用的组件,如果现有的组件不能完全满足开发,这时可以自己动手开发一个组件。 - -如果您愿意,可以将组件发布到HPM的仓库中供其他用户使用。假设要在D:/source目录下新建一个全新的组件my-bundle: - -可以使用hpm init 创建该组件的脚手架代码,例如,进入D:/source目录,执行如下命令: - -``` -hpm init -t default -d demo my-bundle -``` - -会在 source 目录下生成如下文件: - -``` -mybundle -├── bundle.json # 组件元数据描述文件 -├── example # 测试组件功能的示例 -│ └── main.c -├── include # 组件的内部头文件 -│ └── mybundle.h -├── README.md # 组件的简要说明 -└── src # 组件的源代码 - └─ mybundle.c -``` - -接下来根据您的业务需要,实现组件内部的功能代码,完成代码开发后,通过git将代码(包括bundle.json文件)提交到组件代码托管仓库中(如gitee)。 - -## 改造组件 - -如果您已经有了代码,只是还不满足OpenHarmony的组件结构,需要改造成为hpm的组件包,只需要在当前要改造的代码目录下(例如mybundle2),执行如下命令,会提示您输入组件名称和版本。 - -``` -hpm init -``` - -1. 输入名称后回车(如mybundle2)。 -2. 输入版本后(如1.0.0)回车,在当前组件目录下会生成一个bundle.json文件。 -3. 打开bundle.json文件再添加其他的描述,这时候他已经是一个具备可发布的组件了。 - - ``` - $ hpm init - Your bundle will be created in dirname E:\demo\mybundle2 - ? bundle name mybundel2 - ? version 1.0.0 - Init finished! - ``` - - -1. 打开bundle.json文件修改其他信息(如作者,代码仓库,代码目录,命令脚本,依赖组件等),如下: - - ``` - { - "name": "mybundle2", - "version": "1.0.0", - "publishAs": "source", - "dirs":{ - ".":[ - "README.md" - ], - "src":[ - "test.c" - ], - "header":[ - "header/test.h" - ], - "src/common":[ - "src/common/foobar.txt" - ] - }, - "scripts": { - "build": "make -${args}" - }, - "dependencies": { - "@ohos/cjson": "^1.0.0", - "@ohos/": "^1.2.0" - } - } - ``` - - -## 从模板创建组件 - -hpm 除了提供了默认模板 default和simple两个简单的模板之外,其他模板均存储在服务器端。 - -可以使用命令hpm search -t template 从服务器端搜索模板。 - -![](figures/zh-cn_image_0000001051452177.png) - -根据description简要中的描述,找到适合的模板,基于模板可以快速创建一个组件的脚手架,执行如下初始化命令(指定-t -d 参数)。 - -``` -hpm init -t {templatename} -d dir name -``` - -- \{templatename\} :指的是模板名称。 -- -d 后面的参数dir:是要创建的组件所存放的路径。 -- name:为要创建的组件名称。 - -## 编译组件 - -完成代码开发后,需要对组件进行编译。hpm提供了命令集成的能力,您可以选择任意的适合项目的编译工具(如make,gcc,gn等等)。只需在当前项目的bundle.json文件中定义scripts脚本中的build命令,就可以通过执行hpm build执行编译。 - -## 定义编译脚本 - -以编译一个app目录下helloworld可执行文件为例: - -``` -app -├── BUILD.gn -├── include -│ └── helloworld.h -└── src - └── helloworld.c -``` - -在helloworld.c同级目录下新建一个BUILD.gn - -``` -touch BUILD.gn -vim BUILD.gn -``` - -以下是BUILD.gn的样例,仅供参考 - -``` -executable("hello_world") { - sources = [ - "src/helloworld.c" - ] - - include_dirs = [ - "include" - ] -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->- “executable”是gn内置模板,可以用“gn help executable ”查看使用方法。 ->- “sources ”是源码路径,“include\_dirs ”是头文件路径。 - -## 执行编译 - -在当前文件夹下,执行编译命令: - -``` -hpm build -``` - -在完成一系列的编译动作后,显示build succeed。检查编译的输出结果: - -![](figures/zh-cn_image_0000001051770876.png) - -## 定义发行版 - -发行版是将一组组件组合起来的,编译生成可以运行的OpenHarmony解决方案,里面包含了较多依赖的组件,以及以脚本形式描述如何完整编译、链接这些组件。 - -## 定义脚本 - -bundle.json中定义 - -``` -{ -"name": "my_dist", -"version": "1.0.0", -"publishAs": "distribution", -"scripts": { -"dist": "make -${args}" - }, -"base": { -"name": "dist-bundle", -"version": "1.0.0" - }, -"envs": { -"args": "x86" - }, -"dependencies": { -} -} -``` - -## 发行 - -在当前发行版根目录下,执行如下命令。 - -``` -hpm dist -``` - -hpm-cli工具会自动执行编译,打包操作,将根据scripts定义的dist脚本生成镜像文件,如: - -``` -out -|-xxdist.img -|-xx.file -``` - -## 烧录 - -发行版的编译结果可以烧录到设备中运行,例如使用hiburn工具进行烧录。在发行版的bundle.json文件配置烧录参数。 - -``` -"scripts": { -"flash": "{$DEP_HIBURN}/hiburn" -}, -``` - -配置烧录相关的参数(参考烧录工具的说明进行配置)。 - -``` -hpm run flash -``` - -## 运行调试 - -将发行版的镜像烧录到设备中后,就可以启动运行调试了,由于运行调试和具体的开发板和IDE调试工具相关,此处不再详细描述。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" deleted file mode 100755 index cb1868b0b4463c569d8e022005d52487f9e05f29..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 组件开发指南 - -- **[概述](概述-0.md)** - -- **[准备工作](准备工作.md)** - -- **[组件开发](组件开发.md)** - - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index d3e13752118de3f3e106ab01950b786e0ed3e757..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 组件开发示例 - -- **[HPM介绍](HPM介绍.md)** - -- **[环境准备](环境准备.md)** - -- **[操作实例](操作实例.md)** - - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" deleted file mode 100755 index 4205b8d5383cd8baea3a4ce99710e0715682190d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\345\274\200\345\217\221\350\247\204\350\214\203.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 组件开发规范 - -- **[概述](概述.md)** - -- **[组件构成](组件构成.md)** - -- **[组件管理](组件管理.md)** - -- **[组件版本](组件版本.md)** - -- **[发行版](发行版.md)** - -- **[环境变量说明](环境变量说明.md)** - - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" deleted file mode 100755 index 98e4e2dd608c2fb78374ae2c9b8ce57748499723..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\346\236\204\346\210\220.md" +++ /dev/null @@ -1,99 +0,0 @@ -# 组件构成 - -- [代码文件](#section101483489110) -- [说明文件](#section10519101221211) -- [元数据描述文件](#section45511827111211) - -一个组件包一般包含如下内容: - -- 组件包的代码或库(src目录下的代码文件) -- ohos\_bundles文件夹(存放依赖的组件,安装组件时自动生成,无需提交到代码库) -- 组件包的说明文件\(README.md\) -- 组件包元数据声明文件\(bundle.json\) -- 开源许可文件\(LICENSE\) - - ``` - my-bundle - |_ohos_bundles - |_src - |_bundle.json - |_README.md - |_LICENSE - ``` - - -## 代码文件 - -组件的代码文件和普通的代码目录没有差异。但要注意的是,组件中对外暴露的接口(头文件),会被其他组件所引用,需要单独在bundle.json的dirs中声明。 - -## 说明文件 - -README.md,为markdown格式的描述关于组件自述说明文件。([语法参考](https://www.markdownguide.org/getting-started/)\) - -为了帮助他人在hpm上找到该组件,并更方便的使用它,在组件的根目录中包含一个README文件。 - -README文件可能包括如何安装,配置和使用组件包中的实例代码说明,以及可能会对用户有所帮助的任何其他信息。 - -每个组件的自述文件将显示在hpm系统的组件详情页面的描述中。 - -## 元数据描述文件 - -bundle.json文件是对当前组件的元数据描述,每个组件中必须包含一个bundle.json文件。 - -``` -{ - "name": "@myorg/demo-bundle", - "version": "1.0.0", - "license": "MIT", - "description": "bundle description", - "keywords": ["hos"], - "tags": ["applications", "drivers"], - "author": {"name":"","email":"","url":""}, - "contributors":[{"name":"","email":"","url":""},{"name":"","email":"","url":""}], - "homepage": "http://www.foo.bar.com", - "repository": "https://git@gitee.com:foo/bar.git", - "publishAs": "source", - "dirs": { - "src": ["src/**/*.c"], - "headers": ["headers/**/*.h"], - "bin": ["bin/**/*.o"] - }, - "scripts": { - "build": "make" - }, - "envs": {}, - "ohos": { - "os": "2.0.0", - "board": "hi3516", - "kernel": "liteos-a" - }, - "rom": "10240", - "ram": "1024", - "dependencies": { - "@myorg/net":"1.0.0" - } -} -``` - -bundle.json文件具有如下功能: - -- name:定义组件的名称,放到组织下, 以@开头,/分割,如:@myorg/mybundle - -- version:定义组件版本号,如1.0.0,需满足semver的标准。 - -- description:一句话对组件进行简要的描述。 -- dependencies:定义组件的依赖组件。 - -- envs: 定义组件编译时所需要的参数,包括全局参数以及依赖所需的参数。 - -- scripts:定义在当前组件下能够执行的命令(如编译,构建,测试,烧录等)。 - -- publishAs:定义组件的发布类型(source:源码,binary:二进制,distribution:发行版,code-segment:代码片段)。 - -- dirs:定义发布时打包的目录结构(如头文件)。 - -- ram&rom:统计相关信息:预计占用ROM和RAM信息。 -- ohos:描述OpenHarmony系统版本、开发板及内核的匹配关系(多个请用英文逗号的“,”分割)。 -- 定义其他扩展信息:作者,主页,代码仓库,许可协议,标签,关键字。 -- 对于发行版类型,还有个base,可以定义继承自的发行版。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" deleted file mode 100755 index 55647fdcb7093589938272e874379867ef00ffea..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\211\210\346\234\254.md" +++ /dev/null @@ -1,23 +0,0 @@ -# 组件版本 - -- [版本号命名规范](#section16893854141310) -- [版本发布](#section43401320171420) - -## 版本号命名规范 - -名称需要为全小写字母,中间可以使用中划线或者下划线分隔。比如 "bundle", "my\_bundle"。 - -版本号的格式为 "主版本号.次版本号.修订号" 或 "主版本号.次版本号.修订号-先行版本号",比如 "1.0.0", "1.0.0-beta",详细规格可以参考 [https://semver.org](https://semver.org/)。 - -## 版本发布 - -为了使组件能被其他开发者使用,组件需要上传到远端仓库。组件上传使用如下命令: - -``` -hpm publish -``` - -命令执行以后,系统会对的整个依赖关系进行检查,下载缺失依赖组件。依赖检查完成后,如果发布类型为binary,系统会对整个组件进行编译,生成二进制文件,然后打包上传。如果使其他上传类型,则直接根据定义的打包规则进行打包,然后上传。 - -注意:发布组件需要用户账号登录,需要先拥有hpm的系统账号后,并注册组织,申请组织认证通过后,才拥有发布的权限。 - diff --git "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" "b/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" deleted file mode 100755 index 852d9929b0961be9d557c496806167e5301f0ec2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/bundles/\347\273\204\344\273\266\347\256\241\347\220\206.md" +++ /dev/null @@ -1,237 +0,0 @@ -# 组件管理 - -- [依赖关系](#section12657593129) -- [hpm操作命令参考](#section1258849181312) - -## 依赖关系 - -生成基础bundle.json以后,需要继续添加组件依赖来实现更复杂的功能。此时需要知道所依赖组件的名称和版本号,并且把它们定义在bundle.json里面的dependencies字段中。 - -``` -{ - "name": "my-bundle", - "version": "1.0.0", - "dependencies": { - "net": "1.0.0" - } -} -``` - -上述示例中,my-bundle组件依赖于net 1.0.0组件。在全局安装了 hpm CLI 工具之后,执行如下命令可以从远端仓库获取到依赖: - -``` -hpm install -``` - -依赖获取以后,会保存到当前组件根目录下到ohos\_bundles文件夹中。组件以及依赖之间会形成一个依赖关系的树状结构。全局安装了 hpm CLI 工具之后,在组件根目录下执行如下命令: - -``` -username@server MINGW64 /f/showcase/demo/demo -$ hpm list -+--demo@1.0.0 -| +--@huawei/media@1.0.2 -| +--@demo/sport_hi3518ev300_liteos_a@1.0.0 -| | +--@demo/app@4.0.1 -| | | +--@demo/build@4.0.1 -| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 -| | +--@demo/liteos_a@4.0.0 -| | | +--@demo/third_party_fatfs@4.0.0 -| | | +--@demo/arm_harmonyeabi_gcc@4.0.0 -| | +--@demo/init@4.0.0 -| | +--@demo/dist_tools@4.0.0 -``` - -还可以使用图的形式,来查看当前组件的依赖关系,执行如下命令: - -``` -hpm dependencies -``` - -在当前目录下会生成deps\_visual文件夹,里面包含两个文件,deps.html 和 deps-data.js。在浏览器中打开 deps.html 文件,就可以看到依赖关系的图形化展示\(如下图\)。 - -根据不同的依赖类型,图形结点呈现出不同的颜色。鼠标悬浮在结点上,可以查看当前结点的状态。 - -**图 1** 组件包依赖关系图 -![](figures/组件包依赖关系图.png "组件包依赖关系图") - -## hpm操作命令参考 - -组件的全生命周期管理,可以通过hpm命令工具进行操作,hpm的操作命令如下(详细帮助可以执行 hpm -h学习): - -**表 1** hpm操作命令 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

命令类别

-

命令行

-

含义说明

-

版本查询

-

hpm -V 或 hpm --version

-

查看hpm-cli 版本号。

-

帮助查询

-

hpm -h 或 hpm --version

-

查看命令列表及帮助。

-

hpm -h

-

查看命令帮助。

-

创建

-

-

hpm init bundle

-

创建组件工程。

-

hpm init -t template

-

根据模板创建脚手架工程。

-

安装

-

-

hpm install 或hpm i

-

安装bundle.json中依赖的组件。

-

hpm install bundle@version

-

安装指定组件版本。

-

卸载

-

-

hpm uninstall bundle

-

删除depedencies依赖的组件。

-

hpm remove 或hpm rm bundlename

-

删除depedencies依赖的组件。

-

查看

-

-

hpm list 或者 hpm ls

-

显示当前组件/发行版所有的组件树。

-

hpm dependencies

-

生成当前组件/发行版依赖关系图(html格式)。

-

搜索

-

hpm search name

-

搜索组件,--json,可以以json格式输出 -type 可以设置搜索组件的类型,包括bundle,distribution,code-segment三种。

-

设置hpm配置项

-

hpm config set key value

-

设置配置值,如服务器地址,网络代理。

-

hpm config delete key

-

删除配置。

-

更新

-

-

hpm update

-

更新当前组件依赖的组件的版本。

-

hpm check-update

-

检查依赖的组件版本是否有更新。

-

编译

-

-

hpm build

-

编译组件/发行版。

-

hpm dist

-

发行版打包(依赖bundle.json的scripts中的dist脚本)。

-

打包

-

hpm pack

-

本地组件打包依赖。

-

烧录

-

hpm run flash

-

烧录固件(依赖bundle.json的scripts中的flash脚本)。

-

发布

-

hpm publish

-

发布组件,发布的组件在仓库中必须唯一,且版本唯一(需要账号登录)。

-

执行扩展命令

-

hpm run

-

执行bundle.json文件中定义的scripts脚本命令,支持多个命令可用 && 连接。

-

生成秘钥

-

hpm gen-keys

-

生成公钥/私钥对,将公钥配置到HPM服务端,可以实现hpm-cli 免密登录,发布组件。

-

生成第三方开源说明

-

hpm gen-notice

-

根据每个组件的说明,生成一份合并后的第三方开源说明的合并文件。

-
- - - - -
- diff --git a/zh-cn/device-dev/driver/GPIO.md b/zh-cn/device-dev/driver/GPIO.md deleted file mode 100755 index afffef57ab689bd2220b0cc24b3323089b0e2d52..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/GPIO.md +++ /dev/null @@ -1,9 +0,0 @@ -# GPIO - -- **[GPIO概述](GPIO概述.md)** - -- **[GPIO使用指导](GPIO使用指导.md)** - -- **[GPIO使用实例](GPIO使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 86231b7af28d913333f5ee3c7440ce6c7551d4a7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,79 +0,0 @@ -# GPIO使用实例 - -本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。 - -首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300某开发板,GPIO管脚选择GPIO10\_3,换算成GPIO号为83。 - -读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。 - -``` -#include "gpio_if.h" -#include "hdf_log.h" -#include "osal_irq.h" -#include "osal_time.h" - -static uint32_t g_irqCnt; - -/* 中断服务函数*/ -static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data) -{ - HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data); - g_irqCnt++; /* 如果中断服务函数触发执行,则将全局中断计数加1 */ - return GpioDisableIrq(gpio); -} - -/* 测试用例函数 */ -static int32_t TestCaseGpioIrqEdge(void) -{ - int32_t ret; - uint16_t valRead; - uint16_t mode; - uint16_t gpio = 83; /* 待测试的GPIO管脚号 */ - uint32_t timeout; - - /* 将管脚方向设置为输出 */ - ret = GpioSetDir(gpio, GPIO_DIR_OUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret); - return ret; - } - - /* 先禁止该管脚中断 */ - ret = GpioDisableIrq(gpio); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret); - return ret; - } - - /* 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发 */ - mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; - HDF_LOGE("%s: mode:%0x\n", __func__, mode); - ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret); - return ret; - } - - /* 使能此管脚中断 */ - ret = GpioEnableIrq(gpio); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret); - (void)GpioUnSetIrq(gpio); - return ret; - } - - g_irqCnt = 0; /* 清除全局计数器 */ - timeout = 0; /* 等待时间清零 */ - /* 等待此管脚中断服务函数触发,等待超时时间为1000毫秒 */ - while (g_irqCnt <= 0 && timeout < 1000) { - (void)GpioRead(gpio, &valRead); - (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); - HDF_LOGE("%s: wait irq timeout:%u\n", __func__, timeout); - OsalMDelay(200); /* wait for irq trigger */ - timeout += 200; - } - (void)GpioUnSetIrq(gpio); - return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; -} -``` - diff --git "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 1bc136ee21147a7eca55b507cd96dfa8ab5fe583..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/GPIO\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,395 +0,0 @@ -# GPIO使用指导 - -- [使用流程](#section1583613406410) -- [确定GPIO管脚号](#section135943361443) -- [使用API操作GPIO管脚](#section69151114115315) - -## 使用流程 - -GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig1399416053717)所示。 - -**图 1** GPIO使用流程图 - - -![](figures/zh-cn_image_0000001057342245.png) - -## 确定GPIO管脚号 - -不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。 - -- Hi3516DV300 - - 控制器管理12组GPIO管脚,每组8个。 - - GPIO号 = GPIO组索引 \(0\~11\) \* 每组GPIO管脚数\(8\) + 组内偏移 - - 举例:GPIO10\_3的GPIO号 = 10 \* 8 + 3 = 83 - -- Hi3518EV300 - - 控制器管理10组GPIO管脚,每组10个。 - - GPIO号 = GPIO组索引 \(0\~9\) \* 每组GPIO管脚数\(10\) + 组内偏移 - - 举例:GPIO7\_3的GPIO管脚号 = 7 \* 10 + 3 = 73 - - -## 使用API操作GPIO管脚 - -- 设置GPIO管脚方向 - - 在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向: - - int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\); - - **表 1** GpioSetDir参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

待设置的GPIO管脚号

-

dir

-

待设置的方向值

-

返回值

-

返回值描述

-

0

-

设置成功

-

负数

-

设置失败

-
- -- 读写GPIO管脚 - - 如果要读取一个GPIO管脚电平,通过以下函数完成: - - int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\); - - **表 2** GpioRead参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

待读取的GPIO管脚号

-

val

-

接收读取电平值的指针

-

返回值

-

返回值描述

-

0

-

读取成功

-

负数

-

读取失败

-
- - 如果要向GPIO管脚写入电平值,通过以下函数完成: - - int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\); - - **表 3** GpioWrite参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

待写入的GPIO管脚号

-

val

-

待写入的电平值

-

返回值

-

返回值描述

-

0

-

写入成功

-

负数

-

写入失败

-
- - 示例代码: - - ``` - int32_t ret; - uint16_t val; - /* 将3号GPIO管脚配置为输出 */ - ret = GpioSetDir(3, GPIO_DIR_OUT); - if (ret != 0) { - HDF_LOGE("GpioSerDir: failed, ret %d\n", ret); - return; - } - /* 向3号GPIO管脚写入低电平GPIO_VAL_LOW */ - ret = GpioWrite(3, GPIO_VAL_LOW); - if (ret != 0) { - HDF_LOGE("GpioWrite: failed, ret %d\n", ret); - return; - } - /* 将6号GPIO管脚配置为输入 */ - ret = GpioSetDir(6, GPIO_DIR_IN); - if (ret != 0) { - HDF_LOGE("GpioSetDir: failed, ret %d\n", ret); - return; - } - /* 读取6号GPIO管脚的电平值 */ - ret = GpioRead(6, &val); - ``` - - -- 设置GPIO中断 - - 如果要为一个GPIO管脚设置中断响应程序,使用如下函数: - - int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\); - - **表 4** GpioSetIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

GPIO管脚号

-

mode

-

中断触发模式

-

func

-

中断服务程序

-

arg

-

传递给中断服务程序的入参

-

返回值

-

返回值描述

-

0

-

设置成功

-

负数

-

设置失败

-
- - >![](public_sys-resources/icon-caution.gif) **注意:** - >同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。 - - 当不再需要响应中断服务函数时,使用如下函数取消中断设置: - - int32\_t GpioUnSetIrq\(uint16\_t gpio\); - - **表 5** GpioUnSetIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

GPIO管脚号

-

返回值

-

返回值描述

-

0

-

取消成功

-

负数

-

取消失败

-
- - 在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断: - - int32\_t GpioEnableIrq\(uint16\_t gpio\); - - **表 6** GpioEnableIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

GPIO管脚号

-

返回值

-

返回值描述

-

0

-

使能成功

-

负数

-

使能失败

-
- - >![](public_sys-resources/icon-caution.gif) **注意:** - >必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。 - - 如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断: - - int32\_t GpioDisableIrq\(uint16\_t gpio\); - - **表 7** GpioDisableIrq参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

gpio

-

GPIO管脚号

-

返回值

-

返回值描述

-

0

-

禁止成功

-

负数

-

禁止失败

-
- - 示例代码: - - ``` - /* 中断服务函数 - */ - int32_t MyCallBackFunc(uint16_t gpio, void *data) - { - HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data); - return 0; - } - - int32_t ret; - /* 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发 */ - ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL); - if (ret != 0) { - HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret); - return; - } - - /* 使能3号GPIO管脚中断 */ - ret = GpioEnableIrq(3); - if (ret != 0) { - HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret); - return; - } - - /* 禁止3号GPIO管脚中断 */ - ret = GpioDisableIrq(3); - if (ret != 0) { - HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret); - return; - } - - /* 取消3号GPIO管脚中断服务程序 */ - ret = GpioUnSetIrq(3); - if (ret != 0) { - HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret); - return; - } - ``` - - diff --git "a/zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" deleted file mode 100755 index 1c4bcfc9c060718e31a5dd7bf267513fdb3afb0d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/GPIO\346\246\202\350\277\260.md" +++ /dev/null @@ -1,82 +0,0 @@ -# GPIO概述 - -- [简介](#section15318165672215) -- [接口说明](#section18977142162418) - -## 简介 - -GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。 - -GPIO接口定义了操作GPIO管脚的标准方法集合,包括: - -- 设置管脚方向: 方向可以是输入或者输出\(暂不支持高阻态\) - -- 读写管脚电平值: 电平值可以是低电平或高电平 -- 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式 -- 使能和禁止管脚中断:禁止或使能管脚中断 - -## 接口说明 - -**表 1** GPIO驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

GPIO读写

-

GpioRead

-

读管脚电平值

-

GpioWrite

-

写管脚电平值

-

GPIO配置

-

GpioSetDir

-

设置管脚方向

-

GpioGetDir

-

获取管脚方向

-

GPIO中断设置

-

GpioSetIrq

-

设置管脚对应的中断服务函数

-

GpioUnSetIrq

-

取消管脚对应的中断服务函数

-

GpioEnableIrq

-

使能管脚中断

-

GpioDisableIrq

-

禁止管脚中断

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git "a/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index f9b3ca1aca4612cba98dd4d788645e0704f59850..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,238 +0,0 @@ -# HDF开发实例 - -- [添加配置](#section27261067111) -- [编写驱动代码](#section177988005) -- [编写用户程序和驱动交互代码](#section6205173816412) - -下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。 - -## 添加配置 - -在HDF框架的配置文件(例如vendor/hisilicon/xxx/config/device\_info)中添加该驱动的配置信息,如下所示: - -``` -root { - device_info { - match_attr = "hdf_manager"; - template host { - hostName = ""; - priority = 100; - template device { - template deviceNode { - policy = 0; - priority = 100; - preload = 0; - permission = 0664; - moduleName = ""; - serviceName = ""; - deviceMatchAttr = ""; - } - } - } - sample_host :: host { - hostName = "sample_host"; - sample_device :: device { - device0 :: deviceNode { - policy = 2; - priority = 100; - preload = 1; - permission = 0664; - moduleName = "sample_driver"; - serviceName = "sample_service"; - } - } - } - } -} -``` - -## 编写驱动代码 - -基于HDF框架编写的sample驱动代码如下: - -``` -#include -#include -#include -#include "hdf_log.h" -#include "hdf_base.h" -#include "hdf_device_desc.h" - -#define HDF_LOG_TAG "sample_driver" - -#define SAMPLE_WRITE_READ 123 - -int32_t HdfSampleDriverDispatch( - struct HdfDeviceObject *deviceObject, int id, struct HdfSBuf *data, struct HdfSBuf *reply) -{ - HDF_LOGE("%s: received cmd %d", __func__, id); - if (id == SAMPLE_WRITE_READ) { - const char *readData = HdfSbufReadString(data); - if (readData != NULL) { - HDF_LOGE("%s: read data is: %s", __func__, readData); - } - if (!HdfSbufWriteInt32(reply, INT32_MAX)) { - HDF_LOGE("%s: reply int32 fail", __func__); - } - return HdfDeviceSendEvent(deviceObject, id, data); - } - return HDF_FAILURE; -} - -void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) -{ - // release resources here - return; -} - -int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) -{ - if (deviceObject == NULL) { - return HDF_FAILURE; - } - static struct IDeviceIoService testService = { - .Dispatch = HdfSampleDriverDispatch, - }; - deviceObject->service = &testService; - return HDF_SUCCESS; -} - -int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) -{ - if (deviceObject == NULL) { - HDF_LOGE("%s::ptr is null!", __func__); - return HDF_FAILURE; - } - HDF_LOGE("Sample driver Init success"); - return HDF_SUCCESS; -} - -struct HdfDriverEntry g_sampleDriverEntry = { - .moduleVersion = 1, - .moduleName = "sample_driver", - .Bind = HdfSampleDriverBind, - .Init = HdfSampleDriverInit, - .Release = HdfSampleDriverRelease, -}; - -HDF_INIT(g_sampleDriverEntry); -``` - -## 编写用户程序和驱动交互代码 - -基于HDF框架编写的用户态程序和驱动交互的代码如下: - -``` -#include -#include -#include -#include -#include "hdf_log.h" -#include "hdf_sbuf.h" -#include "hdf_io_service_if.h" - -#define HDF_LOG_TAG "sample_test" -#define SAMPLE_SERVICE_NAME "sample_service" - -#define SAMPLE_WRITE_READ 123 - -int g_replyFlag = 0; - -static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) -{ - const char *string = HdfSbufReadString(data); - if (string == NULL) { - HDF_LOGE("fail to read string in event data"); - g_replyFlag = 1; - return HDF_FAILURE; - } - HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string); - g_replyFlag = 1; - return HDF_SUCCESS; -} - -static int SendEvent(struct HdfIoService *serv, char *eventData) -{ - int ret = 0; - struct HdfSBuf *data = HdfSBufObtainDefaultSize(); - if (data == NULL) { - HDF_LOGE("fail to obtain sbuf data"); - return 1; - } - - struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); - if (reply == NULL) { - HDF_LOGE("fail to obtain sbuf reply"); - ret = HDF_DEV_ERR_NO_MEMORY; - goto out; - } - - if (!HdfSbufWriteString(data, eventData)) { - HDF_LOGE("fail to write sbuf"); - ret = HDF_FAILURE; - goto out; - } - - ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); - if (ret != HDF_SUCCESS) { - HDF_LOGE("fail to send service call"); - goto out; - } - - int replyData = 0; - if (!HdfSbufReadInt32(reply, &replyData)) { - HDF_LOGE("fail to get service call reply"); - ret = HDF_ERR_INVALID_OBJECT; - goto out; - } - HDF_LOGE("Get reply is: %d", replyData); -out: - HdfSBufRecycle(data); - HdfSBufRecycle(reply); - return ret; -} - -int main() -{ - char *sendData = "default event info"; - struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME); - if (serv == NULL) { - HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME); - return HDF_FAILURE; - } - - static struct HdfDevEventlistener listener = { - .callBack = OnDevEventReceived, - .priv ="Service0" - }; - - if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) { - HDF_LOGE("fail to register event listener"); - return HDF_FAILURE; - } - if (SendEvent(serv, sendData)) { - HDF_LOGE("fail to send event"); - return HDF_FAILURE; - } - - while (g_replyFlag == 0) { - sleep(1); - } - - if (HdfDeviceUnregisterEventListener(serv, &listener)) { - HDF_LOGE("fail to unregister listener"); - return HDF_FAILURE; - } - - HdfIoServiceRecycle(serv); - return HDF_SUCCESS; -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项: ->deps = \[ ->"//drivers/adapter/lite/uhdf/manager:hdf\_core", ->"//drivers/adapter/lite/uhdf/posix:hdf\_posix\_osal", ->\] - diff --git "a/zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" "b/zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" deleted file mode 100755 index fb6f985a6e5516f1520061a7923ee782a26fc9a0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/HDF\351\251\261\345\212\250\346\241\206\346\236\266.md" +++ /dev/null @@ -1,15 +0,0 @@ -# HDF驱动框架 - -- **[HDF开发概述](HDF开发概述.md)** - -- **[驱动开发](驱动开发.md)** - -- **[驱动服务管理](驱动服务管理.md)** - -- **[驱动消息机制管理](驱动消息机制管理.md)** - -- **[配置管理](配置管理.md)** - -- **[HDF开发实例](HDF开发实例.md)** - - diff --git a/zh-cn/device-dev/driver/I2C.md b/zh-cn/device-dev/driver/I2C.md deleted file mode 100755 index 5bc8c5bf3ce065ab72f19260fe0ab8ca622c0cd8..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/I2C.md +++ /dev/null @@ -1,9 +0,0 @@ -# I2C - -- **[I2C概述](I2C概述.md)** - -- **[I2C使用指导](I2C使用指导.md)** - -- **[I2C使用实例](I2C使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index a75da59b1b8b225230df1091d4335afbd8240b1d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,192 +0,0 @@ -# I2C使用实例 - -本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 - -本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下: - -- SOC:hi3516dv300。 - -- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。 - -- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。 - -本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 - -示例如下: - -``` -#include "i2c_if.h" /* I2C标准接口头文件 */ -#include "gpio_if.h" /* GPIO标准接口头文件 */ -#include "hdf_log.h" /* 标准日志打印头文件 */ -#include "osal_io.h" /* 标准IO读写接口头文件 */ -#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ - -/* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */ -struct TpI2cDevice { - uint16_t rstGpio; /* 复位管脚 */ - uint16_t busId; /* I2C总线号 */ - uint16_t addr; /* I2C设备地址 */ - uint16_t regLen; /* 寄存器字节宽度 */ - DevHandle i2cHandle; /* I2C控制器句柄 */ -}; - -/* I2C管脚io配置,需要查阅SOC寄存器手册 */ -#define I2C3_DATA_REG_ADDR 0x112f008c /* 3号I2C控制器SDA管脚配置寄存器地址 */ -#define I2C3_CLK_REG_ADDR 0x112f0090 /* 3号I2C控制器SCL管脚配置寄存器地址 */ -#define I2C_REG_CFG 0x5f1 /* 3号I2C控制器SDA及SCL管脚配置值 */ - -static void TpSocIoCfg(void) -{ - /* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */ - OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR)); - OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR)); -} - -/* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20ms, 完成复位动作 */ -static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice) -{ - int32_t ret; - - /* 设置复位管脚方向为输出 */ - ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret); - return ret; - } - - ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret); - return ret; - } - OsalMSleep(20); - - ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst low fail!:%d", __func__, ret); - return ret; - } - OsalMSleep(50); - - ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set rst high fail!:%d", __func__, ret); - return ret; - } - OsalMSleep(20); - - return HDF_SUCCESS; -} - -/* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */ -static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr, - unsigned char *regData, unsigned int dataLen, uint8_t flag) -{ - int index = 0; - unsigned char regBuf[4] = {0}; - struct I2cMsg msgs[2] = {0}; - - /* 单双字节寄存器长度适配 */ - if (tpDevice->regLen == 1) { - regBuf[index++] = regAddr & 0xFF; - } else { - regBuf[index++] = (regAddr >> 8) & 0xFF; - regBuf[index++] = regAddr & 0xFF; - } - - /* 填充I2cMsg消息结构 */ - msgs[0].addr = tpDevice->addr; - msgs[0].flags = 0; /* 标记为0,表示写入 */ - msgs[0].len = tpDevice->regLen; - msgs[0].buf = regBuf; - - msgs[1].addr = tpDevice->addr; - msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0; /* 添加读标记位,表示读取 */ - msgs[1].len = dataLen; - msgs[1].buf = regData; - - if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) { - HDF_LOGE("%s: i2c read err", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -/* TP寄存器读函数 */ -static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, - unsigned char *regData, unsigned int dataLen) -{ - return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1); -} - -/* TP寄存器写函数 */ -static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, - unsigned char *regData, unsigned int dataLen) -{ - return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0); -} - -/* I2C例程总入口 */ -static int32_t TestCaseI2c(void) -{ - int32_t i; - int32_t ret; - unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC }; - unsigned char bufRead[7] = {0}; - static struct TpI2cDevice tpDevice; - - /* IO管脚功能配置 */ - TpSocIoCfg(); - - /* TP设备信息初始化 */ - tpDevice.rstGpio = 3; - tpDevice.busId = 3; - tpDevice.addr = 0x38; - tpDevice.regLen = 1; - tpDevice.i2cHandle = NULL; - - /* GPIO管脚初始化 */ - ret = TestCaseGpioInit(&tpDevice); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: gpio init fail!:%d", __func__, ret); - return ret; - } - - /* 打开I2C控制器 */ - tpDevice.i2cHandle = I2cOpen(tpDevice.busId); - if (tpDevice.i2cHandle == NULL) { - HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId); - return -1; - } - - /* 向TP-IC的0xD5寄存器连续写7字节数据 */ - ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret); - I2cClose(tpDevice.i2cHandle); - return -1; - } - OsalMSleep(10); - - /* 从TP-IC的0xDO寄存器连续读7字节数据 */ - ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret); - I2cClose(tpDevice.i2cHandle); - return -1; - } - - HDF_LOGE("%s: tp i2c write&read reg success!", __func__); - for (i = 0; i < 7; i++) { - HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]); - } - - /* 访问完毕关闭I2C控制器 */ - I2cClose(tpDevice.i2cHandle); - return ret; -} -``` - diff --git "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 38341ca1d40f1c2572078f2f449e8a37065a9281..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/I2C\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,171 +0,0 @@ -# I2C使用指导 - -- [使用流程](#section333203315215) -- [打开I2C控制器](#section123631358135713) -- [进行I2C通信](#section11091522125812) -- [关闭I2C控制器](#section13519505589) - -## 使用流程 - -使用I2C设备的一般流程如[图1](#fig166181128151112)所示。 - -**图 1** I2C设备使用流程图 - - -![](figures/zh-cn_image_0000001057902344.png) - -## 打开I2C控制器 - -在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。 - -DevHandle I2cOpen\(int16\_t number\); - -**表 1** I2cOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

number

-

I2C控制器号

-

返回值

-

返回值描述

-

NULL

-

打开I2C控制器失败

-

设备句柄

-

打开的I2C控制器设备句柄

-
- -假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器 - -``` -DevHandle i2cHandle = NULL; /* I2C控制器句柄 / - -/* 打开I2C控制器 */ -i2cHandle = I2cOpen(3); -if (i2cHandle == NULL) { - HDF_LOGE("I2cOpen: failed\n"); - return; -} -``` - -## 进行I2C通信 - -消息传输 - -int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\); - -**表 2** I2cTransfer参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

I2C控制器设备句柄

-

msgs

-

待传输数据的消息结构体数组

-

count

-

消息数组长度

-

返回值

-

返回值描述

-

正整数

-

成功传输的消息结构体数目

-

负数

-

执行失败

-
- -I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 - -``` -int32_t ret; -uint8_t wbuff[2] = { 0x12, 0x13 }; -uint8_t rbuff[2] = { 0 }; -struct I2cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ -msgs[0].buf = wbuff; /* 写入的数据 */ -msgs[0].len = 2; /* 写入数据长度为2 */ -msgs[0].addr = 0x5A; /* 写入设备地址为0x5A */ -msgs[0].flags = 0; /* 传输标记为0,默认为写 */ -msgs[1].buf = rbuff; /* 要读取的数据 */ -msgs[1].len = 2; /* 读取数据长度为2 */ -msgs[1].addr = 0x5A; /* 读取设备地址为0x5A */ -msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ置位 */ -/* 进行一次自定义传输,传输的消息个数为2 */ -ret = I2cTransfer(i2cHandle, msgs, 2); -if (ret != 2) { - HDF_LOGE("I2cTransfer: failed, ret %d\n", ret); - return; -} -``` - ->![](public_sys-resources/icon-caution.gif) **注意:** ->- I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 ->- 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。 ->- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。 ->- 本函数可能会引起系统休眠,不允许在中断上下文调用 - -## 关闭I2C控制器 - -I2C通信完成之后,需要关闭2C控制器,关闭函数如下所示: - -void I2cClose\(DevHandle handle\); - -**表 3** I2cClose参数和返回值描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

I2C控制器设备句柄

-
- -``` -I2cClose(i2cHandle); /* 关闭I2C控制器 */ -``` - diff --git "a/zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" deleted file mode 100755 index 7961b58a8284049766dc470b862e377d79f1c696..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/I2C\346\246\202\350\277\260.md" +++ /dev/null @@ -1,60 +0,0 @@ -# I2C概述 - -- [简介](#section5361140416) -- [接口说明](#section7606310210) - -## 简介 - -- I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。 -- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA\(SerialData\)串行数据线以及SCL\(SerialClock\)串行时钟线两根线相连,如[图1 ](#fig1135561232714)所示。 - -- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 -- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 - -- I2C接口定义了完成I2C传输的通用方法集合,包括: - - - I2C控制器管理: 打开或关闭I2C控制器 - - I2C消息传输:通过消息传输结构体数组进行自定义传输 - - **图 1** I2C物理连线示意图 - ![](figures/I2C物理连线示意图.png "I2C物理连线示意图") - - -## 接口说明 - -**表 1** I2C驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

I2C控制器管理接口

-

I2cOpen

-

打开I2C控制器

-

I2cClose

-

关闭I2C控制器

-

I2c消息传输接口

-

I2cTransfer

-

自定义传输

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/LCD.md b/zh-cn/device-dev/driver/LCD.md deleted file mode 100755 index b6352ca83310a7c0f1d6af1d09f47a8450e626db..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/LCD.md +++ /dev/null @@ -1,9 +0,0 @@ -# LCD - -- **[LCD开发概述](LCD开发概述.md)** - -- **[LCD开发指导](LCD开发指导.md)** - -- **[LCD开发实例](LCD开发实例.md)** - - diff --git "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index 6de19704008c9850cec3a9f79baeddeef0c24401..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,291 +0,0 @@ -# LCD开发实例 - -添加设备描述配置: - -``` -/* Display驱动相关的设备描述配置 */ -display :: host { - hostName = "display_host"; - /* Display平台驱动设备描述 */ - device_hdf_disp :: device { - device0 :: deviceNode { - policy = 2; - priority = 200; - permission = 0660; - moduleName = "HDF_DISP"; - serviceName = "hdf_disp"; - } - } - /* SOC适配层驱动设备描述 */ - device_hi35xx_disp :: device { - device0 :: deviceNode { - policy = 0; - priority = 199; - moduleName = "HI351XX_DISP"; - } - } - /* LCD器件驱动设备描述 */ - device_lcd :: device { - device0 :: deviceNode { - policy = 0; - priority = 100; - preload = 0; - moduleName = "LCD_Sample"; - } - device1 :: deviceNode { - policy = 0; - priority = 100; - preload = 2; - moduleName = "LCD_SampleXX"; - } - } -} -``` - -SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下: - -``` -static int32_t MipiDsiInit(struct PanelInfo *info) -{ - int32_t ret; - struct DevHandle *mipiHandle = NULL; - struct MipiCfg cfg; - - mipiHandle = MipiDsiOpen(0); - if (mipiHandle == NULL) { - HDF_LOGE("%s: MipiDsiOpen failure", __func__); - return HDF_FAILURE; - } - cfg.lane = info->mipi.lane; - cfg.mode = info->mipi.mode; - cfg.format = info->mipi.format; - cfg.burstMode = info->mipi.burstMode; - cfg.timing.xPixels = info->width; - cfg.timing.hsaPixels = info->hsw; - cfg.timing.hbpPixels = info->hbp; - cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; - cfg.timing.vsaLines = info->vsw; - cfg.timing.vbpLines = info->vbp; - cfg.timing.vfpLines = info->vfp; - cfg.timing.ylines = info->height; - /* 0 : no care */ - cfg.timing.edpiCmdSize = 0; - cfg.pixelClk = CalcPixelClk(info); - cfg.phyDataRate = CalcDataRate(info); - /* config mipi device */ - ret = MipiDsiSetCfg(mipiHandle, &cfg); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); - } - MipiDsiClose(mipiHandle); - HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, - cfg.pixelClk, cfg.phyDataRate); - return ret; -} -``` - -LCD器件驱动示例如下: - -``` -#define RESET_GPIO 5 -#define MIPI_DSI0 0 -#define BLK_PWM1 1 -#define PWM_MAX_PERIOD 100000 -/* backlight setting */ -#define MIN_LEVEL 0 -#define MAX_LEVEL 255 -#define DEFAULT_LEVEL 100 - -#define WIDTH 480 -#define HEIGHT 960 -#define HORIZONTAL_BACK_PORCH 20 -#define HORIZONTAL_FRONT_PORCH 20 -#define HORIZONTAL_SYNC_WIDTH 10 -#define VERTIACL_BACK_PORCH 14 -#define VERTIACL_FRONT_PORCH 16 -#define VERTIACL_SYNC_WIDTH 2 -#define FRAME_RATE 60 - -/* Panel Info结构体结构体 */ -struct PanelInfo { - uint32_t width; - uint32_t height; - uint32_t hbp; - uint32_t hfp; - uint32_t hsw; - uint32_t vbp; - uint32_t vfp; - uint32_t vsw; - uint32_t frameRate; - enum LcdIntfType intfType; - enum IntfSync intfSync; - struct MipiDsiDesc mipi; - struct BlkDesc blk; - struct PwmCfg pwm; -}; - -/* LCD屏的初始化序列 */ -static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; -static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; -static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; -static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; -static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; -static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; -static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; -static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; -static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; -static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; -static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; -static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; -static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; -static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; -static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; -static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; -static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; -static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; -static uint8_t g_payLoad18[] = { - 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, - 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, - 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 -}; -static uint8_t g_payLoad19[] = { 0x11 }; -static uint8_t g_payLoad20[] = { 0x29 }; - -struct DsiCmdDesc g_OnCmd[] = { - { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 }, - { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 }, - { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 }, - { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 }, - { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 }, - { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 }, - { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 }, - { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 }, - { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 }, - { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 }, - { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 }, - { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 }, - { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 }, - { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 }, - { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 }, - { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 }, - { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 }, - { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 }, - { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 }, - { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 }, - { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, -}; -static DevHandle g_mipiHandle = NULL; -static DevHandle g_pwmHandle = NULL; - -/* 设置Reset Pin脚状态 */ -static int32_t LcdResetOn(void) -{ - int32_t ret; - ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioSetDir failure, ret:%d", ret); - return HDF_FAILURE; - } - ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); - if (ret != HDF_SUCCESS) { - HDF_LOGE("GpioWrite failure, ret:%d", ret); - return HDF_FAILURE; - } - /* delay 20ms */ - OsalMSleep(20); - return HDF_SUCCESS; -} - -static int32_t SampleInit(void) -{ - /* 获取MIPI DSI设备操作句柄 */ - g_mipiHandle = MipiDsiOpen(MIPI_DSI0); - if (g_mipiHandle == NULL) { - HDF_LOGE("%s: MipiDsiOpen failure", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -static int32_t SampleOn(void) -{ - int32_t ret; - /* LCD上电序列 */ - ret = LcdResetOn(); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: LcdResetOn failure", __func__); - return HDF_FAILURE; - } - if (g_mipiHandle == NULL) { - HDF_LOGE("%s: g_mipiHandle is null", __func__); - return HDF_FAILURE; - } - /* 使用mipi下发初始化序列 */ - int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); - int32_t i; - for (i = 0; i < count; i++) { - ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i])); - if (ret != HDF_SUCCESS) { - HDF_LOGE("MipiDsiTx failure"); - return HDF_FAILURE; - } - } - /* 将mipi切换到HS模式 */ - MipiDsiSetHsMode(g_mipiHandle); - return HDF_SUCCESS; -} - -/* PanelInfo结构体变量 */ -static struct PanelInfo g_panelInfo = { - .width = WIDTH, /* width */ - .height = HEIGHT, /* height */ - .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ - .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ - .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ - .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ - .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ - .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ - .frameRate = FRAME_RATE, /* frame rate */ - .intfType = MIPI_DSI, /* panel interface type */ - .intfSync = OUTPUT_USER, /* output timming type */ - /* mipi config info */ - .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, - /* backlight config info */ - .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, - .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, -}; - -/* 器件驱动需要适配的基础接口 */ -static struct PanelData g_panelData = { - .info = &g_panelInfo, - .init = SampleInit, - .on = SampleOn, - .off = SampleOff, - .setBacklight = SampleSetBacklight, -}; - -/* 器件驱动入口函数 */ -int32_t SampleEntryInit(struct HdfDeviceObject *object) -{ - HDF_LOGI("%s: enter", __func__); - if (object == NULL) { - HDF_LOGE("%s: param is null!", __func__); - return HDF_FAILURE; - } - /* 器件驱动接口注册,ops提供给平台驱动调用 */ - if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { - HDF_LOGE("%s: PanelDataRegister error!", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -struct HdfDriverEntry g_sampleDevEntry = { - .moduleVersion = 1, - .moduleName = "LCD_SAMPLE", - .Init = SampleEntryInit, -}; - -HDF_INIT(g_sampleDevEntry); -``` - diff --git "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 12161e4cef9752fb16db59f597560828f5af8085..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,23 +0,0 @@ -# LCD开发指导 - -- [开发步骤](#section3904154911218) - -Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。 - -## 开发步骤 - -1. 添加LCD驱动相关的设备描述配置。 -2. 在SOC平台驱动适配层中适配对应的芯片平台驱动。 -3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口: - - LCD上下电 - - 根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。 - - - 发送初始化序列 - - 根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。 - - -4. 根据需求实现HDF框架其他接口,比如Release接口。 -5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。 - diff --git "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index ab5e824934e96eedd766288dbeb33f93d7b38ab2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/LCD\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,46 +0,0 @@ -# LCD开发概述 - -- [简介](#section3781515122118) -- [接口说明](#section20280192712120) - -## 简介 - -LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](HDF开发概述.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)。 - -**图 1** 基于HDF驱动框架的Display驱动模型 -![](figures/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型") - -- **Display驱动模型介绍** - - Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。 - - (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令; - - (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层; - - (3)LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。 - - 基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。 - - -## 接口说明 - -LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。 - -- MIPI DSI接口 - - **图 2** MIPI DSI接口 - ![](figures/MIPI-DSI接口.png "MIPI-DSI接口") - - MIPI DSI接口是MIPI(移动行业处理器接口)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。 - -- TTL接口 - - **图 3** TTL接口 - ![](figures/TTL接口.png "TTL接口") - - TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。 - - TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。 - - diff --git a/zh-cn/device-dev/driver/MIPI-DSI.md b/zh-cn/device-dev/driver/MIPI-DSI.md deleted file mode 100755 index 2dcbddcdd053fdc85e2b8478b690d79dfe41909d..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/MIPI-DSI.md +++ /dev/null @@ -1,9 +0,0 @@ -# MIPI DSI - -- **[MIPI DSI概述](MIPI-DSI概述.md)** - -- **[MIPI DSI使用指导](MIPI-DSI使用指导.md)** - -- **[MIPI DSI使用实例](MIPI-DSI使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 77e9242f30b175fee1f855d9516d3e407aa2a8fa..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,98 +0,0 @@ -# MIPI DSI使用实例 - -MIPI-DSI完整的使用示例如下所示: - -``` -#include "hdf.h" -#include "mipi_dsi_if.h" - -void PalMipiDsiTestSample(void) -{ - uint8_t chnId; - int32_t ret; - DevHandle handle = NULL; - - /* 设备通道编号 */ - chnId = 0; - /* 获取操作句柄 */ - handle = MipiDsiOpen(chnId); - if (handle == NULL) { - HDF_LOGE("MipiDsiOpen: failed!\n"); - return; - } - /* 配置相应参数 */ - struct MipiCfg cfg = {0}; - cfg.lane = DSI_4_LANES; - cfg.mode = DSI_CMD_MODE; - cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; - cfg.format = FORMAT_RGB_24_BIT; - cfg.pixelClk = 174; - cfg.phyDataRate = 384; - cfg.timingInfo.hsaPixels = 50; - cfg.timingInfo.hbpPixels = 55; - cfg.timingInfo.hlinePixels = 1200; - cfg.timingInfo.yResLines = 1800; - cfg.timingInfo.vbpLines = 33; - cfg.timingInfo.vsaLines = 76; - cfg.timingInfo.vfpLines = 120; - cfg.timingInfo.xResPixels = 1342; - /* 写入配置数据 */ - ret = MipiDsiSetCfg(g_handle, &cfg); - if (ret != 0) { - HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); - return; - } - /* 发送PANEL初始化指令 */ - struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); - if (cmd == NULL) { - return; - } - cmd->dtype = DTYPE_DCS_WRITE; - cmd->dlen = 1; - cmd->payload = OsalMemCalloc(sizeof(uint8_t)); - if (cmd->payload == NULL) { - HdfFree(cmd); - return; - } - *(cmd->payload) = DTYPE_GEN_LWRITE; - MipiDsiSetLpMode(mipiHandle); - ret = MipiDsiTx(mipiHandle, cmd); - MipiDsiSetHsMode(mipiHandle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: MipiDsiTx fail! ret=%d\n", __func__, ret); - HdfFree(cmd->payload); - HdfFree(cmd); - return; - } - HdfFree(cmd->payload); - HdfFree(cmd); - /* 回读panel状态寄存器 */ - uint8_t readVal = 0; - struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); - if (cmdRead == NULL) { - return; - } - cmdRead->dtype = DTYPE_DCS_READ; - cmdRead->dlen = 1; - cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); - if (cmdRead->payload == NULL) { - HdfFree(cmdRead); - return; - } - *(cmdRead->payload) = DDIC_REG_STATUS; - MipiDsiSetLpMode(g_handle); - ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); - MipiDsiSetHsMode(g_handle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); - HdfFree(cmdRead->payload); - HdfFree(cmdRead); - return; - } - HdfFree(cmdRead->payload); - HdfFree(cmdRead); - /* 释放MIPI DSI设备句柄 */ - MipiDsiClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 58603da99a1536aebce4f61f049e5bc960d0114f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/MIPI-DSI\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,365 +0,0 @@ -# MIPI DSI使用指导 - -- [使用流程](#section8982671284) -- [获取MIPI-DSI操作句柄](#section57982569176) -- [MIPI-DSI相应配置](#section5935410201815) -- [发送/回读控制指令](#section611661316194) -- [释放MIPI-DSI操作句柄](#section217313211199) - -## 使用流程 - -使用MIPI-DSI的一般流程如[图1](#fig99821771782)所示。 - -**图 1** MIPI-DSI使用流程图 - - -![](figures/zh-cn_image_0000001072553354.png) - -## 获取MIPI-DSI操作句柄 - -在进行MIPI-DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。 - -DevHandle MipiDsiOpen\(uint8\_t id\); - -**表 1** MipiDsiOpen的参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

id

-

MIPI DSI通道ID

-

返回值

-

返回值描述

-

NULL

-

获取失败

-

设备句柄

-

获取到指令通道的操作句柄, 类型为DevHandle

-
- -假设系统中的MIPI-DSI通道为0,获取该通道操作句柄的示例如下: - -``` -DevHandle mipiDsiHandle = NULL; /* 设备句柄 */ -chnId = 0; /* MIPI-DSI通道ID */ - -/* 获取操作句柄 */ -mipiDsiHandle = MipiDsiOpen(chnId); -if (mipiDsiHandle == NULL) { - HDF_LOGE("MipiDsiOpen: failed\n"); - return; -} -``` - -## MIPI-DSI相应配置 - -- 写入MIPI-DSI配置 - -int32\_t MipiDsiSetCfg\(DevHandle handle, struct MipiCfg \*cfg\); - -**表 2** MipiDsiSetCfg的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

操作句柄

-

cfg

-

MIPI-DSI相应配置buf 指针

-

返回值

-

返回值描述

-

0

-

设置成功

-

负数

-

设置失败

-
- -``` -int32_t ret; -struct MipiCfg cfg = {0}; - -/* 当前对接的屏幕配置如下 */ -cfg.lane = DSI_4_LANES; -cfg.mode = DSI_CMD_MODE; -cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; -cfg.format = FORMAT_RGB_24_BIT; -cfg.pixelClk = 174; -cfg.phyDataRate = 384; -cfg.timingInfo.hsaPixels = 50; -cfg.timingInfo.hbpPixels = 55; -cfg.timingInfo.hlinePixels = 1200; -cfg.timingInfo.yResLines = 1800; -cfg.timingInfo.vbpLines = 33; -cfg.timingInfo.vsaLines = 76; -cfg.timingInfo.vfpLines = 120; -cfg.timingInfo.xResPixels = 1342; -/* 写入配置数据 */ -ret = MipiDsiSetCfg(g_handle, &cfg); -if (ret != 0) { - HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); - return -1; -} -``` - -- 获取当前MIPI-DSI的配置 - -int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\); - -**表 3** MipiDsiGetCfg的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

操作句柄

-

cfg

-

MIPI-DSI相应配置buf 指针

-

返回值

-

返回值描述

-

0

-

获取成功

-

负数

-

获取失败

-
- -``` -int32_t ret; -struct MipiCfg cfg; -memset(&cfg, 0, sizeof(struct MipiCfg)); -ret = MipiDsiGetCfg(g_handle, &cfg); -if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: GetMipiCfg fail!\n", __func__); - return HDF_FAILURE; -} -``` - -## 发送/回读控制指令 - -- 发送指令 - -int32\_t MipiDsiTx\(PalHandle handle, struct DsiCmdDesc \*cmd\); - -**表 4** MipiDsiTx的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

操作句柄

-

cmd

-

需要发送的指令数据指针

-

返回值

-

返回值描述

-

0

-

发送成功

-

负数

-

发送失败

-
- -``` -int32_t ret; -struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); -if (cmd == NULL) { - return HDF_FAILURE; -} -cmd->dtype = DTYPE_DCS_WRITE; -cmd->dlen = 1; -cmd->payload = OsalMemCalloc(sizeof(uint8_t)); -if (cmd->payload == NULL) { - HdfFree(cmd); - return HDF_FAILURE; -} -*(cmd->payload) = DTYPE_GEN_LWRITE; -MipiDsiSetLpMode(mipiHandle); -ret = MipiDsiTx(mipiHandle, cmd); -MipiDsiSetHsMode(mipiHandle); -if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret); - HdfFree(cmd->payload); - HdfFree(cmd); - return HDF_FAILURE; -} -HdfFree(cmd->payload); -HdfFree(cmd); -``` - -- 回读指令 - -int32\_t MipiDsiRx\(DevHandle handle, struct DsiCmdDesc \*cmd, uint32\_t readLen, uint8\_t \*out\); - -**表 5** MipiDsiRx的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

操作句柄

-

cmd

-

需要回读的指令数据指针

-

readLen

-

期望回读的数据长度

-

out

-

回读的数据buf指针

-

返回值

-

返回值描述

-

0

-

获取成功

-

负数

-

获取失败

-
- -``` -int32_t ret; -uint8_t readVal = 0; - -struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); -if (cmdRead == NULL) { - return HDF_FAILURE; -} -cmdRead->dtype = DTYPE_DCS_READ; -cmdRead->dlen = 1; -cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); -if (cmdRead->payload == NULL) { - HdfFree(cmdRead); - return HDF_FAILURE; -} -*(cmdRead->payload) = DDIC_REG_STATUS; -MipiDsiSetLpMode(g_handle); -ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); -MipiDsiSetHsMode(g_handle); -if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); - HdfFree(cmdRead->payload); - HdfFree(cmdRead); - return HDF_FAILURE; -} -HdfFree(cmdRead->payload); -HdfFree(cmdRead); -``` - -## 释放MIPI-DSI操作句柄 - -MIPI-DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示: - -void MipiDsiClose\(DevHandle handle\); - -该函数会释放掉由MipiDsiOpen申请的资源。 - -**表 6** MipiDsiClose的参数和返回值描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

MIPI-DSI操作句柄

-
- -``` -MipiDsiClose(mipiHandle); /* 释放掉MIPI-DSI操作句柄 */ -``` - diff --git "a/zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" deleted file mode 100755 index 5af73287eb9f6d46a3ec9f7fb5ca2e3d0668ce1b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/MIPI-DSI\346\246\202\350\277\260.md" +++ /dev/null @@ -1,84 +0,0 @@ -# MIPI DSI概述 - -- [简介](#section1369320102013) -- [接口说明](#section6577545192317) - -## 简介 - -- DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设\(通常是LCD或者类似的显示设备\),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。 - -- MIPI-DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。 - - 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 - - **图 1** DSI发送、接收接口 - ![](figures/DSI发送-接收接口.png "DSI发送-接收接口") - - - -## 接口说明 - -**表 1** MIPI-DSI API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

设置/获取当前MIPI-DSI相关配置

-

MipiDsiSetCfg

-

设置MIPI-DSI相关配置

-

MipiDsiGetCfg

-

获取当前MIPI-DSI相关配置

-

获取/释放MIPI-DSI操作句柄

-

MipiDsiOpen

-

获取MIPI-DSI操作句柄

-

MipiDsiClose

-

释放MIPI-DSI操作句柄

-

设置MIPI-DSI进入Low power模式/High speed模式

-

MipiDsiSetLpMode

-

设置MIPI-DSI进入Low power模式

-

MipiDsiSetHsMode

-

设置MIPI-DSI进入High speed模式

-

MIPI-DSI发送/回读指令

-

MipiDsiTx

-

MIPI-DSI发送相应指令的接口

-

MipiDsiRx

-

MIPI-DSI按期望长度回读的接口

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用 - diff --git a/zh-cn/device-dev/driver/RTC.md b/zh-cn/device-dev/driver/RTC.md deleted file mode 100755 index de745a39f9bbe657f60ac09e4dcfac7bd225b829..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/RTC.md +++ /dev/null @@ -1,9 +0,0 @@ -# RTC - -- **[RTC概述](RTC概述.md)** - -- **[RTC使用指导](RTC使用指导.md)** - -- **[RTC使用实例](RTC使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index d413efda41b8fbc48a7f5c6b8837dbc8aef2c480..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,97 +0,0 @@ -# RTC使用实例 - -本实例提供RTC接口的完整使用流程: - -1. 系统启动,驱动管理模块会识别系统当前的RTC器件; -2. 驱动管理模块完成RTC设备的初始化和设备创建; -3. 用户通过不同API,对该RTC设备进行对应的操作; -4. 关闭RTC设备,释放设备资源。 - -示例如下: - -``` -#include "rtc_if.h" -int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) -{ - if (alarmIndex == RTC_ALARM_INDEX_A) { - /* 报警A的处理 */ - printf("RTC Alarm A callback function\n\r"); - } else if (alarmIndex == RTC_ALARM_INDEX_B) { - /* 报警B的处理 */ - printf("RTC Alarm B callback function\n\r"); - } else { - /* 错误处理 */ - } - return 0; -} - -void RtcTestSample(void) -{ - int32_t ret; - struct RtcTime tm; - struct RtcTime alarmTime; - uint32_t freq; - DevHandle handle = NULL; - - /* 获取RTC设备句柄 */ - handle = RtcOpen(); - if (handle == NULL) { - /* 错误处理 */ - } - /* 注册报警A的定时回调函数 */ - ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ - freq = 32768; /* 32768 Hz */ - ret = RtcSetFreq(handle, freq); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC报警中断使能 */ - ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC时间为2020/01/01 00:00:10 .990 */ - tm.year = 2020; - tm.month = 01; - tm.day = 01; - tm.hour= 0; - tm.minute = 0; - tm.second = 10; - tm.millisecond = 990; - /* 写RTC时间信息 */ - ret = RtcWriteTime(handle, &tm); - if (ret != 0) { - /* 错误处理 */ - } - /* 设置RTC报警时间为2020/01/01 00:00:30 .100 */ - alarmTime.year = 2020; - alarmTime.month = 01; - alarmTime.day = 01; - alarmTime.hour = 0; - alarmTime.minute = 0; - alarmTime.second = 30; - alarmTime.millisecond = 100; - /* 设置RTC_ALARM_INDEX_A索引定时报警时间信息, 定时时间到后会打印"RTC Alarm A callback function" */ - ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); - if (ret != 0) { - /* 错误处理 */ - } - - /* 读取RTC实时时间 */ - ret = RtcReadTime(handle, &tm); - if (ret != 0) { - /* 错误处理 */ - } - sleep(5) - printf("RTC read time:\n\r"); - printf("year-month-date-weekday hour:minute:second .millisecond %04u-%02u-%02u-%u %02u:%02u:%02u .%03u", - tm.year, tm.month, tm.day, tm.weekday, tm.hour, tm.minute, tm.second, tm.millisecond); - /* 销毁RTC设备句柄 */ - RtcClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 45065165bd233fa2a09b4f8843b40c2325786823..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/RTC\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,741 +0,0 @@ -# RTC使用指导 - -- [使用流程](#section620515765714) -- [创建RTC设备句柄](#section0702183665711) -- [销毁RTC设备句柄](#section639962619542) -- [注册RTC定时报警回调函数](#section123631358135713) -- [操作RTC](#section11091522125812) - -## 使用流程 - -在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。 - -使用RTC设备的一般流程如[图1](#fig166181128151112)所示。 - -**图 1** RTC设备使用流程图 - - -![](figures/zh-cn_image_0000001054728498.png) - -## 创建RTC设备句柄 - -RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前操作系统支持一个RTC设备。 - -DevHandle RtcOpen\(void\); - -**表 1** RtcOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

void

-

NA

-

返回值

-

返回值描述

-

handle

-

操作成功返回 指针类型

-

NULL

-

操作失败

-
- -``` -DevHandle handle = NULL; - -/* 获取RTC句柄 */ -handle = RtcOpen(); -if (handle == NULL) { - /* 错误处理 */ -} -``` - -## 销毁RTC设备句柄 - -销毁RTC设备句柄,系统释放对应的资源。 - -void RtcClose\(DevHandle handle\); - -**表 2** RtcClose参数描述 - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-
- -``` -/* 销毁RTC句柄 */ -RtcClose(handle); -``` - -## 注册RTC定时报警回调函数 - -系统启动后需要注册RTC定时报警回调函数,报警超时后触发回调函数。 - -int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb\); - -**表 3** RtcRegisterAlarmCallback参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

alarmIndex

-

报警索引

-

cb

-

定时报警回调函数

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -注册RTC\_ALARM\_INDEX\_A的定时报警处理函数, 示例如下: - -``` -/* 用户注册RTC定时报警回调函数的方法 */ -int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) -{ - if (alarmIndex == RTC_ALARM_INDEX_A) { - /* 报警A的处理 */ - } else if (alarmIndex == RTC_ALARM_INDEX_B) { - /* 报警B的处理 */ - } else { - /* 错误处理 */ - } - return 0; -} -int32_t ret; -/* 注册报警A的定时回调函数 */ -ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); -if (ret != 0) { - /* 错误处理 */ -} -``` - -## 操作RTC - -- 读取RTC时间。 - -系统从RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒,则可以通过以下函数完成: - -int32\_t RtcReadTime\(DevHandle handle, struct RtcTime \*time\); - -**表 4** RtcReadTime参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

time

-

RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; -struct RtcTime tm; - -/* 系统从RTC读取时间信息 */ -ret = RtcReadTime(handle, &tm); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置RTC时间 - -设置RTC时间,则可以通过以下函数完成: - -int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\); - -**表 5** RtcWriteTime参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

time

-

写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 - -``` -int32_t ret; -struct RtcTime tm; - -/* 设置RTC时间为 UTC 2020/01/01 00:59:00 .000 */ -tm.year = 2020; -tm.month = 01; -tm.day = 01; -tm.hour= 00; -tm.minute = 59; -tm.second = 00; -tm.millisecond = 0; -/* 写RTC时间信息 */ -ret = RtcWriteTime(handle, &tm); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 读取RTC报警时间 - -如果需要读取定时报警时间,则可以通过以下函数完成: - -int32\_t RtcReadAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); - -**表 6** RtcReadAlarm参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

alarmIndex

-

报警索引

-

time

-

RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; -struct RtcTime alarmTime; - -/* 读RTC_ALARM_INDEX_A索引的RTC定时报警时间信息 */ -ret = RtcReadAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置RTC报警时间 - -根据报警索引设置RTC报警时间,通过以下函数完成: - -int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); - -**表 7** RtcWriteAlarm参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

alarmIndex

-

报警索引

-

time

-

RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 - -``` -int32_t ret; -struct RtcTime alarmTime; - -/* 设置RTC报警时间为2020/01/01 00:59:59 .000 */ -alarmTime.year = 2020; -alarmTime.month = 01; -alarmTime.day = 01; -alarmTime.hour = 00; -alarmTime.minute = 59; -alarmTime.second = 59; -alarmTime.millisecond = 0; -/* 设置RTC_ALARM_INDEX_A索引的定时报警时间 */ -ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置定时报警中断使能或去使能 - -在启动报警操作前,需要先设置报警中断使能,报警超时后会触发告警回调函数,可以通过以下函数完成: - -int32\_t RtcAlarmInterruptEnable\(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8\_t enable\); - -**表 8** RtcAlarmInterruptEnable参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

alarmIndex

-

报警索引

-

enable

-

RTC报警中断配置,1:使能,0:去使能

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; - -/* 设置RTC报警中断使能 */ -ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 读取RTC外频 - -读取RTC外接晶体振荡频率,可以通过以下函数完成: - -int32\_t RtcGetFreq\(DevHandle handle, uint32\_t \*freq\); - -**表 9** RtcGetFreq参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

freq

-

RTC的外接晶体振荡频率,单位(HZ)

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; -uint32_t freq = 0; - -/* 读取RTC外接晶体振荡频率 */ -ret = RtcGetFreq(handle, &freq); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 配置RTC外频 - -配置RTC外接晶体振荡频率,可以通过以下函数完成: - -int32\_t RtcSetFreq\(DevHandle handle, uint32\_t freq\); - -**表 10** RtcSetFreq参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

freq

-

RTC的外接晶体振荡频率,单位(HZ)

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; -uint32_t freq = 32768; /* 32768 Hz */ - -/* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ -ret = RtcSetFreq(handle, freq); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 复位RTC - -复位RTC,复位RTC后各配置寄存器恢复默认值,可以通过以下函数完成: - -int32\_t RtcReset\(DevHandle handle\); - -**表 11** RtcReset参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; - -/* 复位RTC,复位RTC后各配置寄存器恢复默认值 */ -ret = RtcReset(handle); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 读取RTC自定义寄存器配置 - -按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: - -int32\_t RtcReadReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t \*value\); - -**表 12** RtcReadReg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

usrDefIndex

-

用户定义的寄存器对应索引

-

value

-

寄存器值

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; -uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义的第一个寄存器*/ -uint8_t value = 0; - -/* 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 */ -ret = RtcReadReg(handle, usrDefIndex, &value); -if (ret != 0) { - /* 错误处理 */ -} -``` - -- 设置RTC自定义寄存器配置 - -按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: - -int32\_t RtcWriteReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t value\); - -**表 13** RtcWriteReg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

RTC设备句柄

-

usrDefIndex

-

用户定义的寄存器对应索引

-

value

-

寄存器值

-

返回值

-

返回值描述

-

0

-

操作成功

-

负数

-

操作失败

-
- -``` -int32_t ret; -uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义第一个寄存器*/ -uint8_t value = 0x10; - -/* 按照用户的定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 */ -ret = RtcWriteReg(handle, usrDefIndex, value); -if (ret != 0) { - /* 错误处理 */ -} -``` - diff --git "a/zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" deleted file mode 100755 index 19b903394cd28f79241b90a90db46a81f1d82529..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/RTC\346\246\202\350\277\260.md" +++ /dev/null @@ -1,103 +0,0 @@ -# RTC概述 - -- [简介](#section104842041574) -- [接口说明](#section16892932155715) - -## 简介 - -RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 - -## 接口说明 - -**表 1** RTC设备API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

RTC句柄操作

-

RtcOpen

-

获取RTC设备驱动句柄

-

RtcClose

-

释放RTC设备驱动句柄

-

RTC时间操作接口

-

RtcReadTime

-

读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

-

RtcWriteTime

-

写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

-

RTC报警操作接口

-

RtcReadAlarm

-

读RTC报警时间信息

-

RtcWriteAlarm

-

写RTC报警时间信息

-

RtcRegisterAlarmCallback

-

注册报警超时回调函数

-

RtcAlarmInterruptEnable

-

使能/去使能RTC报警中断

-

RTC配置操作

-

RtcGetFreq

-

读RTC外接晶振频率

-

RtcSetFreq

-

配置RTC外接晶振频率

-

RtcReset

-

RTC复位

-

读写用户定义寄存器

-

RtcReadReg

-

读用户自定义寄存器

-

RtcWriteReg

-

写用户自定义寄存器

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/Readme-CN.md b/zh-cn/device-dev/driver/Readme-CN.md index f86ff0362ebca8304d36ae274a125ce7bd8e22bc..39991f33cabcae6e181fdfaefe7a8e3fe0d84a5b 100755 --- a/zh-cn/device-dev/driver/Readme-CN.md +++ b/zh-cn/device-dev/driver/Readme-CN.md @@ -1,73 +1,24 @@ -# 驱动 - -- [HDF驱动框架](HDF驱动框架.md) - - [HDF开发概述](HDF开发概述.md) - - [驱动开发](驱动开发.md) - - [驱动服务管理](驱动服务管理.md) - - [驱动消息机制管理](驱动消息机制管理.md) - - [配置管理](配置管理.md) - - [HDF开发实例](HDF开发实例.md) - -- [驱动平台](驱动平台.md) - - [GPIO](GPIO.md) - - [GPIO概述](GPIO概述.md) - - [GPIO使用指导](GPIO使用指导.md) - - [GPIO使用实例](GPIO使用实例.md) - - - [I2C](I2C.md) - - [I2C概述](I2C概述.md) - - [I2C使用指导](I2C使用指导.md) - - [I2C使用实例](I2C使用实例.md) - - - [RTC](RTC.md) - - [RTC概述](RTC概述.md) - - [RTC使用指导](RTC使用指导.md) - - [RTC使用实例](RTC使用实例.md) - - - [SDIO](SDIO.md) - - [SDIO概述](SDIO概述.md) - - [SDIO使用指导](SDIO使用指导.md) - - [SDIO使用实例](SDIO使用实例.md) - - - [SPI](SPI.md) - - [SPI概述](SPI概述.md) - - [SPI使用指导](SPI使用指导.md) - - [SPI使用实例](SPI使用实例.md) - - - [UART](UART.md) - - [UART概述](UART概述.md) - - [UART使用指导](UART使用指导.md) - - [UART使用实例](UART使用实例.md) - - - [WATCHDOG](WATCHDOG.md) - - [看门狗概述](看门狗概述.md) - - [看门狗使用指导](看门狗使用指导.md) - - [看门狗使用实例](看门狗使用实例.md) - - - [MIPI DSI](MIPI-DSI.md) - - [MIPI DSI概述](MIPI-DSI概述.md) - - [MIPI DSI使用指导](MIPI-DSI使用指导.md) - - [MIPI DSI使用实例](MIPI-DSI使用实例.md) - -- [外设](外设.md) - - [LCD](LCD.md) - - [LCD开发概述](LCD开发概述.md) - - [LCD开发指导](LCD开发指导.md) - - [LCD开发实例](LCD开发实例.md) - - - [TOUCHSCREEN](TOUCHSCREEN.md) - - [Touchscreen开发概述](Touchscreen开发概述.md) - - [Touchscreen开发指导](Touchscreen开发指导.md) - - [Touchscreen开发实例](Touchscreen开发实例.md) - - - [SENSOR](SENSOR.md) - - [传感器驱动开发概述](传感器驱动开发概述.md) - - [传感器驱动开发指导](传感器驱动开发指导.md) - - [传感器驱动开发实例](传感器驱动开发实例.md) - - [传感器驱动测试指导](传感器驱动测试指导.md) - - - [WLAN](WLAN.md) - - [WLAN开发概述](WLAN开发概述.md) - - [WLAN开发指导](WLAN开发指导.md) - - [WLAN开发实例](WLAN开发实例.md) +# 驱动使用指南 + +- [HDF驱动框架](drive.md) + - [HDF开发概述](drive-hdf-overview.md) + - [驱动开发](drive-hdf-development.md) + - [驱动服务管理](drive-hdf-servicemanage.md) + - [驱动消息机制管理](drive-hdf-news.md) + - [配置管理](drive-hdf-manage.md) + - [HDF开发实例](drive-hdf-sample.md) +- [平台驱动](drive-platform.md) + - [GPIO](drive-platform-gpio-des.md) + - [I2C](drive-platform-i2c-des.md) + - [RTC](drive-platform-rtc-des.md) + - [SDIO](drive-platform-sdio-des.md) + - [SPI](drive-platform-spi-des.md) + - [UART](drive-platform-uart-des.md) + - [WATCHDOG](drive-platform-watchdog-des.md) + - [MIPI DSI](drive-platform-mipidsi-des.md) +- [外设](drive-peripherals.md) + - [LCD](drive-peripherals-lcd-des.md) + - [TOUCHSCREEN](drive-peripherals-touch-des.md) + - [SENSOR](drive-peripherals-sensor-des.md) + - [WLAN](drive-peripherals-external-des.md) diff --git a/zh-cn/device-dev/driver/SDIO.md b/zh-cn/device-dev/driver/SDIO.md deleted file mode 100755 index 192dd216b5df44ef51ede3e7ac9dab09eaca828a..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/SDIO.md +++ /dev/null @@ -1,9 +0,0 @@ -# SDIO - -- **[SDIO概述](SDIO概述.md)** - -- **[SDIO使用指导](SDIO使用指导.md)** - -- **[SDIO使用实例](SDIO使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 18ddb74593b5ea69a427ecd03e8a41394daae174..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,129 +0,0 @@ -# SDIO使用实例 - -SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 - -``` -#include "hdf_log.h" -#include "sdio_if.h" - -#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ -#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ -#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ -#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ -#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ - -/* 中断服务函数,需要根据各自平台的情况去实现 */ -static void SdioIrqFunc(void *data) -{ - if (data == NULL) { - HDF_LOGE("SdioIrqFunc: data is NULL.\n"); - return; - } - /* 需要开发者自行添加具体的实现 */ -} - -void SdioTestSample(void) -{ - int32_t ret; - DevHandle handle = NULL; - uint8_t data[TEST_DATA_LEN] = {0}; - struct SdioFunctionConfig config = {1, 0x123, 0x456}; - uint8_t val; - uint32_t addr; - - /* 打开总线号为1的SDIO设备 */ - handle = SdioOpen(1, &config); - if (handle == NULL) { - HDF_LOGE("SdioOpen: failed!\n"); - return; - } - /* 独占HOST */ - SdioClaimHost(handle); - /* 使能SDIO设备 */ - ret = SdioEnableFunc(handle); - if (ret != 0) { - HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); - goto ENABLE_ERR; - } - /* 注册中断 */ - ret = SdioClaimIrq(handle, SdioIrqFunc); - if (ret != 0) { - HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); - goto CLAIM_IRQ_ERR; - } - /* 设置块大小为2字节 */ - ret = SdioSetBlockSize(handle, TEST_BLOCKSIZE); - if (ret != 0) { - HDF_LOGE("SdioSetBlockSize: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO设备增量地址读取3字节的数据 */ - addr = TEST_FBR_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET; - ret = SdioReadBytes(handle, data, addr, TEST_DATA_LEN); - if (ret != 0) { - HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO设备增量地址写入3字节的数据 */ - ret = SdioWriteBytes(handle, data, addr, TEST_DATA_LEN); - if (ret != 0) { - HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO设备读取1字节的数据 */ - ret = SdioReadBytes(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO设备写入1字节的数据 */ - ret = SdioWriteBytes(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO设备固定地址读取3字节的数据 */ - ret = SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0); - if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO设备固定地址写入1字节的数据 */ - ret = SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0); - if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 从SDIO function 0读取1字节的数据 */ - addr = 0x02; - ret = SdioReadBytesFromFunc0(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); - goto COMM_ERR; - } - /* 向SDIO function 0写入1字节的数据 */ - ret = SdioWriteBytesToFunc0(handle, &val, addr, 1); - if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); - goto COMM_ERR; - } -COMM_ERR: - /* 释放中断 */ - ret = SdioReleaseIrq(handle); - if (ret != 0) { - HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); - } -CLAIM_IRQ_ERR: - /* 去使能SDIO设备 */ - ret = SdioDisableFunc(handle); - if (ret != 0) { - HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); - } -ENABLE_ERR: - /* 释放HOST */ - SdioReleaseHost(handle); - /* 关闭SDIO设备 */ - SdioClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index fd65e6de6adcef6ef307018c850ca1cb513d3b1f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/SDIO\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,787 +0,0 @@ -# SDIO使用指导 - -- [使用流程](#section1962415610383) -- [打开SDIO控制器](#section814751015461) -- [独占HOST](#section49274582455) -- [使能SDIO设备](#section1431520410489) -- [注册SDIO中断](#section3662781537) -- [进行SDIO通信](#section391941913484) -- [释放SDIO中断](#section56205204481) -- [去使能SDIO设备](#section181181621124815) -- [释放HOST](#section657117215486) -- [关闭SDIO控制器](#section1898172114818) - -## 使用流程 - -使用SDIO的一般流程如[图1](SPI使用指导.md#fig23885455594)所示。 - -**图 1** SDIO使用流程图 - - -![](figures/zh-cn_image_0000001054440624.png) - -## 打开SDIO控制器 - -在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。 - -DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\); - -**表 1** SdioOpen函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

mmcBusNum

-

总线号

-

config

-

SDIO功能配置信息

-

返回值

-

返回值描述

-

NULL

-

获取SDIO控制器的设备句柄失败

-

设备句柄

-

SDIO控制器的设备句柄

-
- -打开SDIO控制器的示例如下: - -``` -DevHandle handle = NULL; -struct SdioFunctionConfig config; -config.funcNr = 1; -config.vendorId = 0x123; -config.deviceId = 0x456; -/* 打开总线号为1的SDIO控制器 */ -handle = SdioOpen(1, &config); -if (handle == NULL) { - HDF_LOGE("SdioOpen: failed!\n"); -} -``` - -## 独占HOST - -获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示: - -void SdioClaimHost\(DevHandle handle\); - -**表 2** SdioClaimHost函数的参数描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-
- -独占HOST示例如下: - -``` -SdioClaimHost(handle); /* 独占HOST */ -``` - -## 使能SDIO设备 - -在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示: - -int32\_t SdioEnableFunc\(DevHandle handle\); - -**表 3** SdioEnableFunc函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

返回值

-

返回值描述

-

0

-

SDIO使能成功

-

负数

-

SDIO使能失败

-
- -使能SDIO设备的示例如下: - -``` -int32_t ret; -/* 使能SDIO设备 */ -ret = SdioEnableFunc(handle); -if (ret != 0) { - HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); -} -``` - -## 注册SDIO中断 - -在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下图所示: - -int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\); - -**表 4** SdioClaimIrq函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

handler

-

中断服务函数指针

-

返回值

-

返回值描述

-

0

-

注册中断成功

-

负数

-

注册中断失败

-
- -注册SDIO中的示例如下: - -``` -/* 中断服务函数需要根据各自平台的情况去实现 */ -static void SdioIrqFunc(void *data) -{ - if (data == NULL) { - HDF_LOGE("SdioIrqFunc: data is NULL.\n"); - return; - } - /* 需要开发者自行添加具体实现 */ -} - -int32_t ret; -/* 注册SDIO中断 */ -ret = SdioClaimIrq(handle, SdioIrqFunc); -if (ret != 0) { - HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); -} -``` - -## 进行SDIO通信 - -- 向SDIO设备增量写入指定长度的数据 - -对应的接口函数如下所示: - -int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 5** SdioWriteBytes函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

data

-

待写入数据的指针

-

addr

-

待写入数据的起始地址

-

size

-

待写入数据的长度

-

返回值

-

返回值描述

-

0

-

SDIO写数据成功

-

负数

-

SDIO写数据失败

-
- -向SDIO设备增量写入指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t wbuff[] = {1,2,3,4,5}; -uint32_t addr = 0x100 + 0x09; -/* 向SDIO设备起始地址0x109,增量写入5个字节的数据 */ -ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0])); -if (ret != 0) { - HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); -} -``` - -- 从SDIO设备增量读取指定长度的数据 - -对应的接口函数如下所示: - -int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 6** SdioReadBytes函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

data

-

接收读取数据的指针

-

addr

-

待读取数据的起始地址

-

size

-

待读取数据的长度

-

返回值

-

返回值描述

-

0

-

SDIO读数据成功

-

负数

-

SDIO读数据失败

-
- -从SDIO设备增量读取指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t rbuff[5] = {0}; -uint32_t addr = 0x100 + 0x09; -/* 从SDIO设备起始地址0x109,增量读取5个字节的数据 */ -ret = SdioReadBytes(handle, rbuff, addr, 5); -if (ret != 0) { - HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); -} -``` - -- 向SDIO设备的固定地址写入指定长度的数据 - - 对应的接口函数如下所示: - - int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); - - **表 7** SdioWriteBytesToFixedAddr函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

data

-

待写入数据的指针

-

addr

-

待写入数据的固定地址

-

size

-

待写入数据的长度

-

scatterLen

-

集散表的长度。如果该字段不为0,则data为集散表类型。

-

返回值

-

返回值描述

-

0

-

SDIO写数据成功

-

负数

-

SDIO写数据失败

-
- - 向SDIO设备的固定地址写入指定长度的数据的示例如下: - - ``` - int32_t ret; - uint8_t wbuff[] = {1,2,3,4,5}; - uint32_t addr = 0x100 + 0x09; - /* 向SDIO设备固定地址0x109写入5个字节的数据 */ - ret = SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0); - if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); - } - ``` - -- 从SDIO设备的固定地址读取指定长度的数据 - - 对应的接口函数如下所示: - - int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); - - **表 8** SdioReadBytesFromFixedAddr函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

data

-

接收读取数据的指针

-

addr

-

待读取数据的起始地址

-

size

-

待读取数据的长度

-

scatterLen

-

集散表的长度。如果该字段不为0,则data为集散表类型。

-

返回值

-

返回值描述

-

0

-

SDIO读数据成功

-

负数

-

SDIO读数据失败

-
- - 从SDIO设备的固定地址读取指定长度的数据的示例如下: - - ``` - int32_t ret; - uint8_t rbuff[5] = {0}; - uint32_t addr = 0x100 + 0x09; - /* 从SDIO设备固定地址0x109中读取5个字节的数据 */ - ret = SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0); - if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); - } - ``` - - -- 向SDIO function 0的指定地址空间写入指定长度的数据 - -当前只支持写入一个字节的数据,对应的接口函数如下所示: - -int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 9** SdioWriteBytesToFunc0函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

data

-

待写入数据的指针

-

addr

-

待写入数据的起始地址

-

size

-

待写入数据的长度

-

返回值

-

返回值描述

-

0

-

SDIO写数据成功

-

负数

-

SDIO写数据失败

-
- -向SDIO function 0的指定地址空间写入指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t wbuff = 1; -/* 向SDIO function 0地址0x2中写入1字节的数据 */ -ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1); -if (ret != 0) { - HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); -} -``` - -- 从SDIO function 0的指定地址空间读取指定长度的数据 - -当前只支持读取一个字节的数据,对应的接口函数如下所示: - -int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); - -**表 10** SdioReadBytesFromFunc0函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

data

-

接收读取数据的指针

-

addr

-

待读取数据的起始地址

-

size

-

待读取数据的长度

-

返回值

-

返回值描述

-

0

-

SDIO读数据成功

-

负数

-

SDIO读数据失败

-
- -从SDIO function 0的指定地址空间读取指定长度的数据的示例如下: - -``` -int32_t ret; -uint8_t rbuff; -/* 从SDIO function 0设备地址0x2中读取1字节的数据 */ -ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1); -if (ret != 0) { - HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); -} -``` - -## 释放SDIO中断 - -通信完成之后,需要释放SDIO中断,函数如下所示: - -int32\_t SdioReleaseIrq\(DevHandle handle\); - -**表 11** SdioReleaseIrq函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

返回值

-

返回值描述

-

0

-

释放SDIO中断成功

-

负数

-

释放SDIO中断失败

-
- -释放SDIO中断的示例如下: - -``` -int32_t ret; -/* 释放SDIO中断 */ -ret = SdioReleaseIrq(handle); -if (ret != 0) { - HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); -} -``` - -## 去使能SDIO设备 - -通信完成之后,还需要去使能SDIO设备,函数如下所示: - -int32\_t SdioDisableFunc\(DevHandle handle\); - -**表 12** SdioDisableFunc函数的参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-

返回值

-

返回值描述

-

0

-

去使能SDIO设备成功

-

负数

-

去使能SDIO设备失败

-
- -去使能SDIO设备的示例如下: - -``` -int32_t ret; -/* 去使能SDIO设备 */ -ret = SdioDisableFunc(handle); -if (ret != 0) { - HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); -} -``` - -## 释放HOST - -通信完成之后,还需要释放去HOST,函数如下所示: - -void SdioReleaseHost\(DevHandle handle\); - -**表 13** SdioReleaseHost函数的参数描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-
- -释放HOST的示例如下: - -``` -SdioReleaseHost(handle); /* 释放HOST */ -``` - -## 关闭SDIO控制器 - -SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示: - -void SdioClose\(DevHandle handle\); - -该函数会释放掉申请的资源。 - -**表 14** SdioClose函数的参数描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SDIO控制器的设备句柄

-
- -关闭SDIO控制器的示例如下: - -``` -SdioClose(handle); /* 关闭SDIO控制器 */ -``` - diff --git "a/zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" deleted file mode 100755 index 69b74874472f27c6f3d737e8383f80708ae654a7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/SDIO\346\246\202\350\277\260.md" +++ /dev/null @@ -1,149 +0,0 @@ -# SDIO概述 - -- [简介](#section1155271783811) -- [接口说明](#section10204143763819) - -## 简介 - -- SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。 -- SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。 -- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示: - - - CLK信号:HOST给DEVICE的时钟信号。 - - VDD信号:电源信号。 - - VSS信号:Ground信号。 - - D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 - - CMD信号:用于HOST发送命令和DEVICE回复响应。 - - **图 1** SDIO的HOST-DEVICE连接示意图 - - - ![](figures/zh-cn_image_0000001054280608.png) - -- SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。 - -## 接口说明 - -**表 1** SDIO驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

SDIO设备打开/关闭接口

-

SdioOpen

-

打开指定总线号的SDIO控制器

-

SdioClose

-

关闭SDIO控制器

-

SDIO读写接口

-

SdioReadBytes

-

从指定地址开始,增量读取指定长度的数据

-

SdioWriteBytes

-

从指定地址开始,增量写入指定长度的数据

-

SdioReadBytesFromFixedAddr

-

从固定地址读取指定长度的数据

-

SdioWriteBytesToFixedAddr

-

向固定地址写入指定长度的数据

-

SdioReadBytesFromFunc0

-

从SDIO function 0的指定地址空间读取指定长度的数据

-

SdioWriteBytesToFunc0

-

向SDIO function 0的指定地址空间写入指定长度的数据

-

SDIO设置块大小接口

-

SdioSetBlockSize

-

设置块的大小

-

SDIO获取/设置公共信息接口

-

SdioGetCommonInfo

-

获取公共信息

-

SdioSetCommonInfo

-

设置公共信息

-

SDIO刷新数据接口

-

SdioFlushData

-

刷新数据

-

SDIO独占/释放HOST接口

-

SdioClaimHost

-

独占Host

-

SdioReleaseHost

-

释放Host

-

SDIO使能/去使能功能设备接口

-

SdioEnableFunc

-

使能SDIO功能设备

-

SdioDisableFunc

-

去使能SDIO功能设备

-

SDIO申请/释放中断接口

-

SdioClaimIrq

-

申请中断

-

SdioReleaseIrq

-

释放中断

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/SENSOR.md b/zh-cn/device-dev/driver/SENSOR.md deleted file mode 100755 index 5907809028cf4b2f14cf484c96adbd8c25a57db2..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/SENSOR.md +++ /dev/null @@ -1,11 +0,0 @@ -# SENSOR - -- **[传感器驱动开发概述](传感器驱动开发概述.md)** - -- **[传感器驱动开发指导](传感器驱动开发指导.md)** - -- **[传感器驱动开发实例](传感器驱动开发实例.md)** - -- **[传感器驱动测试指导](传感器驱动测试指导.md)** - - diff --git a/zh-cn/device-dev/driver/SPI.md b/zh-cn/device-dev/driver/SPI.md deleted file mode 100755 index 394692a78397c81a270b1cc0e5e944c4837336ab..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/SPI.md +++ /dev/null @@ -1,9 +0,0 @@ -# SPI - -- **[SPI概述](SPI概述.md)** - -- **[SPI使用指导](SPI使用指导.md)** - -- **[SPI使用实例](SPI使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 4c3a6280301b448fad37b861d0028fd737ef2f82..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,70 +0,0 @@ -# SPI使用实例 - -SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 - -``` -#include "hdf_log.h" -#include "spi_if.h" - -void SpiTestSample(void) -{ - int32_t ret; - struct SpiCfg cfg; /* SPI配置信息 */ - struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ - DevHandle spiHandle = NULL; /* SPI设备句柄 */ - struct SpiMsg msg; /* 自定义传输的消息 */ - uint8_t rbuff[4] = { 0 }; - uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 }; - uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 }; - - spiDevinfo.busNum = 0; /* SPI设备总线号 */ - spiDevinfo.csNum = 0; /* SPI设备片选号 */ - spiHandle = SpiOpen(&spiDevinfo); /* 根据spiDevinfo获取SPI设备句柄 */ - if (spiHandle == NULL) { - HDF_LOGE("SpiOpen: failed\n"); - return; - } - /* 获取SPI设备属性 */ - ret = SpiGetCfg(spiHandle, &cfg); - if (ret != 0) { - HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); - goto err; - } - cfg.maxSpeedHz = 115200; /* 将最大时钟频率改为115200 */ - cfg.bitsPerWord = 8; /* 传输位宽改为8比特 */ - /* 配置SPI设备属性 */ - ret = SpiSetCfg(spiHandle, &cfg); - if (ret != 0) { - HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); - goto err; - } - /* 向SPI设备写入指定长度的数据 */ - ret = SpiWrite(spiHandle, wbuff, 4); - if (ret != 0) { - HDF_LOGE("SpiWrite: failed, ret %d\n", ret); - goto err; - } - /* 从SPI设备读取指定长度的数据 */ - ret = SpiRead(spiHandle, rbuff, 4); - if (ret != 0) { - HDF_LOGE("SpiRead: failed, ret %d\n", ret); - goto err; - } - msg.wbuf = wbuff2; /* 写入的数据 */ - msg.rbuf = rbuff; /* 读取的数据 */ - msg.len = 4; /* 读取写入数据的长度为4 */ - msg.csChange = 1; /* 进行下一次传输前关闭片选 */ - msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ - msg.speed = 115200; /* 本次传输的速度 */ - /* 进行一次自定义传输,传输的msg个数为1 */ - ret = SpiTransfer(spiHandle, &msg, 1); - if (ret != 0) { - HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); - goto err; - } -err: - /* 销毁SPI设备句柄 */ - SpiClose(spiHandle); -} -``` - diff --git "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 58698a9460cefc157fd27f41bfb3978a1547fdfc..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/SPI\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,386 +0,0 @@ -# SPI使用指导 - -- [使用流程](#section691514116412) -- [获取SPI设备句柄](#section12372204616215) -- [获取SPI设备属性](#section17121446171311) -- [配置SPI设备属性](#section97691946634) -- [进行SPI通信](#section197116254416) -- [销毁SPI设备句柄](#section117661819108) - -## 使用流程 - -使用SPI的一般流程如[图1](#fig23885455594)所示。 - -**图 1** SPI使用流程图 - - -![](figures/zh-cn_image_0000001054726248.png) - -## 获取SPI设备句柄 - -在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 - -DevHandle SpiOpen\(const struct SpiDevInfo \*info\); - -**表 1** SpiOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

info

-

SPI设备描述符

-

返回值

-

返回值描述

-

NULL

-

获取SPI设备句柄失败

-

设备句柄

-

对应的SPI设备句柄

-
- -假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: - -``` -struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ -DevHandle spiHandle = NULL; /* SPI设备句柄 */ -spiDevinfo.busNum = 0; /* SPI设备总线号 */ -spiDevinfo.csNum = 0; /* SPI设备片选号 */ - -/* 获取SPI设备句柄 */ -spiHandle = SpiOpen(&spiDevinfo); -if (spiHandle == NULL) { - HDF_LOGE("SpiOpen: failed\n"); - return; -} -``` - -## 获取SPI设备属性 - -在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: - -int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\); - -**表 2** SpiGetCfg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SPI设备句柄

-

cfg

-

SPI设备配置参数

-

返回值

-

返回值描述

-

0

-

获取配置成功

-

负数

-

获取配置失败

-
- -``` -int32_t ret; -struct SpiCfg cfg = {0}; /* SPI配置信息*/ -ret = SpiGetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ -if (ret != 0) { - HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); -} -``` - -## 配置SPI设备属性 - -在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: - -int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\); - -**表 3** SpiSetCfg参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SPI设备句柄

-

cfg

-

SPI设备配置参数

-

返回值

-

返回值描述

-

0

-

配置成功

-

负数

-

配置失败

-
- -``` -int32_t ret; -struct SpiCfg cfg = {0}; /* SPI配置信息*/ -cfg.mode = SPI_MODE_LOOP; /* 以回环模式进行通信 */ -cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* 以轮询的方式进行通信 */ -cfg.maxSpeedHz = 115200; /* 最大传输频率 */ -cfg.bitsPerWord = 8; /* 读写位宽为8个比特 */ -ret = SpiSetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ -if (ret != 0) { - HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); -} -``` - -## 进行SPI通信 - -- 向SPI设备写入指定长度的数据 - -如果只向SPI设备写一次数据,则可以通过以下函数完成: - -int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); - -**表 4** SpiWrite参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SPI设备句柄

-

buf

-

待写入数据的指针

-

len

-

待写入的数据长度

-

返回值

-

返回值描述

-

0

-

写入成功

-

负数

-

写入失败

-
- -``` -int32_t ret; -uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; -/* 向SPI设备写入指定长度的数据 */ -ret = SpiWrite(spiHandle, wbuff, 4); -if (ret != 0) { - HDF_LOGE("SpiWrite: failed, ret %d\n", ret); -} -``` - -- 从SPI设备读取指定长度的数据 - -如果只读取一次数据,则可以通过以下函数完成: - -int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); - -**表 5** SpiRead参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SPI设备句柄

-

buf

-

待读取数据的指针

-

len

-

待读取的数据长度

-

返回值

-

返回值描述

-

0

-

读取成功

-

负数

-

读取失败

-
- -``` -int32_t ret; -uint8_t rbuff[4] = {0}; -/* 从SPI设备读取指定长度的数据 */ -ret = SpiRead(spiHandle, rbuff, 4); -if (ret != 0) { - HDF_LOGE("SpiRead: failed, ret %d\n", ret); -} -``` - -- 自定义传输 - -如果需要发起一次自定义传输,则可以通过以下函数完成: - -int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\); - -**表 6** SpiTransfer参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

SPI设备句柄

-

msgs

-

待传输数据的数组

-

count

-

msgs数组长度

-

返回值

-

返回值描述

-

0

-

执行成功

-

负数

-

执行失败

-
- -``` -int32_t ret; -uint8_t wbuff[1] = {0x12}; -uint8_t rbuff[1] = {0}; -struct SpiMsg msg; /* 自定义传输的消息*/ -msg.wbuf = wbuff; /* 写入的数据 */ -msg.rbuf = rbuff; /* 读取的数据 */ -msg.len = 1; /* 读取、写入数据的长度都是1 */ -msg.csChange = 1; /* 进行下一次传输前关闭片选 */ -msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ -msg.speed = 115200; /* 本次传输的速度 */ -/* 进行一次自定义传输,传输的msg个数为1 */ -ret = SpiTransfer(spiHandle, &msg, 1); -if (ret != 0) { - HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); -} -``` - -## 销毁SPI设备句柄 - -SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: - -void SpiClose\(DevHandle handle\); - -该函数会释放掉申请的资源。 - -**表 7** SpiClose参数描述 - - - - - - - - - -

参数

-

参数描述

-

handle

-

SPI设备句柄

-
- -``` -SpiClose(spiHandle); /* 销毁SPI设备句柄 */ -``` - diff --git "a/zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" deleted file mode 100755 index 3d3567489af059b7a5f56b8e072bdab95e190eab..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/SPI\346\246\202\350\277\260.md" +++ /dev/null @@ -1,107 +0,0 @@ -# SPI概述 - -- [简介](#section9202632114011) -- [接口说明](#section1859594134119) - -## 简介 - -- SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。 -- SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。 -- SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: - - SCLK – 时钟信号,由主设备产生; - - MOSI – 主设备数据输出,从设备数据输入; - - MISO – 主设备数据输入,从设备数据输出; - - CS – 片选,从设备使能信号,由主设备控制。 - - -- 一个主设备和两个从设备的连接示意图如[图1](#fig15227181812587)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 - -**图 1** SPI主从设备连接示意图。 - - -![](figures/zh-cn_image_0000001054142582.png) - -- SPI通信通常由主设备发起,通过以下步骤完成一次通信: - -1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 -2. 通过SCLK给选中的从设备提供时钟信号。 -3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。 - -- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: - - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 - - CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。 - - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 - - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 - - -- SPI接口定义了操作SPI设备的通用方法集合,包括: - - SPI设备句柄获取和释放。 - - SPI读写: 从SPI设备读取或写入指定长度数据。 - - SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 - - SPI设备配置:获取和设置SPI设备属性。 - - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前只支持主机模式,不支持从机模式。 - -## 接口说明 - -**表 1** SPI驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

SPI设备句柄获取释放接口

-

SpiOpen

-

获取SPI设备句柄

-

SpiClose

-

释放SPI设备句柄

-

SPI读写接口

-

SpiRead

-

读取指定长度的数据

-

SpiWrite

-

写入指定长度的数据

-

SpiTransfer

-

SPI数据传输接口

-

SPI设备配置接口

-

-

SpiSetCfg

-

根据指定参数,配置SPI设备

-

SpiGetCfg

-

获取SPI设备配置参数

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/TOUCHSCREEN.md b/zh-cn/device-dev/driver/TOUCHSCREEN.md deleted file mode 100755 index ce5156c848cb3b1ae5403caeb17ae4d9714baadb..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/TOUCHSCREEN.md +++ /dev/null @@ -1,9 +0,0 @@ -# TOUCHSCREEN - -- **[Touchscreen开发概述](Touchscreen开发概述.md)** - -- **[Touchscreen开发指导](Touchscreen开发指导.md)** - -- **[Touchscreen开发实例](Touchscreen开发实例.md)** - - diff --git "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index a298d618c1547f7c66c6213a42563b3896ac80b2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,300 +0,0 @@ -# Touchscreen开发实例 - -- [设备描述配置](#section85281142102317) -- [板级配置及器件私有配置](#section189081946192410) -- [添加器件驱动](#section19856687253) - -本实例提供touchscreen驱动开发示例,并简要对具体关键点进行开发说明。 - -## 设备描述配置 - -如下配置主要包含input驱动模型各模块层级信息,具体原理可参考[HDF驱动开发指南](驱动开发.md),HDF框架依据该配置信息实现对Input模型各模块的依次加载等。 - -``` -input :: host { - hostName = "input_host"; - priority = 100; - device_input_manager :: device { - device0 :: deviceNode { - policy = 2; // 向外发布服务 - priority = 100; // 加载优先级,在input模块内,manager模块优先级应为最高 - preload = 0; // 加载该驱动 0:加载 1:不加载 - permission = 0660; - moduleName = "HDF_INPUT_MANAGER"; - serviceName = "input_dev_manager"; - deviceMatchAttr = ""; - } - } - device_hdf_touch :: device { - device0 :: deviceNode { - policy = 2; - priority = 120; - preload = 0; - permission = 0660; - moduleName = "HDF_TOUCH"; - serviceName = "event1"; - deviceMatchAttr = "touch_device1"; - } - } - - device_touch_chip :: device { - device0 :: deviceNode { - policy = 0; - priority = 130; - preload = 0; - permission = 0660; - moduleName = "HDF_TOUCH_SAMPLE"; - serviceName = "hdf_touch_sample_service"; - deviceMatchAttr = "zsj_sample_5p5"; - } - } -} -``` - -## 板级配置及器件私有配置 - -如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。 - -``` -root { - input_config { - touchConfig { - touch0 { - boardConfig { - match_attr = "touch_device1"; - inputAttr { - inputType = 0; // 0代表触摸屏 - solutionX = 480; - solutionY = 960; - devName = "main_touch"; // 设备名称 - } - busConfig { - busType = 0; // 0代表I2C - busNum = 6; - clkGpio = 86; - dataGpio = 87; - i2cClkIomux = [0x114f0048, 0x403]; // i2c_clk对应pin的寄存器配置 - i2cDataIomux = [0x114f004c, 0x403]; // i2c_data对应pin的寄存器配置 - } - pinConfig { - rstGpio = 3; - intGpio = 4; - rstRegCfg = [0x112f0094, 0x400]; // reset对应pin的寄存器配置 - intRegCfg = [0x112f0098, 0x400]; // interrupt对应pin的寄存器配置 - } - powerConfig { - vccType = 2; // 1代表LDO、2代表GPIO、3代表PMIC - vccNum = 20; // GPIO号为20 - vccValue = 1800; // 电压幅值为1800mV - vciType = 1; - vciNum = 12; - vciValue = 3300; - } - featureConfig { - capacitanceTest = 0; - gestureMode = 0; - gloverMOde = 0; - coverMode = 0; - chargerMode = 0; - knuckleMode = 0; - } - } - chipConfig { - template touchChip { - match_attr = ""; - chipName = "sample"; - vendorName = "zsj"; - chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 - busType = 0; - deviceAddr = 0x5D; - irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 - maxSpeed = 400; - chipVersion = 0; - powerSequence { - /* 上电时序的配置含义说明: - [类型, 状态, 方向 , 延时] - 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 - 0代表下电或拉低,1代表上电或拉高,2代表无操作 - 0代表输入方向,1代表输出方向,2代表无操作 - 代表延时多少毫秒, 例如20代表延时20ms - */ - powerOnSeq = [4, 0, 1, 0, - 3, 0, 1, 10, - 3, 1, 2, 60, - 4, 2, 0, 0]; - suspendSeq = [3, 0, 2, 10]; - resumeSeq = [3, 1, 2, 10]; - powerOffSeq = [3, 0, 2, 10, - 1, 0, 2, 20]; - } - } - chip0 :: touchChip { - match_attr = "zsj_sample_5p5"; - chipInfo = "ZIDN45100"; - chipVersion = 0; - } - } - } - } - } -} -``` - -## 添加器件驱动 - -在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。 - -``` -/* 将从器件中读取到的报点数据解析为坐标 */ -static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) -{ - int32_t resX = device->driver->boardCfg->attr.resolutionX; - int32_t resY = device->driver->boardCfg->attr.resolutionY; - - for (int32_t i = 0; i < pointNum; i++) { - frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - frame->fingers[i].valid = true; - } -} -/* 从器件中获取报点数据 */ -static int32_t ChipDataHandle(ChipDevice *device) -{ - int32_t ret; - uint8_t touchStatus = 0; - uint8_t pointNum; - uint8_t buf[GT_POINT_SIZE * MAX_SUPPORT_POINT] = {0}; - InputI2cClient *i2cClient = &device->driver->i2cClient; - uint8_t reg[GT_ADDR_LEN] = {0}; - FrameData *frame = &device->driver->frameData; - reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; - ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); - if (ret < 0 || touchStatus == GT_EVENT_INVALID) { - return HDF_FAILURE; - } - OsalMutexLock(&device->driver->mutex); - (void)memset_s(frame, sizeof(FrameData), 0, sizeof(FrameData)); - if (touchStatus == GT_EVENT_UP) { - frame->realPointNum = 0; - frame->definedEvent = TOUCH_UP; - goto exit; - } - reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; - pointNum = touchStatus & GT_FINGER_NUM_MASK; - if (pointNum <= 0 || pointNum > MAX_SUPPORT_POINT) { - HDF_LOGE("%s: pointNum is invalid, %d", __func__, pointNum); - (void)ChipCleanBuffer(i2cClient); - OsalMutexUnlock(&device->driver->mutex); - return HDF_FAILURE; - } - frame->realPointNum = pointNum; - frame->definedEvent = TOUCH_DOWN; - /* 从寄存器中读取报点值 */ - (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); - /* 解析报点值 */ - ParsePointData(device, frame, buf, pointNum); -exit: - OsalMutexUnlock(&device->driver->mutex); - if (ChipCleanBuffer(i2cClient) != HDF_SUCCESS) { - return HDF_FAILURE; - } - return HDF_SUCCESS; -} - -static struct TouchChipOps g_sampleChipOps = { - .Init = ChipInit, - .Detect = ChipDetect, - .Resume = ChipResume, - .Suspend = ChipSuspend, - .DataHandle = ChipDataHandle, -}; - -static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device) -{ - TouchChipCfg *chipCfg = (TouchChipCfg *)OsalMemAlloc(sizeof(TouchChipCfg)); - if (chipCfg == NULL) { - HDF_LOGE("%s: instance chip config failed", __func__); - return NULL; - } - (void)memset_s(chipCfg, sizeof(TouchChipCfg), 0, sizeof(TouchChipCfg)); - /* 解析器件私有配置 */ - if (ParseTouchChipConfig(device->property, chipCfg) != HDF_SUCCESS) { - HDF_LOGE("%s: parse chip config failed", __func__); - OsalMemFree(chipCfg); - chipCfg = NULL; - } - return chipCfg; -} - -static ChipDevice *ChipDeviceInstance(void) -{ - ChipDevice *chipDev = (ChipDevice *)OsalMemAlloc(sizeof(ChipDevice)); - if (chipDev == NULL) { - HDF_LOGE("%s: instance chip device failed", __func__); - return NULL; - } - (void)memset_s(chipDev, sizeof(ChipDevice), 0, sizeof(ChipDevice)); - return chipDev; -} - -static void FreeChipConfig(TouchChipCfg *config) -{ - if (config->pwrSeq.pwrOn.buf != NULL) { - OsalMemFree(config->pwrSeq.pwrOn.buf); - } - if (config->pwrSeq.pwrOff.buf != NULL) { - OsalMemFree(config->pwrSeq.pwrOff.buf); - } - OsalMemFree(config); -} - -static int32_t HdfSampleChipInit(struct HdfDeviceObject *device) -{ - TouchChipCfg *chipCfg = NULL; - ChipDevice *chipDev = NULL; - HDF_LOGE("%s: enter", __func__); - if (device == NULL) { - return HDF_ERR_INVALID_PARAM; - } - /* 器件私有配置解析 */ - chipCfg = ChipConfigInstance(device); - if (chipCfg == NULL) { - return HDF_ERR_MALLOC_FAIL; - } - /* 器件设备实例化 */ - chipDev = ChipDeviceInstance(); - if (chipDev == NULL) { - goto freeCfg; - } - chipDev->chipCfg = chipCfg; - chipDev->ops = &g_sampleChipOps; - chipDev->chipName = chipCfg->chipName; - chipDev->vendorName = chipCfg->vendorName; - - /* 器件设备注册到平台驱动 */ - if (RegisterChipDevice(chipDev) != HDF_SUCCESS) { - goto freeDev; - } - HDF_LOGI("%s: exit succ, chipName = %s", __func__, chipCfg->chipName); - return HDF_SUCCESS; - -freeDev: - OsalMemFree(chipDev); -freeCfg: - FreeChipConfig(chipCfg); - return HDF_FAILURE; -} - -struct HdfDriverEntry g_touchSampleChipEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH_SAMPLE", - .Init = HdfSampleChipInit, -}; - -HDF_INIT(g_touchSampleChipEntry); -``` - diff --git "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 09dc518533e0397fd75711d33a582a7520c5af39..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,36 +0,0 @@ -# Touchscreen开发指导 - -- [开发步骤](#section1255740132616) - -Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。 - -- 如下以touchscreen器件驱动为例,说明input驱动模型的完整加载流程: - - (1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 - - (2)加载input设备管理驱动:input设备管理驱动由HDF驱动加载,完成设备manager的创建并对其初始化。 - - (3)加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。 - - (4)加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。 - - (5)器件设备向平台驱动注册:将实例化的器件设备向平台驱动注册,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。 - - (6)input设备注册:在器件初始化完成后,实例化input设备,并将其注册到input manager进行管理。 - - -## 开发步骤 - -1. 设备描述配置 - - 目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](驱动开发.md#section1969312275533)。 - -2. 板级配置及Touchscreen器件私有配置 - - 配置对应的IO管脚功能,例如对单板上为touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。 - -3. 实现器件差异化适配接口 - - 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](GPIO使用指导.md) - - diff --git "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index b6456936b0195199ef6f29d12e690492892bbda0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/Touchscreen\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,71 +0,0 @@ -# Touchscreen开发概述 - -- [简介](#section124332411260) -- [接口说明](#section10542625172618) - -## 简介 - -- **Touchscreen驱动主要任务** - - Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定input相关配置、下载及更新固件等操作。 - - -- **Touchscreen驱动层次说明** - - 本节主要介绍基于input驱动模型开发touchscreen器件驱动,其整体的框架模型如[图1](#fig6251184817261)。 - - Input驱动模型基于HDF驱动框架、PLATFORM接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。 - - -**图 1** 基于HDF驱动框架的input驱动模型 -![](figures/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型") - -- **Input驱动模型介绍** - - Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明: - - (1)input设备管理:为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; - - (2)input平台驱动:指各类input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; - - (3)input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; - - (4)input数据通道:提供一套通用的数据上报通道,各类别的input设备驱动均可用此通道上报input事件; - - (5)input配置解析:负责对input设备的板级配置及器件私有配置进行解析及管理。 - - -- **基于HDF驱动框架开发器件驱动的优势** - - 在HDF(Hardware Driver Foundation)[驱动管理框架](驱动开发.md)的基础上,input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。 - - -## 接口说明 - -Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: - -- 电源接口 -- IO控制接口 -- 通信接口 - -**图 2** Touchscreen器件常用管脚 -![](figures/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚") - -如上图所示的三类接口,分别做简要说明如下: - -1. **电源接口** - - LDO\_1P8:1.8v数字电路 - - LDO\_3P3:3.3v模拟电路 - - 通常情况下,touchscreen驱动IC和LCD驱动IC是相互分离的,这种情况下,touchscreen驱动IC一般同时需要1.8v和3.3v两路供电。随着芯片演进,业内已有touchscreen驱动IC和LCD驱动IC集成在一颗IC中的芯片案例,对touchscreen而言,只需要关注1.8v供电即可,其内部需要的3.3v电源,会在驱动IC内部从LCD的VSP电源(典型值5.5V)中分出来。 - - -2. **IO控制接口** - - Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。 - - INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。 - -3. **通信接口** - - I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](I2C使用指导.md)。 - - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](SPI使用指导.md)。 - - diff --git a/zh-cn/device-dev/driver/UART.md b/zh-cn/device-dev/driver/UART.md deleted file mode 100755 index 5d81f12e15f43bdf7e3302bc33cf1dddd524b4e9..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/UART.md +++ /dev/null @@ -1,9 +0,0 @@ -# UART - -- **[UART概述](UART概述.md)** - -- **[UART使用指导](UART使用指导.md)** - -- **[UART使用实例](UART使用实例.md)** - - diff --git "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index d049e3d021843a422c3e11b1fde5a10b57393070..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,67 +0,0 @@ -# UART使用实例 - -UART设备完整的使用示例如下所示,首先获取UART设备句柄,接着设置波特率、设备属性和传输模式,之后进行UART通信,最后销毁UART设备句柄。 - -``` -#include "hdf_log.h" -#include "uart_if.h" - -void UartTestSample(void) -{ - int32_t ret; - uint32_t port; - DevHandle handle = NULL; - uint8_t wbuff[5] = { 1, 2, 3, 4, 5 }; - uint8_t rbuff[5] = { 0 }; - struct UartAttribute attribute; - attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ - attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ - attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ - attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ - attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ - attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ - attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ - /* UART设备端口号,要填写实际平台上的端口号 */ - port = 1; - /* 获取UART设备句柄 */ - handle = UartOpen(port); - if (handle == NULL) { - HDF_LOGE("UartOpen: failed!\n"); - return; - } - /* 设置UART波特率为9600 */ - ret = UartSetBaud(handle, 9600); - if (ret != 0) { - HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); - goto _ERR; - } - /* 设置UART设备属性 */ - ret = UartSetAttribute(handle, &attribute); - if (ret != 0) { - HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); - goto _ERR; - } - /* 设置UART传输模式为非阻塞模式 */ - ret = UartSetTransMode(handle, UART_MODE_RD_NONBLOCK); - if (ret != 0) { - HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); - goto _ERR; - } - /* 向UART设备写入5字节的数据 */ - ret = UartWrite(handle, wbuff, 5); - if (ret != 0) { - HDF_LOGE("UartWrite: failed, ret %d\n", ret); - goto _ERR; - } - /* 从UART设备读取5字节的数据 */ - ret = UartRead(handle, rbuff, 5); - if (ret < 0) { - HDF_LOGE("UartRead: failed, ret %d\n", ret); - goto _ERR; - } -_ERR: - /* 销毁UART设备句柄 */ - UartClose(handle); -} -``` - diff --git "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 1d1ee50a8c13e37c506350820c71a5a7b4893d7f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/UART\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,506 +0,0 @@ -# UART使用指导 - -- [使用流程](#section47784125013) -- [获取UART设备句柄](#section146445153110) -- [UART设置波特率](#section1862705516339) -- [UART获取波特率](#section1263651563414) -- [UART设置设备属性](#section1770091483814) -- [UART获取设备属性](#section117543316384) -- [设置UART传输模式](#section187233112369) -- [向UART设备写入指定长度的数据](#section82416423368) -- [从UART设备中读取指定长度的数据](#section192177171373) -- [销毁UART设备句柄](#section63131236354) - -## 使用流程 - -使用UART的一般流程如[图1](#p58686354483)所示。 - -**图 1** UART使用流程图 - - -![](figures/zh-cn_image_0000001054006983.png) - -## 获取UART设备句柄 - -在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。 - -DevHandle UartOpen\(uint32\_t port\); - -**表 1** UartOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

port

-

UART设备号

-

返回值

-

返回值描述

-

NULL

-

获取UART设备句柄失败

-

设备句柄

-

UART设备句柄

-
- -假设系统中的UART端口号为3,获取该UART设备句柄的示例如下: - -``` -DevHandle handle = NULL; /* UART设备句柄 */ -uint32_t port = 3; /* UART设备端口号 */ -handle = UartOpen(port); -if (handle == NULL) { - HDF_LOGE("UartOpen: failed!\n"); - return; -} -``` - -## UART设置波特率 - -在通信之前,需要设置UART的波特率,设置波特率的函数如下所示: - -int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\); - -**表 2** UartSetBaud参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

baudRate

-

待设置的波特率值

-

返回值

-

返回值描述

-

0

-

UART设置波特率成功

-

负数

-

UART设置波特率失败

-
- -假设需要设置的UART波特率为9600,设置波特率的实例如下: - -``` -int32_t ret; -/* 设置UART波特率 */ -ret = UartSetBaud(handle, 9600); -if (ret != 0) { - HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); -} -``` - -## UART获取波特率 - -设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率,获取波特率的函数如下所示: - -int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\); - -**表 3** UartGetBaud参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

baudRate

-

接收波特率值的指针

-

返回值

-

返回值描述

-

0

-

UART获取波特率成功

-

负数

-

UART获取波特率失败

-
- -获取波特率的实例如下: - -``` -int32_t ret; -uint32_t baudRate; -/* 获取UART波特率 */ -ret = UartGetBaud(handle, &baudRate); -if (ret != 0) { - HDF_LOGE("UartGetBaud: failed, ret %d\n", ret); -} -``` - -## UART设置设备属性 - -在通信之前,需要设置UART的设备属性,设置设备属性的函数如下图所示: - -int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); - -**表 4** UartSetAttribute参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

attribute

-

待设置的设备属性

-

返回值

-

返回值描述

-

0

-

UART设置设备属性成功

-

负数

-

UART设置设备属性失败

-
- -设置UART的设备属性的实例如下: - -``` -int32_t ret; -struct UartAttribute attribute; -attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ -attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ -attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ -attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ -attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ -attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ -attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ -/* 设置UART设备属性 */ -ret = UartSetAttribute(handle, &attribute); -if (ret != 0) { - HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); -} -``` - -## UART获取设备属性 - -设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性,获取设备属性的函数如下图所示: - -int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); - -**表 5** UartGetAttribute参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

attribute

-

接收UART设备属性的指针

-

返回值

-

返回值描述

-

0

-

UART获取设备属性成功

-

负数

-

UART获取设备属性失败

-
- -获取UART的设备属性的实例如下: - -``` -int32_t ret; -struct UartAttribute attribute; -/* 获取UART设备属性 */ -ret = UartGetAttribute(handle, &attribute); -if (ret != 0) { - HDF_LOGE("UartGetAttribute: failed, ret %d\n", ret); -} -``` - -## 设置UART传输模式 - -在通信之前,需要设置UART的传输模式,设置传输模式的函数如下图所示: - -int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\); - -**表 6** UartSetTransMode参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

mode

-

待设置的传输模式,

-

返回值

-

返回值描述

-

0

-

UART设置传输模式成功

-

负数

-

UART设置传输模式失败

-
- -假设需要设置的UART传输模式为UART\_MODE\_RD\_BLOCK,设置传输模式的实例如下: - -``` -int32_t ret; -/* 设置UART传输模式 */ -ret = UartSetTransMode(handle, UART_MODE_RD_BLOCK); -if (ret != 0) { - HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); -} -``` - -## 向UART设备写入指定长度的数据 - -对应的接口函数如下所示: - -int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\); - -**表 7** UartWrite参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

data

-

待写入数据的指针

-

size

-

待写入数据的长度

-

返回值

-

返回值描述

-

0

-

UART写数据成功

-

负数

-

UART写数据失败

-
- -写入指定长度数据的实例如下: - -``` -int32_t ret; -uint8_t wbuff[5] = {1, 2, 3, 4, 5}; -/* 向UART设备写入指定长度的数据 */ -ret = UartWrite(handle, wbuff, 5); -if (ret != 0) { - HDF_LOGE("UartWrite: failed, ret %d\n", ret); -} -``` - -## 从UART设备中读取指定长度的数据 - -对应的接口函数如下所示: - -int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\); - -**表 8** UartRead参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-

data

-

接收读取数据的指针

-

size

-

待读取数据的长度

-

返回值

-

返回值描述

-

非负数

-

UART读取到的数据长度

-

负数

-

UART读取数据失败

-
- -读取指定长度数据的实例如下: - -``` -int32_t ret; -uint8_t rbuff[5] = {0}; -/* 从UART设备读取指定长度的数据 */ -ret = UartRead(handle, rbuff, 5); -if (ret < 0) { - HDF_LOGE("UartRead: failed, ret %d\n", ret); -} -``` - ->![](public_sys-resources/icon-caution.gif) **注意:** ->UART返回值为非负值,表示UART读取成功。若返回值等于0,表示UART无有效数据可以读取。若返回值大于0,表示实际读取到的数据长度,该长度小于或等于传入的参数size的大小,并且不超过当前正在使用的UART控制器规定的最大单次读取数据长度的值。 - -## 销毁UART设备句柄 - -UART通信完成之后,需要销毁UART设备句柄,函数如下所示: - -void UartClose\(DevHandle handle\); - -该函数会释放申请的资源。 - -**表 9** UartClose参数和返回值描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

UART设备句柄

-
- -销毁UART设备句柄的实例如下: - -``` -UartClose(handle); /* 销毁UART设备句柄 * -``` - diff --git "a/zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" deleted file mode 100755 index 2f295bddd98e43a9ff8670b0b5b44943243e6574..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/UART\346\246\202\350\277\260.md" +++ /dev/null @@ -1,106 +0,0 @@ -# UART概述 - -- [简介](#section14770623164917) -- [接口说明](#section149505462492) - -## 简介 - -- UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 -- UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。 -- 两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是: - - TX:发送数据端,和对端的RX相连; - - RX:接收数据端,和对端的TX相连; - - RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连; - - CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连; - - **图 1** 2线UART设备连接示意图 - - - ![](figures/zh-cn_image_0000001053926237.png) - - **图 2** 4线UART设备连接示意图 - - - ![](figures/zh-cn_image_0000001054007499.png) - - -- UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。 -- UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。 - -## 接口说明 - -**表 1** UART驱动API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

UART获取/释放设备句柄

-

-

UartOpen

-

UART获取设备句柄

-

UartClose

-

UART释放设备句柄

-

UART读写接口

-

-

UartRead

-

从UART设备中读取指定长度的数据

-

UartWrite

-

向UART设备中写入指定长度的数据

-

UART获取/设置波特率接口

-

UartGetBaud

-

UART获取波特率

-

UartSetBaud

-

UART设置波特率

-

UART获取/设置设备属性

-

-

UartGetAttribute

-

UART获取设备属性

-

UartSetAttribute

-

UART设置设备属性

-

UART设置传输模式

-

UartSetTransMode

-

UART设置传输模式

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git a/zh-cn/device-dev/driver/WATCHDOG.md b/zh-cn/device-dev/driver/WATCHDOG.md deleted file mode 100755 index 0d7afef9e34e797337223f629833ac288a532914..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/WATCHDOG.md +++ /dev/null @@ -1,9 +0,0 @@ -# WATCHDOG - -- **[看门狗概述](看门狗概述.md)** - -- **[看门狗使用指导](看门狗使用指导.md)** - -- **[看门狗使用实例](看门狗使用实例.md)** - - diff --git a/zh-cn/device-dev/driver/WLAN.md b/zh-cn/device-dev/driver/WLAN.md deleted file mode 100755 index af39a0d3a2bed463178b7cc278c21373c91ef9f1..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/driver/WLAN.md +++ /dev/null @@ -1,9 +0,0 @@ -# WLAN - -- **[WLAN开发概述](WLAN开发概述.md)** - -- **[WLAN开发指导](WLAN开发指导.md)** - -- **[WLAN开发实例](WLAN开发实例.md)** - - diff --git "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index bc558cb653344f4a82333d7c4ccdcc73815db838..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,372 +0,0 @@ -# WLAN开发实例 - -本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以hi3881WLAN芯片为例): - -1、根据硬件,修改配置参数 - -``` -/* 根据硬件参数,通过wlan_platform.hcs配置相关参数,以下是WLAN平台配置的示例 */ -hisi :& deviceList { - device0 :: deviceInst { - deviceInstId = 0; - powers { - power0 { - powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ - gpioId = 1; /* GPIO管脚号 */ - activeLevel=1; /* 有效电平:0--低;1--高 */ - } - power1 { - powerSeqDelay = 0; /* 电源序列延时 */ - powerType = 0; /* 电源类型:0--总是打开;1--GPIO */ - } - } - reset { - resetType = 0; /* 复位类型:0--不管理;1--GPIO */ - gpioId = 2; /* GPIO管脚号 */ - activeLevel=1; /* 有效电平:0--低;1--高 */ - resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ - } - bootUpTimeout = 30; /* 启动超时时间(ms) */ - bus { - busType = 0; /* 总线类型:0-sdio */ - busId = 2; /* 总线号 */ - funcNum = [1]; /* SDIO功能号 */ - timeout = 1000; /* 读/写数据的超时时间 */ - blockSize = 512; /* 读/写数据的块大小 */ - } - } -} -/* 每一块芯片添加配置文件wlan_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例 */ -root { - wlan_config { - hi3881 :& chipList { - chipHi3881 :: chipInst { - match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */ - chipName = "hi3881"; /* WLAN芯片的名称 */ - sdio { - vendorId = 0x0296; /* 厂商Id */ - deviceId = [0x5347]; /* 设备Id */ - } - } - } - } -} -``` - -2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化 - -``` -/* WLAN初始化挂接流程 */ -#include "hdf_device_desc.h" -#include "hdf_wifi_product.h" -#include "hdf_log.h" -#include "osal_mem.h" -#include "hdf_wlan_chipdriver_manager.h" -#include "securec.h" -#include "wifi_module.h" -#include "hi_wifi_api.h" -#include "hi_types_base.h" - -#define HDF_LOG_TAG Hi3881Driver - -/* WLAN芯片的初始化和去初始化函数 */ -int32_t InitHi3881Chip(struct HdfWlanDevice *device); -int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); -/* WLAN芯片驱动的初始化和去初始化函数 */ -int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); -int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); - -/* 初始化mac80211与芯片侧的函数挂接 */ -hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); - -static const char* const HI3881_DRIVER_NAME = "hisi"; - -/* WLAN芯片驱动挂接以及mac80211与芯片侧的函数挂接 */ -static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex) -{ - struct HdfChipDriver *specificDriver = NULL; - if (device == NULL) { - HDF_LOGE("%s fail : channel is NULL", __func__); - return NULL; - } - (void)device; - (void)ifIndex; - specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); - if (specificDriver == NULL) { - HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); - return NULL; - } - if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { - HDF_LOGE("%s fail: memset_s fail!", __func__); - OsalMemFree(specificDriver); - return NULL; - } - - if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { - HDF_LOGE("%s fail : strcpy_s fail", __func__); - OsalMemFree(specificDriver); - return NULL; - } - specificDriver->init = Hi3881Init; - specificDriver->deinit = Hi3881Deinit; - - HiMac80211Init(specificDriver); - - return specificDriver; -} - -/* 释放WLAN芯片驱动 */ -static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver) -{ - if (chipDriver == NULL) { - return; - } - if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { - HDF_LOGE("%s:Not my driver!", __func__); - return; - } - OsalMemFree(chipDriver); -} - -static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { - (void)factory; - return 1; -} - -/* WLAN芯片相关函数的注册 */ -static int32_t HDFWlanRegHisiDriverFactory(void) -{ - static struct HdfChipDriverFactory tmpFactory = { 0 }; - struct HdfChipDriverManager *driverMgr = NULL; - driverMgr = HdfWlanGetChipDriverMgr(); - if (driverMgr == NULL && driverMgr->RegChipDriver != NULL) { - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; - } - tmpFactory.driverName = HI3881_DRIVER_NAME; - tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; - tmpFactory.InitChip = InitHi3881Chip; - tmpFactory.DeinitChip = DeinitHi3881Chip; - tmpFactory.Build = BuildHi3881Driver; - tmpFactory.Release = ReleaseHi3881Driver; - tmpFactory.ReleaseFactory = NULL; - if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) { - HDF_LOGE("%s fail: driverMgr is NULL!", __func__); - return HDF_FAILURE; - } - - return HDF_SUCCESS; -} - -static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) -{ - (void)device; - return HDFWlanRegHisiDriverFactory(); -} - -struct HdfDriverEntry g_hdfHisiChipEntry = { - .moduleVersion = 1, - .Init = HdfWlanHisiChipDriverInit, - .moduleName = "HDF_WLAN_CHIPS" -}; - -HDF_INIT(g_hdfHisiChipEntry); -``` - -``` -#include "hdf_wifi_product.h" -#include "hi_wifi_api.h" -#if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) -#include "oal_thread.h" -#include "osal_time.h" -#endif -#include "wifi_mac80211_ops.h" -#include "wal_cfg80211.h" -#include "net_adpater.h" -#include "hdf_wlan_utils.h" - -#define HDF_LOG_TAG Hi3881Driver - -/* WLAN芯片的初始化函数 */ -int32_t InitHi3881Chip(struct HdfWlanDevice *device) -{ - uint8_t maxPortCount = 1; - int32_t ret = HI_SUCCESS; - uint8_t maxRetryCount = 2; - if (device == NULL) { - HDF_LOGE("%s:NULL ptr!", __func__); - return HI_FAIL; - } - - do { - if (ret != HI_SUCCESS) { - if (device->reset != NULL && device->reset->Reset != NULL) { - device->reset->Reset(device->reset); - } - HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret); - } - ret = hi_wifi_init(maxPortCount); - } while (ret != 0 && --maxRetryCount > 0); - - if (ret != 0) { - HDF_LOGE("%s:Init hi3881 driver failed!", __func__); - return ret; - } - return HI_SUCCESS; -} - -/* WLAN芯片的去初始化函数 */ -int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) -{ - (void)device; - int32_t ret = hi_wifi_deinit(); - if (ret != 0) { - HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); - } - return ret; -} - -/* WLAN芯片驱动的初始化函数 */ -int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) -{ - HDF_LOGI("%s: start...", __func__); - hi_u16 mode = wal_get_vap_mode(); - int32_t ret; - nl80211_iftype_uint8 type; - (void)chipDriver; - - if (mode >= WAL_WIFI_MODE_BUTT) { - oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); - return HI_FAIL; - } - - if (mode == WAL_WIFI_MODE_STA) { - type = NL80211_IFTYPE_STATION; - } else if (mode == WAL_WIFI_MODE_AP) { - type = NL80211_IFTYPE_AP; - } else { - oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); - return HI_FAIL; - } - - ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice); - if (ret != HI_SUCCESS) { - oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret); - } - return ret; -} - -/* WLAN芯片驱动的去初始化函数 */ -int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) -{ - (void)chipDriver; - int32_t ret = wal_deinit_drv_wlan_netdev(netDevice); - if (ret != HDF_SUCCESS) { - return ret; - } - return ReleasePlatformNetDevice(netDevice); -} -``` - -3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针 - -``` -hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) -{ - oal_net_device_stru *netdev = HI_NULL; - - ...... - /* 初始化网络设备,获取对应的实例。*/ - netdev = NetDeviceInit(ifname, *len, LITE_OS); - oal_wireless_dev *wdev = (oal_wireless_dev *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(oal_wireless_dev)); - ret = wal_init_netif(type, netdev, wdev); - - ...... - - return HI_SUCCESS; -} -/* 挂接netdev的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */ -oal_net_device_ops_stru g_wal_net_dev_ops = -{ - .getStats = wal_netdev_get_stats, - .open = wal_netdev_open, - .stop = wal_netdev_stop, - .xmit = hmac_bridge_vap_xmit, - .ioctl = wal_net_device_ioctl, - .changeMtu = oal_net_device_change_mtu, - .init = oal_net_device_init, - .deInit = oal_net_free_netdev, -#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) - .selectQueue = wal_netdev_select_queue, -#endif - .setMacAddr = wal_netdev_set_mac_addr, -#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) - .netifNotify = HI_NULL, -#endif - .specialEtherTypeProcess = SpecialEtherTypeProcess, -}; - -hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) -{ - /* 添加网络设备到协议栈 */ - hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); - - ...... - - return HI_SUCCESS; -} -``` - -4、WifiMac80211Ops中的函数挂接实现 - -``` -/* 挂接mac80211的一些函数指针 */ - -/* 驱动需要实现的MAC层基本能力的控制接口 */ -static struct HdfMac80211BaseOps g_baseOps = { - .SetMode = WalSetMode, - .AddKey = WalAddKey, - .DelKey = WalDelKey, - .SetDefaultKey = WalSetDefaultKey, - .GetDeviceMacAddr = WalGetDeviceMacAddr, - .SetMacAddr = WalSetMacAddr, - .SetTxPower = WalSetTxPower, - .GetValidFreqsWithBand = WalGetValidFreqsWithBand, - .GetHwCapability = WalGetHwCapability -}; - -/* 驱动需要实现的MAC层STA能力的控制接口 */ -static struct HdfMac80211STAOps g_staOps = { - .Connect = WalConnect, - .Disconnect = WalDisconnect, - .StartScan = WalStartScan, - .AbortScan = WalAbortScan, - .SetScanningMacAddress = WalSetScanningMacAddress, -}; - -/* 驱动需要实现的MAC层AP能力的控制接口 */ -static struct HdfMac80211APOps g_apOps = { - .ConfigAp = WalConfigAp, - .StartAp = WalStartAp, - .StopAp = WalStopAp, - .ConfigBeacon = WalChangeBeacon, - .DelStation = WalDelStation, - .SetCountryCode = WalSetCountryCode, - .GetAssociatedStasCount = WalGetAssociatedStasCount, - .GetAssociatedStasInfo = WalGetAssociatedStasInfo -}; - -/* 初始化mac80211与芯片侧的函数挂接 */ -hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) -{ - if (chipDriver == NULL) { - oam_error_log(0, OAM_SF_ANY, "%s:input is NULL!", __func__); - return; - } - chipDriver->ops = &g_baseOps; - chipDriver->staOps = &g_staOps; - chipDriver->apOps = &g_apOps; -} -``` - diff --git "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 1a5d63663ab7c28d50b8ddd19db7d339b1248472..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,18 +0,0 @@ -# WLAN开发指导 - -- [开发步骤](#section96091936185820) - -WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 - -## 开发步骤 - -1. 通过wifi\_config.hcs文件,配置硬件参数:module\(不同feature\),芯片等。 -2. 解析配置文件, 生成全量配置的结构体对象。 -3. Module初始化,创建Module。 -4. 挂接chip,初始化chip。 -5. 总线初始化。 -6. 上层wpa业务挂接。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。 - diff --git "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index 869ee1da51d3e2ac53a46eaebef489ab55428c7e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/WLAN\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,229 +0,0 @@ -# WLAN开发概述 - -- [简介](#section23087361515) -- [WLAN驱动接口架构](#section1533192516212) -- [接口说明](#section87491484213) - -## 简介 - -WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig967034316227)如下: - -**图 1** WLAN框架 - - -![](figures/zh-cn_image_0000001055299108.png) - -## WLAN驱动接口架构 - -WLAN模块有三部分对外开放的API接口,如[下图2](#fig15016395217)所示: - -1. 对HDI层提供的能力接口。 - -2. 驱动直接调用WLAN模块能力接口。 - -3. 提供给各厂商实现的能力接口。 - -**图 2** WLAN模块开放能力分布图 - - -![](figures/接口分布图4.png) - -## 接口说明 - -WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。提供的部分接口说明如[表1](#table1521573319472)所示: - -**表 1** 可直接调用的接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

wifi_module.h

-

-

struct WifiModule *WifiModuleCreate(const struct HdfConfigWifiModuleConfig *config);

-

基于HDF开发WLAN驱动时,创建一个WifiModule。

-

void WifiModuleDelete(struct WifiModule *module);

-

基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据。

-

int32_t DelFeature(struct WifiModule *module, uint16_t featureType);

-

基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。

-

int32_t AddFeature(struct WifiModule *module, uint16_t featureType, struct WifiFeature *featureData);

-

基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。

-

wifi_mac80211_ops.h

-

int32_t (*startAp)(NetDevice *netDev);

-

启动AP。

-

int32_t (*stopAp)(NetDevice *netDev);

-

停止AP。

-

int32_t (*connect)(NetDevice *netDev, WifiConnectParams *param);

-

开始关联。

-

int32_t (*disconnect)(NetDevice *netDev, uint16_t reasonCode);

-

取消关联。

-

hdf_netbuf.h

-

static inline void NetBufQueueInit(struct NetBufQueue *q);

-

初始化NetBuf队列。

-

struct NetBuf *NetBufAlloc(uint32_t size);

-

申请NetBuf。

-

void NetBufFree(struct NetBuf *nb);

-

释放NetBuf。

-

struct NetBuf *Pbuf2NetBuf(const struct NetDevice *netdev, struct pbuf *lwipBuf);

-

lwip的pbuf转换为NetBuf。

-

struct pbuf *NetBuf2Pbuf(const struct NetBuf *nb);

-

NetBuf转换为lwip的pbuf。

-
- -同时WLAN驱动模块也提供了需要驱动开发人员实现的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如[表2](#table74613501475)所示: - -**表 2** 需要开发人员实现的接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

net_device.h

-

int32_t (*init)(struct NetDevice *netDev);

-

初始化NetDevice。

-

struct NetDevStats *(*getStats)(struct NetDevice *netDev);

-

获取NetDevice的状态。

-

int32_t (*setMacAddr)(struct NetDevice *netDev, void *addr);

-

设置Mac地址。

-

void (*deInit)(struct NetDevice *netDev);

-

注销NetDevice。

-

int32_t (*open)(struct NetDevice *netDev);

-

打开NetDevice。

-

int32_t (*stop)(struct NetDevice *netDev);

-

关闭NetDevice。

-
- -WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如[表3](#table141076311618)所示: - -**表 3** HAL层对外接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口名称

-

功能描述

-

wifi_hal.h

-

-

int32_t WifiConstruct(struct IWiFi **wifiInstance);

-

创建IWiFi对象,提供IWiFi基本能力。

-

int32_t WifiDestruct(struct IWiFi **wifiInstance);

-

销毁IWiFi对象。

-

int32_t (*start)(struct IWiFi *);

-

创建HAL和驱动之间的通道及获取驱动支持的网卡信息。

-

int32_t (*stop)(struct IWiFi *);

-

销毁通道。

-

wifi_hal_base_feature.h

-

int32_t (*getFeatureType)(const struct IWiFiBaseFeature *);

-

获取特性的类型。

-

int32_t (*setMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

-

设置MAC地址。

-

int32_t (*getDeviceMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

-

获取设备持久化的MAC地址。

-

int32_t (*setTxPower)(const struct IWiFiBaseFeature *, int32_t);

-

设置发射功率。

-
- diff --git a/zh-cn/device-dev/driver/drive-hdf-development.md b/zh-cn/device-dev/driver/drive-hdf-development.md new file mode 100644 index 0000000000000000000000000000000000000000..b01173490a99b3f13c30b9c93b03ce6307f6d887 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-development.md @@ -0,0 +1,175 @@ +# 驱动开发 + +- [驱动模型介绍](#section157425168112) +- [驱动开发步骤](#section1969312275533) + +## 驱动模型介绍 + +HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF驱动模型如下图所示: + +**图 1** HDF驱动模型 + + +![](figure/zh-cn_image_0000001054564784.png) + +## 驱动开发步骤 + +基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示: + +1. 驱动实现 + + 驱动实现包含驱动业务代码和驱动入口注册,具体写法如下: + + - 驱动业务代码 + + ``` + #include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件 + #include "hdf_log.h" // HDF 框架提供的日志接口头文件 + + #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签 + + //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架 + int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) + { + HDF_LOGD("Sample driver bind success"); + return 0; + } + + // 驱动自身业务初始的接口 + int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) + { + HDF_LOGD("Sample driver Init success"); + return 0; + } + + // 驱动资源释放的接口 + void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) + { + HDF_LOGD("Sample driver release success"); + return; + } + ``` + + - 驱动入口注册到HDF框架 + + ``` + // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 + struct HdfDriverEntry g_sampleDriverEntry = { + .moduleVersion = 1, + .moduleName = "sample_driver", + .Bind = HdfSampleDriverBind, + .Init = HdfSampleDriverInit, + .Release = HdfSampleDriverRelease, + }; + + // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + HDF_INIT(g_sampleDriverEntry); + ``` + + +2. 驱动编译 + - 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 + + ``` + include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk #导入hdf预定义内容,必需 + MODULE_NAME := #生成的结果文件 + LOCAL_INCLUDE := #本驱动的头文件目录 + LOCAL_SRCS := #本驱动的源代码文件 + LOCAL_CFLAGS := #自定义的编译选项 + include $(HDF_DRIVER) #导入模板makefile完成编译 + ``` + + - 编译结果文件链接到内核镜像,添加到vendor目录下的hdf\_vendor.mk里面,示例如下: + + ``` + LITEOS_BASELIB += -lxxx #链接生成的静态库 + LIB_SUBDIRS += #驱动代码Makefile的目录 + ``` + + +3. 驱动配置 + + HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](drive-hdf-manage.md)介绍。 + + 驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下: + + - 驱动设备描述(必选) + + HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device\_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示: + + ``` + root { + device_info { + match_attr = "hdf_manager"; + template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省 + hostName = ""; + priority = 100; + template device { + template deviceNode { + policy = 0; + priority = 100; + preload = 0; + permission = 0664; + moduleName = ""; + serviceName = ""; + deviceMatchAttr = ""; + } + } + } + sample_host :: host{ + hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器 + priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序 + device_sample :: device { // sample设备节点 + device0 :: deviceNode { // sample驱动的DeviceNode节点 + policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍 + priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 + preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍 + permission = 0664; // 驱动创建设备节点权限 + moduleName = "sample_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 + } + } + } + } + } + ``` + + - 驱动私有配置信息(可选) + + 如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](#li35182436435))传递给驱动,驱动的配置信息示例如下: + + ``` + root { + SampleDriverConfig { + sample_version = 1; + sample_bus = "I2C_0"; + match_attr = "sample_config"; //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 + } + } + ``` + + 配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下: + + ``` + #include "device_info/device_info.hcs" + #include "sample/sample_config.hcs" + ``` + + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下: +>- 按需加载 +> ``` +> typedef enum { +> DEVICE_PRELOAD_ENABLE = 0, +> DEVICE_PRELOAD_ENABLE_STEP2, +> DEVICE_PRELOAD_DISABLE, +> DEVICE_PRELOAD_INVALID +> } DevicePreload; +> ``` +> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](drive-hdf-news.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 +>- 按序加载(需要驱动为默认加载) +> 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 + diff --git a/zh-cn/device-dev/driver/drive-hdf-manage.md b/zh-cn/device-dev/driver/drive-hdf-manage.md new file mode 100644 index 0000000000000000000000000000000000000000..86cc85d8c7d56c8d5fbe544187e191cb48243a56 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-manage.md @@ -0,0 +1,437 @@ +# 配置管理 + +- [配置概述](#section59914284576) +- [配置语法](#section533713333580) +- [关键字](#section1316625413586) +- [基本结构](#section173481622115918) +- [数据类型](#section96521601302) +- [预处理](#section8164295515) +- [注释](#section0338205819610) +- [引用修改](#section179799204716) +- [节点复制](#section382424014712) +- [删除](#section165211112586) +- [属性引用](#section192841514490) +- [模板](#section520134294) +- [配置生成](#section106152531919) +- [hc-gen介绍](#section8260625101012) + +## 配置概述 + +HCS\(**H**DF **C**onfiguration **S**ource\)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。 + +HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式: + +- 在弱性能环境中,转换为配置树源码,驱动可直接调用C代码获取配置。 +- 在高性能环境中,转换为HCB\(**H**DF **C**onfiguration **B**inary\)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。 + +以下是使用HCB模式的典型应用场景: + +**图 1** 配置使用流程图 + + +![](figure/zh-cn_image_0000001053405727.png) + +HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。 + +## 配置语法 + +HCS的语法介绍如下: + +## 关键字 + +HCS配置语法保留了以下关键字。 + +**表 1** HCS配置语法保留关键字 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

关键字

+

用途

+

说明

+

root

+

配置根节点

+

-

+

include

+

引用其他HCS配置文件

+

-

+

delete

+

删除节点或属性

+

只能用于操作include导入的配置树

+

template

+

定义模板节点

+

-

+

match_attr

+

用于标记节点的匹配查找属性

+

解析配置时可以使用该属性的值查找到对应节点

+
+ +## 基本结构 + +HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 + +**属性** + +属性即最小的配置单元,是一个独立的配置项。语法如下: + +``` + attribute_name = value; +``` + +- attribute\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 + +- value的可用格式如下: + + - 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。 + + - 字符串,内容使用双引号\(""\)引用。 + + - 节点引用。 + + +- attribute 必须以分号\(;\)结束且必须属于一个node。 + + +**节点** + +节点是一组属性的集合,语法如下: + +``` + node_name { + module = "sample"; + ... + } +``` + +- node\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 + +- 大括号后无需添加结束符“;”。 + +- root为保留关键字,用于声明配置表的根节点。每个配置表必须以root节点开始。 + +- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块。 + +- 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。 + +## 数据类型 + +在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下: + +**整型** + +整型长度自动推断,根据实际数据长度给与最小空间占用的类型。 + +- 二进制,0b前缀,示例:0b1010。 + +- 八进制,0前缀,示例:0664。 +- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。 + +- 十六进制,0x前缀,示例:0xff00、0xFF。 + + +**字符串** + +字符串使用双引号\(""\)表示。 + +**数组** + +数组元素支持整型、字符串,不支持混合类型。整型数组中uint32\_t uint64\_t混用会向上转型为uint64\_t 数组。整型数组与字符串数组示例如下: + +``` +attr_foo = [0x01, 0x02, 0x03, 0x04]; +attr_bar = ["hello", "world"]; +``` + +**bool类型** + +bool类型中**true**表示真,**false**表示假。 + +## 预处理 + +**include** + +用于导入其他HCS文件。语法示例如下: + +``` +#include "foo.hcs" +#include "../bar.hcs" +``` + +- 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。 +- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。 + +## 注释 + +支持两种注释风格。 + +- 单行注释。 + + ``` + // comment + ``` + +- 多行注释。 + + ``` + /* + comment + */ + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >多行注释不支持嵌套。 + + +## 引用修改 + +引用修改可以实现修改另外任意一个节点的内容,语法为: + +``` + node :& source_node +``` + +上述语句表示node中的内容是对source\_node节点内容的修改。示例如下: + +``` +root { + module = "sample"; + foo { + foo_ :& root.bar{ + attr = "foo"; + } + foo1 :& foo2 { + attr = 0x2; + } + foo2 { + attr = 0x1; + } + } + + bar { + attr = "bar"; + } +} +``` + +最终生成配置树为: + +``` +root { + module = "sample"; + foo { + foo2 { + attr = 0x2; + } + } + bar { + attr = "foo"; + } +} +``` + +在以上示例中,可以看到foo.foo\_节点通过引用将bar.attr属性的值修改为了"foo",foo.foo1节点通过引用将foo.foo2.attr属性的值修改为了0x2。foo.foo\_以及foo.foo1节点表示对目标节点内容的修改,其自身并不会存在最终生成的配置树中。 + +- 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。 +- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。 + +## 节点复制 + +节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为: + +``` + node : source_node +``` + +上述语句表示在定义"node"节点时将另一个节点"source\_node"的属性复制过来。示例如下: + +``` +root { + module = "sample"; + foo { + attr_0 = 0x0; + } + bar:foo { + attr_1 = 0x1; + } +} +``` + +上述代码的最终生成配置树为: + +``` +root { + module = "sample"; + foo { + attr_0 = 0x0; + } + bar { + attr_1 = 0x1; + attr_0 = 0x0; + } +} +``` + +在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。 + +在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section179799204716)。 + +## 删除 + +要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo\_2节点,示例如下: + +``` +// sample2.hcs +root { + attr_1 = 0x1; + attr_2 = 0x2; + foo_2 { + t = 0x1; + } +} + +// sample1.hcs +#include "sample2.hcs" +root { + attr_2 = delete; + foo_2 : delete { + } +} +``` + +上述代码在生成过程中将会删除root.foo\_2节点与attr\_2,最终生成配置树为: + +``` +root { + attr_1 = 0x1; +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。 + +## 属性引用 + +为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为: + +``` + attribute = &node; +``` + +上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下: + +``` +node1 { + attributes; +} + +node2 { + attr_1 = &node1; +} +``` + +## 模板 + +模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。 + +使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下: + +``` +root { + module = "sample"; + template foo { + attr_1 = 0x1; + attr_2 = 0x2; + } + + bar :: foo { + } + + bar_1 :: foo { + attr_1 = 0x2; + } +} +``` + +生成配置树如下: + +``` +root { + module = "sample"; + bar { + attr_1 = 0x1; + attr_2 = 0x2; + } + bar_1 { + attr_1 = 0x2; + attr_2 = 0x2; + } +} +``` + +在上述示例中,bar和bar\_1节点继承了foo节点,生成配置树节点结构与foo保持了完全一致,只是属性的值不同。 + +## 配置生成 + +hc-gen是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。 + +## hc-gen介绍 + +hc-gen参数说明: + +``` +Usage: hc-gen [Options] [File] +options: + -o output file name, default same as input + -a hcb align with four bytes + -b output binary output, default enable + -t output config in C language source file style + -i output binary hex dump in C language source file style + -p prefix of generated symbol name + -d decompile hcb to hcs + -V show verbose info + -v show version + -h show this help message +``` + +生成.c/.h 配置文件方法: + +``` +hc-gen -o [OutputCFileName] -t [SourceHcsFileName] +``` + +生成HCB 配置文件方法: + +``` +hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName] +``` + +反编译HCB文件为HCS方法: + +``` +hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName] +``` + diff --git a/zh-cn/device-dev/driver/drive-hdf-news.md b/zh-cn/device-dev/driver/drive-hdf-news.md new file mode 100644 index 0000000000000000000000000000000000000000..d57a99d58b31df85e19c96fa36d3d06429cf01de --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-news.md @@ -0,0 +1,193 @@ +# 驱动消息机制管理 + +- [使用场景](#section33014541954) +- [接口说明](#section538852311616) +- [开发步骤](#section946912121153) + +## 使用场景 + +当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。 + +## 接口说明 + +消息机制的功能主要有以下两种: + +1. 用户态应用发送消息到驱动。 +2. 用户态应用接收驱动主动上报事件。 + +**表 1** 消息机制接口 + + + + + + + + + + + + + + + + + + + +

方法

+

描述

+

struct HdfIoService *HdfIoServiceBind(const char *serviceName)

+

用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。

+

void HdfIoServiceRecycle(struct HdfIoService *service);

+

释放驱动服务。

+

int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);

+

用户态程序注册接收驱动上报事件的操作方法。

+

int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);

+

驱动主动上报事件接口。

+
+ +## 开发步骤 + +1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE\_POLICY\_CAPACITY,参考[policy定义](drive-hdf-servicemanage.md))。 + + ``` + device_sample :: Device { + policy = 2; + ... + } + ``` + +2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。 +3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。 + + ``` + // Dispatch是用来处理用户态发下来的消息 + int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) + { + HDF_LOGE("sample driver lite A dispatch"); + return 0; + } + int32_t SampleDriverBind(struct HdfDeviceObject *device) + { + HDF_LOGE("test for lite os sample driver A Open!"); + if (device == NULL) { + HDF_LOGE("test for lite os sample driver A Open failed!"); + return -1; + } + static struct ISampleDriverService sampleDriverA = { + .ioService.Dispatch = SampleDriverDispatch, + .ServiceA = SampleDriverServiceA, + .ServiceB = SampleDriverServiceB, + }; + device->service = (struct IDeviceIoService *)(&sampleDriverA); + return 0; + } + ``` + +4. 驱动定义消息处理函数中的cmd类型。 + + ``` + #define SAMPLE_WRITE_READ 1 // 读写操作码1 + ``` + +5. 用户态获取服务接口并发送消息到驱动。 + + ``` + int SendMsg(const char *testMsg) + { + if (testMsg == NULL) { + HDF_LOGE("test msg is null"); + return -1; + } + struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); + if (serv == NULL) { + HDF_LOGE("fail to get service"); + return -1; + } + struct HdfSBuf *data = HdfSBufObtainDefaultSize(); + if (data == NULL) { + HDF_LOGE("fail to obtain sbuf data"); + return -1; + } + struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); + if (reply == NULL) { + HDF_LOGE("fail to obtain sbuf reply"); + ret = HDF_DEV_ERR_NO_MEMORY; + goto out; + } + if (!HdfSbufWriteString(data, testMsg)) { + HDF_LOGE("fail to write sbuf"); + ret = HDF_FAILURE; + goto out; + } + int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("fail to send service call"); + goto out; + } + out: + HdfSBufRecycle(data); + HdfSBufRecycle(reply); + HdfIoServiceRecycle(serv); + return ret; + } + ``` + +6. 用户态接收该驱动上报的消息。 + 1. 用户态编写驱动上报消息的处理函数。 + + ``` + static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) + { + OsalTimespec time; + OsalGetTime(&time); + HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec); + + const char *string = HdfSbufReadString(data); + if (string == NULL) { + HDF_LOGE("fail to read string in event data"); + return -1; + } + HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string); + return 0; + } + ``` + + 2. 用户态注册接收驱动上报消息的操作方法。 + + ``` + int RegisterListen() + { + struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); + if (serv == NULL) { + HDF_LOGE("fail to get service"); + return -1; + } + static struct HdfDevEventlistener listener = { + .callBack = OnDevEventReceived, + .priv ="Service0" + }; + if (HdfDeviceRegisterEventListener(serv, &listener) != 0) { + HDF_LOGE("fail to register event listener"); + return -1; + } + ...... + HdfDeviceUnregisterEventListener(serv, &listener); + HdfIoServiceRecycle(serv); + return 0; + } + ``` + + 3. 驱动上报事件。 + + ``` + int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) + { + ... // process api call here + return HdfDeviceSendEvent(deviceObject, cmdCode, data); + } + ``` + + + diff --git "a/zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\346\246\202\350\277\260.md" b/zh-cn/device-dev/driver/drive-hdf-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/HDF\345\274\200\345\217\221\346\246\202\350\277\260.md" rename to zh-cn/device-dev/driver/drive-hdf-overview.md diff --git a/zh-cn/device-dev/driver/drive-hdf-sample.md b/zh-cn/device-dev/driver/drive-hdf-sample.md new file mode 100644 index 0000000000000000000000000000000000000000..0cc2f0686ff32618900012839c2800fdb8724962 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-hdf-sample.md @@ -0,0 +1,238 @@ +# HDF开发实例 + +- [添加配置](#section27261067111) +- [编写驱动代码](#section177988005) +- [编写用户程序和驱动交互代码](#section6205173816412) + +下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。 + +## 添加配置 + +在HDF框架的配置文件(例如vendor/hisilicon/xxx/config/device\_info)中添加该驱动的配置信息,如下所示: + +``` +root { + device_info { + match_attr = "hdf_manager"; + template host { + hostName = ""; + priority = 100; + template device { + template deviceNode { + policy = 0; + priority = 100; + preload = 0; + permission = 0664; + moduleName = ""; + serviceName = ""; + deviceMatchAttr = ""; + } + } + } + sample_host :: host { + hostName = "sample_host"; + sample_device :: device { + device0 :: deviceNode { + policy = 2; + priority = 100; + preload = 1; + permission = 0664; + moduleName = "sample_driver"; + serviceName = "sample_service"; + } + } + } + } +} +``` + +## 编写驱动代码 + +基于HDF框架编写的sample驱动代码如下: + +``` +#include +#include +#include +#include "hdf_log.h" +#include "hdf_base.h" +#include "hdf_device_desc.h" + +#define HDF_LOG_TAG "sample_driver" + +#define SAMPLE_WRITE_READ 123 + +int32_t HdfSampleDriverDispatch( + struct HdfDeviceObject *deviceObject, int id, struct HdfSBuf *data, struct HdfSBuf *reply) +{ + HDF_LOGE("%s: received cmd %d", __func__, id); + if (id == SAMPLE_WRITE_READ) { + const char *readData = HdfSbufReadString(data); + if (readData != NULL) { + HDF_LOGE("%s: read data is: %s", __func__, readData); + } + if (!HdfSbufWriteInt32(reply, INT32_MAX)) { + HDF_LOGE("%s: reply int32 fail", __func__); + } + return HdfDeviceSendEvent(deviceObject, id, data); + } + return HDF_FAILURE; +} + +void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) +{ + // release resources here + return; +} + +int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) +{ + if (deviceObject == NULL) { + return HDF_FAILURE; + } + static struct IDeviceIoService testService = { + .Dispatch = HdfSampleDriverDispatch, + }; + deviceObject->service = &testService; + return HDF_SUCCESS; +} + +int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) +{ + if (deviceObject == NULL) { + HDF_LOGE("%s::ptr is null!", __func__); + return HDF_FAILURE; + } + HDF_LOGE("Sample driver Init success"); + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_sampleDriverEntry = { + .moduleVersion = 1, + .moduleName = "sample_driver", + .Bind = HdfSampleDriverBind, + .Init = HdfSampleDriverInit, + .Release = HdfSampleDriverRelease, +}; + +HDF_INIT(g_sampleDriverEntry); +``` + +## 编写用户程序和驱动交互代码 + +基于HDF框架编写的用户态程序和驱动交互的代码如下: + +``` +#include +#include +#include +#include +#include "hdf_log.h" +#include "hdf_sbuf.h" +#include "hdf_io_service_if.h" + +#define HDF_LOG_TAG "sample_test" +#define SAMPLE_SERVICE_NAME "sample_service" + +#define SAMPLE_WRITE_READ 123 + +int g_replyFlag = 0; + +static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) +{ + const char *string = HdfSbufReadString(data); + if (string == NULL) { + HDF_LOGE("fail to read string in event data"); + g_replyFlag = 1; + return HDF_FAILURE; + } + HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string); + g_replyFlag = 1; + return HDF_SUCCESS; +} + +static int SendEvent(struct HdfIoService *serv, char *eventData) +{ + int ret = 0; + struct HdfSBuf *data = HdfSBufObtainDefaultSize(); + if (data == NULL) { + HDF_LOGE("fail to obtain sbuf data"); + return 1; + } + + struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); + if (reply == NULL) { + HDF_LOGE("fail to obtain sbuf reply"); + ret = HDF_DEV_ERR_NO_MEMORY; + goto out; + } + + if (!HdfSbufWriteString(data, eventData)) { + HDF_LOGE("fail to write sbuf"); + ret = HDF_FAILURE; + goto out; + } + + ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); + if (ret != HDF_SUCCESS) { + HDF_LOGE("fail to send service call"); + goto out; + } + + int replyData = 0; + if (!HdfSbufReadInt32(reply, &replyData)) { + HDF_LOGE("fail to get service call reply"); + ret = HDF_ERR_INVALID_OBJECT; + goto out; + } + HDF_LOGE("Get reply is: %d", replyData); +out: + HdfSBufRecycle(data); + HdfSBufRecycle(reply); + return ret; +} + +int main() +{ + char *sendData = "default event info"; + struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME); + if (serv == NULL) { + HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME); + return HDF_FAILURE; + } + + static struct HdfDevEventlistener listener = { + .callBack = OnDevEventReceived, + .priv ="Service0" + }; + + if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) { + HDF_LOGE("fail to register event listener"); + return HDF_FAILURE; + } + if (SendEvent(serv, sendData)) { + HDF_LOGE("fail to send event"); + return HDF_FAILURE; + } + + while (g_replyFlag == 0) { + sleep(1); + } + + if (HdfDeviceUnregisterEventListener(serv, &listener)) { + HDF_LOGE("fail to unregister listener"); + return HDF_FAILURE; + } + + HdfIoServiceRecycle(serv); + return HDF_SUCCESS; +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf\_core和osal的动态库,在gn编译文件中添加如下依赖项: +>deps = \[ +>"//drivers/adapter/lite/uhdf/manager:hdf\_core", +>"//drivers/adapter/lite/uhdf/posix:hdf\_posix\_osal", +>\] + diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\234\215\345\212\241\347\256\241\347\220\206.md" b/zh-cn/device-dev/driver/drive-hdf-servicemanage.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/\351\251\261\345\212\250\346\234\215\345\212\241\347\256\241\347\220\206.md" rename to zh-cn/device-dev/driver/drive-hdf-servicemanage.md diff --git a/zh-cn/device-dev/driver/drive-peripherals-external-des.md b/zh-cn/device-dev/driver/drive-peripherals-external-des.md new file mode 100644 index 0000000000000000000000000000000000000000..282d5ed4542e43a142e8262b5f3bbefb87510d36 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-external-des.md @@ -0,0 +1,622 @@ +# WLAN + +- [概述](#section729758162218) + - [WLAN驱动接口架构](#section178022416377) + - [接口说明](#section149681312202415) + +- [开发指导](#section15957746172412) + - [开发步骤](#section11776186132513) + +- [开发实例](#section1395253612512) + +## 概述 + +WLAN是基于HDF(Hardware Driver Foundation)驱动框架开发的模块,该模块可实现跨操作系统迁移,自适应器件差异,模块化拼装编译等功能。各WLAN厂商驱动开发人员可根据WLAN模块提供的向下统一接口适配各自的驱动代码,实现如下能力:建立/关闭WLAN热点、扫描、关联WLAN热点等;对HDI层向上提供能力如下:设置MAC地址、设置发射功率、获取设备的MAC地址等。[WLAN模块框架图](#fig967034316227)如下: + +**图 1** WLAN框架 + + +![](figure/zh-cn_image_0000001170383063.png) + +### WLAN驱动接口架构 + +WLAN模块有三部分对外开放的API接口,如[下图2](#fig15016395217)所示: + +1. 对HDI层提供的能力接口。 + +2. 驱动直接调用WLAN模块能力接口。 + +3. 提供给各厂商实现的能力接口。 + +**图 2** WLAN模块开放能力分布图 + + +![](figure/接口分布图4.png) + +### 接口说明 + +WLAN驱动模块提供给驱动开发人员可直接调用的能力接口,主要功能有:创建/释放WifiModule、关联/取消关联、申请/释放NetBuf、lwip的pbuf和NetBuf的相互转换等。提供的部分接口说明如[表1](#table1521573319472)所示: + +**表 1** 可直接调用的接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口名称

+

功能描述

+

wifi_module.h

+

+

struct WifiModule *WifiModuleCreate(const struct HdfConfigWifiModuleConfig *config);

+

基于HDF开发WLAN驱动时,创建一个WifiModule。

+

void WifiModuleDelete(struct WifiModule *module);

+

基于HDF开发WLAN驱动时,删除并释放WifiModule所有数据。

+

int32_t DelFeature(struct WifiModule *module, uint16_t featureType);

+

基于HDF开发WLAN驱动时,从WifiModule删除一个功能组件。

+

int32_t AddFeature(struct WifiModule *module, uint16_t featureType, struct WifiFeature *featureData);

+

基于HDF开发WLAN驱动时,注册一个功能组件到WifiModule。

+

wifi_mac80211_ops.h

+

int32_t (*startAp)(NetDevice *netDev);

+

启动AP。

+

int32_t (*stopAp)(NetDevice *netDev);

+

停止AP。

+

int32_t (*connect)(NetDevice *netDev, WifiConnectParams *param);

+

开始关联。

+

int32_t (*disconnect)(NetDevice *netDev, uint16_t reasonCode);

+

取消关联。

+

hdf_netbuf.h

+

static inline void NetBufQueueInit(struct NetBufQueue *q);

+

初始化NetBuf队列。

+

struct NetBuf *NetBufAlloc(uint32_t size);

+

申请NetBuf。

+

void NetBufFree(struct NetBuf *nb);

+

释放NetBuf。

+

struct NetBuf *Pbuf2NetBuf(const struct NetDevice *netdev, struct pbuf *lwipBuf);

+

lwip的pbuf转换为NetBuf。

+

struct pbuf *NetBuf2Pbuf(const struct NetBuf *nb);

+

NetBuf转换为lwip的pbuf。

+
+ +同时WLAN驱动模块也提供了需要驱动开发人员实现的能力接口,主要功能有:初始化/注销NetDevice、打开/关闭NetDevice、获取NetDevice的状态等。提供的部分接口说明如[表2](#table74613501475)所示: + +**表 2** 需要开发人员实现的接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口名称

+

功能描述

+

net_device.h

+

int32_t (*init)(struct NetDevice *netDev);

+

初始化NetDevice。

+

struct NetDevStats *(*getStats)(struct NetDevice *netDev);

+

获取NetDevice的状态。

+

int32_t (*setMacAddr)(struct NetDevice *netDev, void *addr);

+

设置Mac地址。

+

void (*deInit)(struct NetDevice *netDev);

+

注销NetDevice。

+

int32_t (*open)(struct NetDevice *netDev);

+

打开NetDevice。

+

int32_t (*stop)(struct NetDevice *netDev);

+

关闭NetDevice。

+
+ +WLAN驱动模块对HDI层提供的能力接口,主要功能有:创建/销毁 IWiFi对象、设置MAC地址等。提供的部分接口说明如[表3](#table141076311618)所示: + +**表 3** HAL层对外接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口名称

+

功能描述

+

wifi_hal.h

+

+

int32_t WifiConstruct(struct IWiFi **wifiInstance);

+

创建IWiFi对象,提供IWiFi基本能力。

+

int32_t WifiDestruct(struct IWiFi **wifiInstance);

+

销毁IWiFi对象。

+

int32_t (*start)(struct IWiFi *);

+

创建HAL和驱动之间的通道及获取驱动支持的网卡信息。

+

int32_t (*stop)(struct IWiFi *);

+

销毁通道。

+

wifi_hal_base_feature.h

+

int32_t (*getFeatureType)(const struct IWiFiBaseFeature *);

+

获取特性的类型。

+

int32_t (*setMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

+

设置MAC地址。

+

int32_t (*getDeviceMacAddress)(const struct IWiFiBaseFeature *, unsigned char *, uint8_t);

+

获取设备持久化的MAC地址。

+

int32_t (*setTxPower)(const struct IWiFiBaseFeature *, int32_t);

+

设置发射功率。

+
+ +## 开发指导 + +WLAN驱动基于HDF框架和PLATFORM框架开发,不区分OS和芯片平台,为不同厂商的WLAN模组提供统一的驱动模型,各WLAN模组厂商根据如下指导适配WLAN驱动框架。 + +### 开发步骤 + +1. 通过wifi\_config.hcs文件,配置硬件参数:module\(不同feature\),芯片等。 +2. 解析配置文件, 生成全量配置的结构体对象。 +3. Module初始化,创建Module。 +4. 挂接chip,初始化chip。 +5. 总线初始化。 +6. 上层wpa业务挂接。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>以上驱动框架适配步骤一部分已经提供(详细见开发实例),待开发人员实现的部分有:1、根据硬件,修改配置参数;2、适配挂接chip;3、测试自验证。 + +## 开发实例 + +本例程提供WLAN模块初始化过程的完整使用流程。示例如下(以hi3881WLAN芯片为例): + +1、根据硬件,修改配置参数。 + +``` +/* 根据硬件参数,通过wlan_platform.hcs配置相关参数,以下是WLAN平台配置的示例 */ +hisi :& deviceList { + device0 :: deviceInst { + deviceInstId = 0; + powers { + power0 { + powerSeqDelay = 0; /* 电源序列延时 */ + powerType = 1; /* 电源类型:0--总是打开;1--GPIO */ + gpioId = 1; /* GPIO管脚号 */ + activeLevel=1; /* 有效电平:0--低;1--高 */ + } + power1 { + powerSeqDelay = 0; /* 电源序列延时 */ + powerType = 0; /* 电源类型:0--总是打开;1--GPIO */ + } + } + reset { + resetType = 0; /* 复位类型:0--不管理;1--GPIO */ + gpioId = 2; /* GPIO管脚号 */ + activeLevel=1; /* 有效电平:0--低;1--高 */ + resetHoldTime = 30; /* 复位配置后的等待时间(ms) */ + } + bootUpTimeout = 30; /* 启动超时时间(ms) */ + bus { + busType = 0; /* 总线类型:0-sdio */ + busId = 2; /* 总线号 */ + funcNum = [1]; /* SDIO功能号 */ + timeout = 1000; /* 读/写数据的超时时间 */ + blockSize = 512; /* 读/写数据的块大小 */ + } + } +} +/* 每一块芯片添加配置文件wlan_chip_<芯片名>.hcs(如:wlan_chip_hi3881.hcs),配置相关参数。以下是hi3881的配置示例 */ +root { + wlan_config { + hi3881 :& chipList { + chipHi3881 :: chipInst { + match_attr = "hdf_wlan_chips_hi3881"; /* 配置匹配标识 */ + chipName = "hi3881"; /* WLAN芯片的名称 */ + sdio { + vendorId = 0x0296; /* 厂商Id */ + deviceId = [0x5347]; /* 设备Id */ + } + } + } + } +} +``` + +2、适配挂接WLAN芯片的初始化和去初始化、WLAN芯片驱动的初始化和去初始化 + +``` +/* WLAN初始化挂接流程 */ +#include "hdf_device_desc.h" +#include "hdf_wifi_product.h" +#include "hdf_log.h" +#include "osal_mem.h" +#include "hdf_wlan_chipdriver_manager.h" +#include "securec.h" +#include "wifi_module.h" +#include "hi_wifi_api.h" +#include "hi_types_base.h" + +#define HDF_LOG_TAG Hi3881Driver + +/* WLAN芯片的初始化和去初始化函数 */ +int32_t InitHi3881Chip(struct HdfWlanDevice *device); +int32_t DeinitHi3881Chip(struct HdfWlanDevice *device); +/* WLAN芯片驱动的初始化和去初始化函数 */ +int32_t Hi3881Deinit(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); +int32_t Hi3881Init(struct HdfChipDriver* chipDriver, struct NetDevice *netDevice); + +/* 初始化mac80211与芯片侧的函数挂接 */ +hi_void HiMac80211Init(struct HdfChipDriver *chipDriver); + +static const char* const HI3881_DRIVER_NAME = "hisi"; + +/* WLAN芯片驱动挂接以及mac80211与芯片侧的函数挂接 */ +static struct HdfChipDriver *BuildHi3881Driver(struct HdfWlanDevice *device, uint8_t ifIndex) +{ + struct HdfChipDriver *specificDriver = NULL; + if (device == NULL) { + HDF_LOGE("%s fail : channel is NULL", __func__); + return NULL; + } + (void)device; + (void)ifIndex; + specificDriver = (struct HdfChipDriver *)OsalMemCalloc(sizeof(struct HdfChipDriver)); + if (specificDriver == NULL) { + HDF_LOGE("%s fail: OsalMemCalloc fail!", __func__); + return NULL; + } + if (memset_s(specificDriver, sizeof(struct HdfChipDriver), 0, sizeof(struct HdfChipDriver)) != EOK) { + HDF_LOGE("%s fail: memset_s fail!", __func__); + OsalMemFree(specificDriver); + return NULL; + } + + if (strcpy_s(specificDriver->name, MAX_WIFI_COMPONENT_NAME_LEN, HI3881_DRIVER_NAME) != EOK) { + HDF_LOGE("%s fail : strcpy_s fail", __func__); + OsalMemFree(specificDriver); + return NULL; + } + specificDriver->init = Hi3881Init; + specificDriver->deinit = Hi3881Deinit; + + HiMac80211Init(specificDriver); + + return specificDriver; +} + +/* 释放WLAN芯片驱动 */ +static void ReleaseHi3881Driver(struct HdfChipDriver *chipDriver) +{ + if (chipDriver == NULL) { + return; + } + if (strcmp(chipDriver->name, HI3881_DRIVER_NAME) != 0) { + HDF_LOGE("%s:Not my driver!", __func__); + return; + } + OsalMemFree(chipDriver); +} + +static uint8_t GetHi3881GetMaxIFCount(struct HdfChipDriverFactory *factory) { + (void)factory; + return 1; +} + +/* WLAN芯片相关函数的注册 */ +static int32_t HDFWlanRegHisiDriverFactory(void) +{ + static struct HdfChipDriverFactory tmpFactory = { 0 }; + struct HdfChipDriverManager *driverMgr = NULL; + driverMgr = HdfWlanGetChipDriverMgr(); + if (driverMgr == NULL && driverMgr->RegChipDriver != NULL) { + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + tmpFactory.driverName = HI3881_DRIVER_NAME; + tmpFactory.GetMaxIFCount = GetHi3881GetMaxIFCount; + tmpFactory.InitChip = InitHi3881Chip; + tmpFactory.DeinitChip = DeinitHi3881Chip; + tmpFactory.Build = BuildHi3881Driver; + tmpFactory.Release = ReleaseHi3881Driver; + tmpFactory.ReleaseFactory = NULL; + if (driverMgr->RegChipDriver(&tmpFactory) != HDF_SUCCESS) { + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} + +static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) +{ + (void)device; + return HDFWlanRegHisiDriverFactory(); +} + +struct HdfDriverEntry g_hdfHisiChipEntry = { + .moduleVersion = 1, + .Init = HdfWlanHisiChipDriverInit, + .moduleName = "HDF_WLAN_CHIPS" +}; + +HDF_INIT(g_hdfHisiChipEntry); +``` + +``` +#include "hdf_wifi_product.h" +#include "hi_wifi_api.h" +#if (_PRE_OS_VERSION_LINUX == _PRE_OS_VERSION) +#include "oal_thread.h" +#include "osal_time.h" +#endif +#include "wifi_mac80211_ops.h" +#include "wal_cfg80211.h" +#include "net_adpater.h" +#include "hdf_wlan_utils.h" + +#define HDF_LOG_TAG Hi3881Driver + +/* WLAN芯片的初始化函数 */ +int32_t InitHi3881Chip(struct HdfWlanDevice *device) +{ + uint8_t maxPortCount = 1; + int32_t ret = HI_SUCCESS; + uint8_t maxRetryCount = 2; + if (device == NULL) { + HDF_LOGE("%s:NULL ptr!", __func__); + return HI_FAIL; + } + + do { + if (ret != HI_SUCCESS) { + if (device->reset != NULL && device->reset->Reset != NULL) { + device->reset->Reset(device->reset); + } + HDF_LOGE("%s:Retry init hi3881!last ret=%d", __func__, ret); + } + ret = hi_wifi_init(maxPortCount); + } while (ret != 0 && --maxRetryCount > 0); + + if (ret != 0) { + HDF_LOGE("%s:Init hi3881 driver failed!", __func__); + return ret; + } + return HI_SUCCESS; +} + +/* WLAN芯片的去初始化函数 */ +int32_t DeinitHi3881Chip(struct HdfWlanDevice *device) +{ + (void)device; + int32_t ret = hi_wifi_deinit(); + if (ret != 0) { + HDF_LOGE("%s:Deinit failed!ret=%d", __func__, ret); + } + return ret; +} + +/* WLAN芯片驱动的初始化函数 */ +int32_t Hi3881Init(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) +{ + HDF_LOGI("%s: start...", __func__); + hi_u16 mode = wal_get_vap_mode(); + int32_t ret; + nl80211_iftype_uint8 type; + (void)chipDriver; + + if (mode >= WAL_WIFI_MODE_BUTT) { + oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + return HI_FAIL; + } + + if (mode == WAL_WIFI_MODE_STA) { + type = NL80211_IFTYPE_STATION; + } else if (mode == WAL_WIFI_MODE_AP) { + type = NL80211_IFTYPE_AP; + } else { + oam_error_log1(0, 0, "wal_init_drv_netdev:: invalid mode[%d]", mode); + return HI_FAIL; + } + + ret = wal_init_drv_wlan_netdev(type, WAL_PHY_MODE_11N, netDevice); + if (ret != HI_SUCCESS) { + oam_error_log2(0, OAM_SF_ANY, "wal_init_drv_netdev %s failed.l_return:%d\n", netDevice->name, ret); + } + return ret; +} + +/* WLAN芯片驱动的去初始化函数 */ +int32_t Hi3881Deinit(struct HdfChipDriver *chipDriver, struct NetDevice *netDevice) +{ + (void)chipDriver; + int32_t ret = wal_deinit_drv_wlan_netdev(netDevice); + if (ret != HDF_SUCCESS) { + return ret; + } + return ReleasePlatformNetDevice(netDevice); +} +``` + +3、在芯片侧初始化过程中调用netdev的init和add接口进行初始化netdev,并挂接netdev的一些函数指针 + +``` +hi_s32 wal_init_drv_wlan_netdev(nl80211_iftype_uint8 type, wal_phy_mode mode, hi_char* ifname, hi_u32* len) +{ + oal_net_device_stru *netdev = HI_NULL; + + ...... + /* 初始化网络设备,获取对应的实例。*/ + netdev = NetDeviceInit(ifname, *len, LITE_OS); + oal_wireless_dev *wdev = (oal_wireless_dev *)oal_mem_alloc(OAL_MEM_POOL_ID_LOCAL, sizeof(oal_wireless_dev)); + ret = wal_init_netif(type, netdev, wdev); + + ...... + + return HI_SUCCESS; +} +/* 挂接netdev的一些函数指针,详细挂接函数{@link NetDeviceInterFace} */ +oal_net_device_ops_stru g_wal_net_dev_ops = +{ + .getStats = wal_netdev_get_stats, + .open = wal_netdev_open, + .stop = wal_netdev_stop, + .xmit = hmac_bridge_vap_xmit, + .ioctl = wal_net_device_ioctl, + .changeMtu = oal_net_device_change_mtu, + .init = oal_net_device_init, + .deInit = oal_net_free_netdev, +#if (defined(_PRE_WLAN_FEATURE_FLOWCTL) || defined(_PRE_WLAN_FEATURE_OFFLOAD_FLOWCTL)) + .selectQueue = wal_netdev_select_queue, +#endif + .setMacAddr = wal_netdev_set_mac_addr, +#if (_PRE_OS_VERSION_LITEOS == _PRE_OS_VERSION) + .netifNotify = HI_NULL, +#endif + .specialEtherTypeProcess = SpecialEtherTypeProcess, +}; + +hi_s32 wal_init_netif(nl80211_iftype_uint8 type, oal_net_device_stru *netdev, const oal_wireless_dev *wdev) +{ + /* 添加网络设备到协议栈 */ + hi_u32 ret = NetDeviceAdd(netdev, (Protocol80211IfType)type); + + ...... + + return HI_SUCCESS; +} +``` + +4、WifiMac80211Ops中的函数挂接实现。 + +``` +/* 挂接mac80211的一些函数指针 */ + +/* 驱动需要实现的MAC层基本能力的控制接口 */ +static struct HdfMac80211BaseOps g_baseOps = { + .SetMode = WalSetMode, + .AddKey = WalAddKey, + .DelKey = WalDelKey, + .SetDefaultKey = WalSetDefaultKey, + .GetDeviceMacAddr = WalGetDeviceMacAddr, + .SetMacAddr = WalSetMacAddr, + .SetTxPower = WalSetTxPower, + .GetValidFreqsWithBand = WalGetValidFreqsWithBand, + .GetHwCapability = WalGetHwCapability +}; + +/* 驱动需要实现的MAC层STA能力的控制接口 */ +static struct HdfMac80211STAOps g_staOps = { + .Connect = WalConnect, + .Disconnect = WalDisconnect, + .StartScan = WalStartScan, + .AbortScan = WalAbortScan, + .SetScanningMacAddress = WalSetScanningMacAddress, +}; + +/* 驱动需要实现的MAC层AP能力的控制接口 */ +static struct HdfMac80211APOps g_apOps = { + .ConfigAp = WalConfigAp, + .StartAp = WalStartAp, + .StopAp = WalStopAp, + .ConfigBeacon = WalChangeBeacon, + .DelStation = WalDelStation, + .SetCountryCode = WalSetCountryCode, + .GetAssociatedStasCount = WalGetAssociatedStasCount, + .GetAssociatedStasInfo = WalGetAssociatedStasInfo +}; + +/* 初始化mac80211与芯片侧的函数挂接 */ +hi_void HiMac80211Init(struct HdfChipDriver *chipDriver) +{ + if (chipDriver == NULL) { + oam_error_log(0, OAM_SF_ANY, "%s:input is NULL!", __func__); + return; + } + chipDriver->ops = &g_baseOps; + chipDriver->staOps = &g_staOps; + chipDriver->apOps = &g_apOps; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals-lcd-des.md b/zh-cn/device-dev/driver/drive-peripherals-lcd-des.md new file mode 100644 index 0000000000000000000000000000000000000000..1e195e52dba11cbcf38cdeacfde333450548a325 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-lcd-des.md @@ -0,0 +1,363 @@ +# LCD + +- [概述](#section141575391542) + - [接口说明](#section14711163785519) + +- [开发指导](#section12394223125615) + - [开发步骤](#section515923045814) + +- [开发实例](#section7441155155813) + +## 概述 + +LCD(Liquid Crystal Display)液晶显示驱动,对LCD进行上电,并通过接口初始化LCD内部寄存器,使LCD正常工作。Display驱动模型基于HDF( Hardware Driver Foundation)[驱动框架](drive-hdf-overview.md)开发,实现跨OS、跨平台,为LCD硬件提供上下电功能、发送初始化序列功能,使LCD进入正常的工作模式,显示芯片平台侧的图像数据,基于HDF驱动框架的Display驱动模型如[图1](#fig69138814229)。 + +**图 1** 基于HDF驱动框架的Display驱动模型 +![](figure/基于HDF驱动框架的Display驱动模型.png "基于HDF驱动框架的Display驱动模型") + +- **Display驱动模型介绍** + + Display驱动模型主要由平台驱动层、芯片平台适配层、LCD器件驱动层三部分组成。驱动模型基于HDF驱动框架开发,通过Platform层和OSAL层提供的接口,屏蔽内核形态的差异,使得器件驱动可以便利的迁移到不同OS及芯片平台。模型向上对接Display公共hal层,支撑HDI接口的实现,通过Display-HDI(Hardware Display Interface)对图形服务提供各类驱动能力接口。 + + (1)Display平台驱动层:通过HDF提供的IOService数据通道,与公共Hal层对接,集中接收并处理各类上层调用指令; + + (2)SOC平台驱动适配层:借助此SOC适配层,实现Display驱动和SOC侧驱动解耦,主要完成芯片平台相关的参数配置,并传递平台驱动层的调用到器件驱动层; + + (3)LCD器件驱动层:在器件驱动层中,主要实现和器件自身强相关的驱动适配接口,例如发送初始化序列、上下电、背光设置等。 + + 基于Display驱动模型开发LCD驱动,可以借助平台提供的各种能力及接口,较大程度的降低器件驱动的开发周期和难度,提升开发效率。 + + +### 接口说明 + +LCD接口通常可分为MIPI DSI接口、TTL接口和LVDS接口,常用的是MIPI DSI接口和TTL接口,下面对常用的MIPI DSI接口和TTL接口作简要介绍。 + +- MIPI DSI接口 + + **图 2** MIPI DSI接口 + ![](figure/MIPI-DSI接口.png "MIPI-DSI接口") + + MIPI DSI接口是MIPI(移动行业处理器接口)联盟定义的显示接口,主要用于移动终端显示屏接口,接口数据传输遵循MIPI协议,MIPI DSI接口为数据接口,传输图像数据,通常情况下MIPI DSI接口的控制信息以MIPI包形式通过MIPI DSI接口发送到对端IC,不需要额外的外设接口。 + +- TTL接口 + + **图 3** TTL接口 + ![](figure/TTL接口.png "TTL接口") + + TTL(Transistor Transistor Logic)即晶体管-晶体管逻辑,TTL电平信号由TTL器件产生,TTL器件是数字集成电路的一大门类,它采用双极型工艺制造,具有高速度、低功耗和品种多等特点。 + + TTL接口是并行方式传输数据的接口,有数据信号、时钟信号和控制信号(行同步、帧同步、数据有效信号等),在控制信号控制下完成数据传输。通常TTL接口的LCD,内部寄存器读写需要额外的外设接口,比如SPI接口、I2C接口等。 + + +## 开发指导 + +Display驱动模型基于HDF驱动框架、Platform接口及OSAL接口开发,可以做到不区分OS(LiteOS、Linux)和芯片平台(Hi35xx、Hi38xx、V3S等),为LCD器件提供统一的驱动模型。 + +### 开发步骤 + +1. 添加LCD驱动相关的设备描述配置。 +2. 在SOC平台驱动适配层中适配对应的芯片平台驱动。 +3. 添加器件驱动,并在驱动入口函数Init中注册Panel驱动数据,驱动数据接口主要包括如下接口: + - LCD上下电 + + 根据LCD硬件连接,使用Platform接口层提供的GPIO操作接口操作对应LCD管脚,例如复位管脚、IOVCC管脚,上电时序参考LCD供应商提供的SPEC。 + + - 发送初始化序列 + + 根据LCD硬件接口,使用Platform接口层提供的I2C、SPI、MIPI等接口,下载LCD初始化序列,初始化参数序列可以参考LCD供应商提供的SPEC。 + + +4. 根据需求实现HDF框架其他接口,比如Release接口。 +5. 根据需求使用HDF框架可创建其他设备节点,用于业务逻辑或者调试功能。 + +## 开发实例 + +添加设备描述配置: + +``` +/* Display驱动相关的设备描述配置 */ +display :: host { + hostName = "display_host"; + /* Display平台驱动设备描述 */ + device_hdf_disp :: device { + device0 :: deviceNode { + policy = 2; + priority = 200; + permission = 0660; + moduleName = "HDF_DISP"; + serviceName = "hdf_disp"; + } + } + /* SOC适配层驱动设备描述 */ + device_hi35xx_disp :: device { + device0 :: deviceNode { + policy = 0; + priority = 199; + moduleName = "HI351XX_DISP"; + } + } + /* LCD器件驱动设备描述 */ + device_lcd :: device { + device0 :: deviceNode { + policy = 0; + priority = 100; + preload = 0; + moduleName = "LCD_Sample"; + } + device1 :: deviceNode { + policy = 0; + priority = 100; + preload = 2; + moduleName = "LCD_SampleXX"; + } + } +} +``` + +SOC适配层驱动,以Hi35xx系列芯片为例,需要在本层驱动中适配MIPI等和芯片平台相关的配置,示例如下: + +``` +static int32_t MipiDsiInit(struct PanelInfo *info) +{ + int32_t ret; + struct DevHandle *mipiHandle = NULL; + struct MipiCfg cfg; + + mipiHandle = MipiDsiOpen(0); + if (mipiHandle == NULL) { + HDF_LOGE("%s: MipiDsiOpen failure", __func__); + return HDF_FAILURE; + } + cfg.lane = info->mipi.lane; + cfg.mode = info->mipi.mode; + cfg.format = info->mipi.format; + cfg.burstMode = info->mipi.burstMode; + cfg.timing.xPixels = info->width; + cfg.timing.hsaPixels = info->hsw; + cfg.timing.hbpPixels = info->hbp; + cfg.timing.hlinePixels = info->width + info->hbp + info->hfp + info->hsw; + cfg.timing.vsaLines = info->vsw; + cfg.timing.vbpLines = info->vbp; + cfg.timing.vfpLines = info->vfp; + cfg.timing.ylines = info->height; + /* 0 : no care */ + cfg.timing.edpiCmdSize = 0; + cfg.pixelClk = CalcPixelClk(info); + cfg.phyDataRate = CalcDataRate(info); + /* config mipi device */ + ret = MipiDsiSetCfg(mipiHandle, &cfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s:MipiDsiSetCfg failure", __func__); + } + MipiDsiClose(mipiHandle); + HDF_LOGI("%s:pixelClk = %d, phyDataRate = %d\n", __func__, + cfg.pixelClk, cfg.phyDataRate); + return ret; +} +``` + +LCD器件驱动示例如下: + +``` +#define RESET_GPIO 5 +#define MIPI_DSI0 0 +#define BLK_PWM1 1 +#define PWM_MAX_PERIOD 100000 +/* backlight setting */ +#define MIN_LEVEL 0 +#define MAX_LEVEL 255 +#define DEFAULT_LEVEL 100 + +#define WIDTH 480 +#define HEIGHT 960 +#define HORIZONTAL_BACK_PORCH 20 +#define HORIZONTAL_FRONT_PORCH 20 +#define HORIZONTAL_SYNC_WIDTH 10 +#define VERTIACL_BACK_PORCH 14 +#define VERTIACL_FRONT_PORCH 16 +#define VERTIACL_SYNC_WIDTH 2 +#define FRAME_RATE 60 + +/* Panel Info结构体结构体 */ +struct PanelInfo { + uint32_t width; + uint32_t height; + uint32_t hbp; + uint32_t hfp; + uint32_t hsw; + uint32_t vbp; + uint32_t vfp; + uint32_t vsw; + uint32_t frameRate; + enum LcdIntfType intfType; + enum IntfSync intfSync; + struct MipiDsiDesc mipi; + struct BlkDesc blk; + struct PwmCfg pwm; +}; + +/* LCD屏的初始化序列 */ +static uint8_t g_payLoad0[] = { 0xF0, 0x5A, 0x5A }; +static uint8_t g_payLoad1[] = { 0xF1, 0xA5, 0xA5 }; +static uint8_t g_payLoad2[] = { 0xB3, 0x03, 0x03, 0x03, 0x07, 0x05, 0x0D, 0x0F, 0x11, 0x13, 0x09, 0x0B }; +static uint8_t g_payLoad3[] = { 0xB4, 0x03, 0x03, 0x03, 0x06, 0x04, 0x0C, 0x0E, 0x10, 0x12, 0x08, 0x0A }; +static uint8_t g_payLoad4[] = { 0xB0, 0x54, 0x32, 0x23, 0x45, 0x44, 0x44, 0x44, 0x44, 0x60, 0x00, 0x60, 0x1C }; +static uint8_t g_payLoad5[] = { 0xB1, 0x32, 0x84, 0x02, 0x87, 0x12, 0x00, 0x50, 0x1C }; +static uint8_t g_payLoad6[] = { 0xB2, 0x73, 0x09, 0x08 }; +static uint8_t g_payLoad7[] = { 0xB6, 0x5C, 0x5C, 0x05 }; +static uint8_t g_payLoad8[] = { 0xB8, 0x23, 0x41, 0x32, 0x30, 0x03 }; +static uint8_t g_payLoad9[] = { 0xBC, 0xD2, 0x0E, 0x63, 0x63, 0x5A, 0x32, 0x22, 0x14, 0x22, 0x03 }; +static uint8_t g_payLoad10[] = { 0xb7, 0x41 }; +static uint8_t g_payLoad11[] = { 0xC1, 0x0c, 0x10, 0x04, 0x0c, 0x10, 0x04 }; +static uint8_t g_payLoad12[] = { 0xC2, 0x10, 0xE0 }; +static uint8_t g_payLoad13[] = { 0xC3, 0x22, 0x11 }; +static uint8_t g_payLoad14[] = { 0xD0, 0x07, 0xFF }; +static uint8_t g_payLoad15[] = { 0xD2, 0x63, 0x0B, 0x08, 0x88 }; +static uint8_t g_payLoad16[] = { 0xC6, 0x08, 0x15, 0xFF, 0x10, 0x16, 0x80, 0x60 }; +static uint8_t g_payLoad17[] = { 0xc7, 0x04 }; +static uint8_t g_payLoad18[] = { + 0xC8, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, 0x43, 0x4C, 0x40, + 0x3D, 0x30, 0x1E, 0x06, 0x7C, 0x50, 0x3B, 0x2C, 0x25, 0x16, 0x1C, 0x08, 0x27, 0x2B, 0x2F, 0x52, + 0x43, 0x4C, 0x40, 0x3D, 0x30, 0x1E, 0x06 +}; +static uint8_t g_payLoad19[] = { 0x11 }; +static uint8_t g_payLoad20[] = { 0x29 }; + +struct DsiCmdDesc g_OnCmd[] = { + { 0x29, 0, sizeof(g_payLoad0), g_payLoad0 }, + { 0x29, 0, sizeof(g_payLoad1), g_payLoad1 }, + { 0x29, 0, sizeof(g_payLoad2), g_payLoad2 }, + { 0x29, 0, sizeof(g_payLoad3), g_payLoad3 }, + { 0x29, 0, sizeof(g_payLoad4), g_payLoad4 }, + { 0x29, 0, sizeof(g_payLoad5), g_payLoad5 }, + { 0x29, 0, sizeof(g_payLoad6), g_payLoad6 }, + { 0x29, 0, sizeof(g_payLoad7), g_payLoad7 }, + { 0x29, 0, sizeof(g_payLoad8), g_payLoad8 }, + { 0x29, 0, sizeof(g_payLoad9), g_payLoad9 }, + { 0x23, 0, sizeof(g_payLoad10), g_payLoad10 }, + { 0x29, 0, sizeof(g_payLoad11), g_payLoad11 }, + { 0x29, 0, sizeof(g_payLoad12), g_payLoad12 }, + { 0x29, 0, sizeof(g_payLoad13), g_payLoad13 }, + { 0x29, 0, sizeof(g_payLoad14), g_payLoad14 }, + { 0x29, 0, sizeof(g_payLoad15), g_payLoad15 }, + { 0x29, 0, sizeof(g_payLoad16), g_payLoad16 }, + { 0x23, 0, sizeof(g_payLoad17), g_payLoad17 }, + { 0x29, 1, sizeof(g_payLoad18), g_payLoad18 }, + { 0x05, 120, sizeof(g_payLoad19), g_payLoad19 }, + { 0x05, 120, sizeof(g_payLoad20), g_payLoad20 }, +}; +static DevHandle g_mipiHandle = NULL; +static DevHandle g_pwmHandle = NULL; + +/* 设置Reset Pin脚状态 */ +static int32_t LcdResetOn(void) +{ + int32_t ret; + ret = GpioSetDir(RESET_GPIO, GPIO_DIR_OUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GpioSetDir failure, ret:%d", ret); + return HDF_FAILURE; + } + ret = GpioWrite(RESET_GPIO, GPIO_VAL_HIGH); + if (ret != HDF_SUCCESS) { + HDF_LOGE("GpioWrite failure, ret:%d", ret); + return HDF_FAILURE; + } + /* delay 20ms */ + OsalMSleep(20); + return HDF_SUCCESS; +} + +static int32_t SampleInit(void) +{ + /* 获取MIPI DSI设备操作句柄 */ + g_mipiHandle = MipiDsiOpen(MIPI_DSI0); + if (g_mipiHandle == NULL) { + HDF_LOGE("%s: MipiDsiOpen failure", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static int32_t SampleOn(void) +{ + int32_t ret; + /* LCD上电序列 */ + ret = LcdResetOn(); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: LcdResetOn failure", __func__); + return HDF_FAILURE; + } + if (g_mipiHandle == NULL) { + HDF_LOGE("%s: g_mipiHandle is null", __func__); + return HDF_FAILURE; + } + /* 使用mipi下发初始化序列 */ + int32_t count = sizeof(g_OnCmd) / sizeof(g_OnCmd[0]); + int32_t i; + for (i = 0; i < count; i++) { + ret = MipiDsiTx(g_mipiHandle, &(g_OnCmd[i])); + if (ret != HDF_SUCCESS) { + HDF_LOGE("MipiDsiTx failure"); + return HDF_FAILURE; + } + } + /* 将mipi切换到HS模式 */ + MipiDsiSetHsMode(g_mipiHandle); + return HDF_SUCCESS; +} + +/* PanelInfo结构体变量 */ +static struct PanelInfo g_panelInfo = { + .width = WIDTH, /* width */ + .height = HEIGHT, /* height */ + .hbp = HORIZONTAL_BACK_PORCH, /* horizontal back porch */ + .hfp = HORIZONTAL_FRONT_PORCH, /* horizontal front porch */ + .hsw = HORIZONTAL_SYNC_WIDTH, /* horizontal sync width */ + .vbp = VERTIACL_BACK_PORCH, /* vertiacl back porch */ + .vfp = VERTIACL_FRONT_PORCH, /* vertiacl front porch */ + .vsw = VERTIACL_SYNC_WIDTH, /* vertiacl sync width */ + .frameRate = FRAME_RATE, /* frame rate */ + .intfType = MIPI_DSI, /* panel interface type */ + .intfSync = OUTPUT_USER, /* output timming type */ + /* mipi config info */ + .mipi = { DSI_2_LANES, DSI_VIDEO_MODE, VIDEO_BURST_MODE, FORMAT_RGB_24_BIT }, + /* backlight config info */ + .blk = { BLK_PWM, MIN_LEVEL, MAX_LEVEL, DEFAULT_LEVEL }, + .pwm = { BLK_PWM1, PWM_MAX_PERIOD }, +}; + +/* 器件驱动需要适配的基础接口 */ +static struct PanelData g_panelData = { + .info = &g_panelInfo, + .init = SampleInit, + .on = SampleOn, + .off = SampleOff, + .setBacklight = SampleSetBacklight, +}; + +/* 器件驱动入口函数 */ +int32_t SampleEntryInit(struct HdfDeviceObject *object) +{ + HDF_LOGI("%s: enter", __func__); + if (object == NULL) { + HDF_LOGE("%s: param is null!", __func__); + return HDF_FAILURE; + } + /* 器件驱动接口注册,ops提供给平台驱动调用 */ + if (PanelDataRegister(&g_panelData) != HDF_SUCCESS) { + HDF_LOGE("%s: PanelDataRegister error!", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +struct HdfDriverEntry g_sampleDevEntry = { + .moduleVersion = 1, + .moduleName = "LCD_SAMPLE", + .Init = SampleEntryInit, +}; + +HDF_INIT(g_sampleDevEntry); +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals-sensor-des.md b/zh-cn/device-dev/driver/drive-peripherals-sensor-des.md new file mode 100644 index 0000000000000000000000000000000000000000..b471e3312416a5159fb6bff31d3632f362b6e08c --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-sensor-des.md @@ -0,0 +1,929 @@ +# SENSOR + +- [概述](#section3634112111) + - [接口说明](#section188213414114) + +- [开发指导](#section1140943382) + - [开发步骤](#section7893102915819) + +- [开发实例](#section257750691) +- [测试指导](#section106021256121219) + +## 概述 + +Sensor(传感器)驱动模块为上层Sensor服务系统提供稳定的Sensor基础能力API,包括Sensor列表查询、Sensor启停、Sensor订阅及去订阅,Sensor参数配置等功能;基于HDF(**H**ardware **D**river **F**oundation)驱动框架开发的Sensor驱动模型,实现跨操作系统迁移,器件差异配置等功能。Sensor驱动模型如下图1所示: + +**图 1** Sensor驱动模型图 +![](figure/Sensor驱动模型图.png "Sensor驱动模型图") + +Sensor驱动模型对外开放的API接口能力如下: + +- 提供Sensor HDI(**H**ardware **D**river **I**nterface)能力接口,简化服务开发。 +- 提供Sensor驱动模型能力接口:依赖HDF驱动框架实现Sensor器件驱动的注册,加载,去注册,器件探测等能力,提供同一类型Sensor器件驱动归一接口, 寄存器配置解析操作接口,总线访问抽象接口,平台抽象接口。 +- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS\(**H**DF **C**onfiguration **S**ource\)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 + +### 接口说明 + +Sensor驱动模型对HDI开放的API接口功能,参考表1。 + +**表 1** Sensor驱动模型对外API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

功能描述

+

查询操作

+

int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count)

+

获取系统中注册的所有传感器信息,一种类型传感器信息包括传感器名字、设备厂商、固件版本号、硬件版本号、传感器类型编号、传感器标识、最大量程、精度、功耗。

+

配置操作

+

int32_t Enable(int32_t sensorId)

+

使能一种传感器设备,只有数据订阅者使能传感器后,才能获取订阅的传感器数据。

+

int32_t Disable(int32_t sensorId)

+

去使能一种传感器设备。

+

int32_t SetBatch(iint32_t sensorId, int64_t samplingInterval, int64_t reportInterval)

+

设置一种传感器的数据采样间隔和数据上报间隔。

+

int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

+

设置一种传感器的工作模式,不同的工作模式,上报数据方式不同。

+

int32_t SetOption(int32_t sensorId, uint32_t option)

+

设置一种传感器量程,精度等可选配置。

+

数据订阅操作

+

int32_t Register(RecordDataCallback cb)

+

订阅者注册传感器数据回调函数,系统会将获取到的传感器数据上报给订阅者。

+

int32_t Unregister(void)

+

订阅者去注册传感器数据回调函数。

+

接口实例

+

const struct SensorInterface *NewSensorInterfaceInstance(void)

+

创建传感器接口实例。

+

int32_t FreeSensorInterfaceInstance(void)

+

释放传感器接口实例。

+
+ +Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无需实现,直接使用,参考表2: + +**表 2** Sensor驱动模型对驱动开发者开放的功能接口列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

功能描述

+

设备管理操作接口

+

int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo)

+

添加当前类型的传感器设备到传感器设备管理。

+

int32_t DeleteSensorDevice(int32_t sensorId)

+

删除传感器设备管理里指定的传感器设备。

+

int32_t ReportSensorEvent(const struct SensorReportEvent *events)

+

上报指定类型传感器的数据到用户侧。

+

Sensor抽象总线和平台操作接口

+

int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)

+

按照配置的总线方式,读取传感器寄存器配置数据。

+

int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len)

+

按照配置的总线方式,传感器配置数据写入寄存器。

+

int32_t CreateSensorThread(struct OsalThread *thread, OsalThreadEntry threadEntry, char *name, void *entryPara)

+

创建指定传感器的定时线程,用于传感器数据上报处理。

+

void DestroySensorThread(struct OsalThread *thread, uint8_t *status);

+

销毁传感器创建的定时线程。

+

通用配置操作接口

+

int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group);

+

根据传感器总线类型信息,下发寄存器分组配置。

+

配置解析操作接口

+

+

int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config)

+

根据传感器设备HCS资源配置,获取传感器信息,总线配置信息,属性配置等基本配置信息,并初始化对应的基本配置数据结构体。

+

int32_t ParseSensorRegConfig(struct SensorCfgData *config)

+

根据传感器设备HCS资源配置,解析寄存器分组信息,并初始化配置数据结构体。

+

void ReleaseSensorAllRegConfig(struct SensorCfgData *config)

+

释放传感器配置数据结构体里分配的资源。

+

int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg)

+

获取传感器总线句柄信息。

+

int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg)

+

释放传感器句柄信息。

+
+ +Sensor驱动模型要求驱动开发者实现的接口功能,参考表3 + +**表 3** Sensor驱动模型要求驱动开发者实现的接口列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

功能描述

+

基本功能操作

+

int32_t init(void)

+

传感器器设备探测成功后,需要对传感器器设备初始化配置。

+

int32_t GetInfo(struct SensorBasicInfo *info)

+

从传感器器设备的HCS配置里,获取当前传感器设备的基本信息。

+

int32_t Enable(void)

+

根据当前传感器器设备的HCS配置,下发传感器设备使能操作组的寄存器配置。

+

int32_t Disable(void)

+

根据当前传感器器设备的HCS配置,下发传感器设备去使能操作组的寄存器配置。

+

int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval)

+

根据数据采样率和数据上报间隔,配置当前传感器设备的数据上报线程处理时间。

+

int32_t SetMode(int32_t mode)

+

配置当前传感器设备数据上报方式。

+

int32_t SetOption(uint32_t option)

+

根据可选配置,下发量程,精度等寄存器配置。

+

void ReadSensorData(void)

+

实现传感器的数据读取函数。

+
+ +接口实现参考[SENSOR](#section257750691)章节。 + +## 开发指导 + +Sensor驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同Sensor器件提供统一的驱动模型。本篇开发指导以加速度计传感器为例,介绍传感器驱动开发。 + +### 开发步骤 + +1. 加速度计传感器驱动注册。HDF驱动框架会提供统一的驱动管理模型,通过加速计传感器模块配置信息,识别并加载对应模块驱动。 +2. 加速度计传感器驱动初始化和去初始化。HDF驱动框架通过init入口函数,依次启动传感器设备驱动加载和分配传感器设备数据配置资源。HDF驱动框架通过release函数,释放驱动加载的资源和配置。 +3. 加速度计传感器寄存器组配置解析。不同类型传感器需要在hcs里配置器件对应的HCS配置文件,然后再设备驱动启动过程中探测器件是否在位,然后加载对应的配置文件,生成配置的结构体对象。 +4. 加速度计传感器驱动操作接口实现。实现各个类型传感器归一化驱动接口,如init,GetInfo,Enable,Disable,SetBatch,SetMode,SetOption,ReadSensorData等函数,完成传感器驱动配置下发和数据上报功能。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>传感器驱动模型已经提供一部分能力集,包括驱动设备管理能力,抽象总线和平台操作接口能力,通用配置操作接口能力,配置解析操作接口能力,接口参考[表2](#table1156812588320)。需要开发人员实现部分有:1、传感器部分操作接口([表3](#table1083014911336));2、传感器HCS差异化数据配置;3、驱动基本功能验证。 + +## 开发实例 + +基于HDF驱动模型,加载启动加速度计传感器驱动,代码形式如下,具体原理可参考[HDF驱动开发指南](drive-hdf-development.md)。加速度传感器选择通讯接口方式为I2C,厂家选择博世BMI160加速度传感器。 + +1. 加速度计传感器驱动入口注册 + +- 加速度计传感器驱动入口函数实现 + +``` +/* 注册加速度计传感器入口数据结构体对象 */ +struct HdfDriverEntry g_sensorAccelDevEntry = { + .moduleVersion = 1, /* 加速度计传感器模块版本号 */ + .moduleName = "HDF_SENSOR_ACCEL", /* 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样*/ + .Bind = BindAccelDriver, /* 加速度计传感器绑定函数 */ + .Init = InitAccelDriver, /* 加速度计传感器初始化函数 */ + .Release = ReleaseAccelDriver, /* 加速度计传感器资源释放函数 */ +}; + +/* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */ +HDF_INIT(g_sensorAccelDevEntry); +``` + +- 加速度计传感器设备配置描述 + +加速度传感器模型使用HCS作为配置描述源码,HCS配置字段详细介绍参考[配置管理](drive-hdf-manage.md)介绍。 + +``` +/* 加速度计传感器设备HCS配置 */ +device_sensor_accel :: device { + device0 :: deviceNode { + policy = 1; /* policy字段是驱动服务发布的策略 */ + priority = 105; /* 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 */ + preload = 2; /* 驱动按需加载字段,0表示加载,2表示不加载 */ + permission = 0664; /* 驱动创建设备节点权限 */ + moduleName = "HDF_SENSOR_ACCEL"; /* 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 */ + serviceName = "sensor_accel"; /* 驱动对外发布服务的名称,必须唯一 */ + deviceMatchAttr = "hdf_sensor_accel_driver"; /* 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 */ + } +} +``` + +1. 加速度计传感器驱动初始化和去初始化 + +- 初始化入口函数init + +``` +/* 加速度计传感器驱动对外提供的服务绑定到HDF框架 */ +int32_t BindAccelDriver(struct HdfDeviceObject *device) +{ + CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); + + static struct IDeviceIoService service = { + .object = {0}, + .Dispatch = DispatchAccel, + }; + device->service = &service; + + return HDF_SUCCESS; +} +/*在探测到器件在位后,需要调用RegisterAccelChipOps注册差异化适配函数*/ +int32_t RegisterAccelChipOps(struct AccelOpsCall *ops) +{ + struct AccelDrvData *drvData = NULL; + + CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM); + + drvData = AccelGetDrvData(); + drvData->ops.Init = ops->Init; + drvData->ops.ReadData = ops->ReadData; + return HDF_SUCCESS; +} +/* 挂载加速度计传感器驱动归一化的接口函数 */ +static int32_t InitAccelOps(struct SensorDeviceInfo *deviceInfo) +{ + struct AccelDrvData *drvData = AccelGetDrvData(); + + (void)memset_s((void *)deviceInfo, sizeof(*deviceInfo), 0, sizeof(*deviceInfo)); + deviceInfo->ops.GetInfo = SetAccelInfo; + deviceInfo->ops.Enable = SetAccelEnable; + deviceInfo->ops.Disable = SetAccelDisable; + deviceInfo->ops.SetBatch = SetAccelBatch; + deviceInfo->ops.SetMode = SetAccelMode; + deviceInfo->ops.SetOption = SetAccelOption; + + if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo), + &drvData->accelCfg->sensorInfo, sizeof(drvData->accelCfg->sensorInfo)) != EOK) { + HDF_LOGE("%s: copy sensor info failed", __func__); + return HDF_FAILURE; + } + /* 传感器类型标识可以在数据HCS配置文件里面配置,也可以在此处 */ + drvData->accelCfg->sensorInfo.sensorTypeId = SENSOR_TAG_ACCELEROMETER; + drvData->accelCfg->sensorInfo.sensorId = SENSOR_TAG_ACCELEROMETER; + + return HDF_SUCCESS; +} +/* 传感器寄存器初始化操作 */ +static int32_t InitAccelAfterConfig(void) +{ + struct SensorDeviceInfo deviceInfo; + + if (InitAccelConfig() != HDF_SUCCESS) { + HDF_LOGE("%s: init accel config failed", __func__); + return HDF_FAILURE; + } + + if (InitAccelOps(&deviceInfo) != HDF_SUCCESS) { + HDF_LOGE("%s: init accel ops failed", __func__); + return HDF_FAILURE; + } + + if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) { + HDF_LOGE("%s: add accel device failed", __func__); + return HDF_FAILURE; + } + + return HDF_SUCCESS; +} +/*通过器件探测函数,挂载器件差异化函数接口*/ +static int32_t DetectAccelChip(void) +{ + int32_t num; + int32_t ret; + int32_t loop; + struct AccelDrvData *drvData = AccelGetDrvData(); + CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); + + num = sizeof(g_accelDetectIfList) / sizeof(g_accelDetectIfList[0]); + for (loop = 0; loop < num; ++loop) { + if (g_accelDetectIfList[loop].DetectChip != NULL) { + ret = g_accelDetectIfList[loop].DetectChip(drvData->accelCfg); + if (ret == HDF_SUCCESS) { + drvData->detectFlag = true; + break; + } + } + } + + if (loop == num) { + HDF_LOGE("%s: detect accel device failed", __func__); + drvData->detectFlag = false; + return HDF_FAILURE; + } + return HDF_SUCCESS; +} +/* 加速度计传感器驱动初始化入口函数,主要功能为对传感器私有数据的结构体对象进行初始化,传感器HCS数据配置对象空间分配,传感器HCS数据配置初始化入口函数调用,传感器设备探测是否在位功能,传感器数据上报定时器创建,传感器归一化接口挂载,传感器设备注册功能 */ +int32_t InitAccelDriver(struct HdfDeviceObject *device) +{ + /* 获取传感器私有数据结构体对象 */ + struct AccelDrvData *drvData = AccelGetDrvData(); + + /* 同类型传感器不同厂家设备探测时,判断此类型传感器是否已经在位,若已经在位,无需再继续探测,直接返回 */ + if (drvData->detectFlag) { + HDF_LOGE("%s: accel sensor have detected", __func__); + return HDF_SUCCESS; + } + + CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); + /* 分配存放传感器数据配置的私有结构体数据对象,需要在驱动释放时释放分配的资源空间 */ + drvData->accelCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*cfg)); + if (drvData->accelCfg == NULL) { + HDF_LOGE("%s: malloc sensor config data failed", __func__); + return HDF_FAILURE; + } + + drvData->accelCfg->regCfgGroup = &g_regCfgGroup[0]; + /* 初始化传感器配置数据主要是解析传感器通讯总线配置类型信息,传感器基本信息,传感器属性信息,传感器是否在位信息,寄存器分组信息 */ + if (GetSensorBaseConfigData(device->property, drvData->accelCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: get sensor base config failed", __func__); + goto Base_CONFIG_EXIT; + } + + if (DetectAccelChip() != HDF_SUCCESS) { + HDF_LOGE("%s: accel sensor detect device no exist", __func__); + goto DETECT_CHIP_EXIT; + } + drvData->detectFlag = true; + if (ParseSensorRegConfig(drvData->accelCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: detect sensor device failed", __func__); + goto REG_CONFIG_EXIT; + } + + if (InitAccelAfterConfig() != HDF_SUCCESS) { + HDF_LOGE("%s: init accel after config failed", __func__); + goto INIT_EXIT; + } + + HDF_LOGI("%s: init accel driver success", __func__); + return HDF_SUCCESS; + +INIT_EXIT: + DestroySensorThread(&drvData->thread, &drvData->threadStatus); + (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); +REG_CONFIG_EXIT: + ReleaseSensorAllRegConfig(drvData->accelCfg); + (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); +DETECT_CHIP_EXIT: + drvData->detectFlag = false; +BASE_CONFIG_EXIT: + drvData->accelCfg->root = NULL; + drvData->accelCfg->regCfgGroup = NULL; + OsalMemFree(drvData->accelCfg); + drvData->accelCfg = NULL; + return HDF_FAILURE; +} + +/* 释放驱动初始化时分配的资源 */ +void ReleaseAccelDriver(struct HdfDeviceObject *device) +{ + (void)device; + struct AccelDrvData *drvData = NULL; + + drvData = AccelGetDrvData(); + (void)DestroySensorThread(&drvData->thread, &drvData->threadStatus); + (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); + drvData->detectFlag = false; + + if (drvData->accelCfg != NULL) { + drvData->accelCfg->root = NULL; + drvData->accelCfg->regCfgGroup = NULL; + ReleaseSensorAllRegConfig(drvData->accelCfg); + (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); + OsalMemFree(drvData->accelCfg); + drvData->accelCfg = NULL; + } + + drvData->initStatus = false; +} +``` + +1. 加速度计传感器寄存器组配置信息 + +加速度计传感器数据配置只需要按照模板配置即可,基于模板配置的解析功能已经在**InitSensorConfigData**函数完成,只需初始化时调用即可。如果有新增配置项,需要同步修改此函数。 + +``` +加速度传感器数据配置模板(accel_config.hcs) +root { + sensorAccelConfig { + accelChipConfig { + /* 传感器设备信息模板 */ + template sensorInfo { + sensorName = "accelerometer"; /* 加速度计名字,字符最大长度16字节 */ + vendorName = "borsh_bmi160"; /* 传感器设备厂商,字符最大长度16字节 */ + firmwareVersion = "1.0"; /* 传感器固件版本号,默认1.0,字符最大长度16字节 */ + hardwareVersion = "1.0"; /* 传感器硬件版本号,默认1.0,字符最大长度16字节 */ + sensorTypeId = 1; /* 传感器类型编号,详见{@link SensorTypeTag} */ + sensorId = 1; /* 传感器的标识号,有传感器驱动开发者定义,推荐用{@link SensorTypeTag}枚举 */ + maxRange = 8; /* 传感器的最大量程,根据开发者需要配置 */ + precision = 0; /* 传感器的精度,与上报数据配合使用,上报数据结构体{@link SensorEvents } */ + power = 230; /* 传感器的功耗 */ + } + /* 传感器使用的总线类型和配置信息模板 */ + template sensorBusConfig { + busType = 0; /* 0:i2c 1:spi */ + busNum = 6; /* 芯片上分配给传感器的器件号 */ + busAddr = 0; /* 芯片上分配给传感器的地址 */ + regWidth = 1; /* 传感器寄存器地址宽度 */ + regBigEndian = 0; /* 传感器寄存器大小端 */ + } + /* 传感器设备属性模板 */ + template sensorAttr { + chipName = ""; /* 传感器芯片名字 */ + chipIdRegister = 0xf; /* 传感器在位检测寄存器地址 */ + chipIdValue = 0xd1; /* 校验传感器在位检测寄存器值 */ + } + } + } +} + +/* 根据不同器件硬件差异,修改模板配置,不修改的就会默认采用模板配置 */ +root { + sensorAccelConfig { + accel_bmi160_chip_config : accelChipConfig { + match_attr = "hdf_sensor_accel_driver"; /* 需要和加速度传感器设备配置match_attr字段保持一致 */ + accelInfo :: sensorInfo { + vendorName = "borsh_bmi160"; + sensorTypeId = 1; + sensorId = 1; + } + accelBusConfig :: sensorBusConfig { + busType = 0; /* i2c通讯方式 */ + busNum = 6; + busAddr = 0x68; + regWidth = 1; /* 1字节位宽 */ + } + accelAttr :: sensorAttr { + chipName = "bmi160"; + chipIdRegister = 0x00; + chipIdValue = 0xd1; + } + accelRegConfig { + /* regAddr: 寄存器地址 + value: 寄存器值 + mask: 寄存器值的掩码 + len: 寄存器值的数据长度(字节) + delay: 配置寄存器延时(ms) + opsType:操作类型 0-无 1-读 2-写 3-读并检查 4-位更新 + calType: 计算类型 0-无 1-写 2-取反 3-异或 4-左移 5-右移 + shiftNum: 移动位数 + debug: 调试开关,0-调试关闭 1-调试打开 + save: 保存数据开关,0-不保存数据 1-保存数据 + */ + /* 传感器寄存器操作分组,按照分组进行有序配置 */ + /* 寄存器地址, 寄存器值, 寄存器值的掩码, 寄存器值的数据长度, 配置寄存器延时, 操作类型, 计算类型, 移动位数, 调试开关, 保存开关 */ + /* 初始化寄存器组 */ + initSeqConfig = [ + 0x7e, 0xb6, 0xff, 1, 5, 2, 0, 0, 0, 0, + 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 + ]; + /* 使能寄存器组 */ + enableSeqConfig = [ + 0x7e, 0x11, 0xff, 1, 5, 2, 0, 0, 0, 0, + 0x41, 0x03, 0xff, 1, 0, 2, 0, 0, 0, 0, + 0x40, 0x08, 0xff, 1, 0, 2, 0, 0, 0, 0 + ]; + /* 去使能寄存器组 */ + disableSeqConfig = [ + 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 + ]; + } + } + } +} +``` + +1. 加速度计传感器驱动操作接口实现 + +开发者需要根据每种类型的传感器实现归一化接口。 + +``` +/* 不使用函数暂时置空 */ +static int32_t SetAccelInfo(struct SensorBasicInfo *info) +{ + (void)info; + + return HDF_ERR_NOT_SUPPORT; +} +/* 下发使能寄存器组的配置 */ +static int32_t SetAccelEnable(void) +{ + int32_t ret; + struct AccelDrvData *drvData = AccelGetDrvData(); + + CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); + ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel sensor disable config failed", __func__); + return HDF_FAILURE; + } + + drvData->threadStatus = SENSOR_THREAD_RUNNING; + + return HDF_SUCCESS; +} +/* 下发去使能寄存器组的配置 */ +static int32_t SetAccelDisable(void) +{ + int32_t ret; + struct AccelDrvData *drvData = AccelGetDrvData(); + + CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); + + ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_DISABLE_GROUP]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel sensor disable config failed", __func__); + return HDF_FAILURE; + } + + drvData->threadStatus = SENSOR_THREAD_STOPPED; + + return HDF_SUCCESS; +} +/* 配置传感器采样率和数据上报间隔 */ +static int32_t SetAccelBatch(int64_t samplingInterval, int64_t interval) +{ + (void)interval; + + struct AccelDrvData *drvData = AccelGetDrvData(); + drvData->interval = samplingInterval; + + return HDF_SUCCESS; +} +/* 设置传感器工作模式,当前支持实时模式 */ +static int32_t SetAccelMode(int32_t mode) +{ + return (mode == SENSOR_WORK_MODE_REALTIME) ? HDF_SUCCESS : HDF_FAILURE; +} +/* 设置传感器可选配置 */ +static int32_t SetAccelOption(uint32_t option) +{ + (void)option; + return HDF_ERR_NOT_SUPPORT; +} +``` + +- 差异化处理接口 + + ``` + /* 器件探测时,如果探测成功,则注册差异化处理函数到accel驱动模型里 */ + int32_t DetectAccelBim160Chip(struct SensorCfgData *data) + { + int32_t ret; + struct AccelOpsCall ops; + CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); + + if (strcmp(ACCEL_CHIP_NAME_BMI160, data->sensorAttr.chipName) != 0) { + return HDF_SUCCESS; + } + ret = InitAccelPreConfig(); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: init BMI160 bus mux config", __func__); + return HDF_FAILURE; + } + if (DetectSensorDevice(data) != HDF_SUCCESS) { + return HDF_FAILURE; + } + + /* 差异化处理函数 */ + ops.Init = InitBmi160; + ops.ReadData = ReadBmi160Data; + ret = RegisterAccelChipOps(&ops); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: register BMI160 accel failed", __func__); + (void)ReleaseSensorBusHandle(&data->busCfg); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + /* 初始化处理函数 */ + static int32_t InitBmi160(struct SensorCfgData *data) + { + int32_t ret; + + CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); + ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: bmi160 sensor init config failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + /* 数据处理函数 */ + int32_t ReadBmi160Data(struct SensorCfgData *data) + { + int32_t ret; + struct AccelData rawData = { 0, 0, 0 }; + int32_t tmp[ACCEL_AXIS_NUM]; + struct SensorReportEvent event; + + (void)memset_s(&event, sizeof(event), 0, sizeof(event)); + + ret = ReadBmi160RawData(data, &rawData, &event.timestamp); + if (ret != HDF_SUCCESS) { + return HDF_FAILURE; + } + + event.sensorId = SENSOR_TAG_ACCELEROMETER; + event.option = 0; + event.mode = SENSOR_WORK_MODE_REALTIME; + + rawData.x = rawData.x * BMI160_ACC_SENSITIVITY_2G; + rawData.y = rawData.y * BMI160_ACC_SENSITIVITY_2G; + rawData.z = rawData.z * BMI160_ACC_SENSITIVITY_2G; + + tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; + tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; + tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; + + event.dataLen = sizeof(tmp); + event.data = (uint8_t *)&tmp; + ret = ReportSensorEvent(&event); + return ret; + } + ``` + +- 数据处理函数 + +创建传感器定时器,按照配置的采样率定时采样,并上报给数据订阅者。 + +``` +/* 传感器定时工作线程 */ +static int32_t ReadAccelDataThreadWorker(void *arg) +{ + (void)arg; + int64_t interval; + struct AccelDrvData *drvData = AccelGetDrvData(); + + drvData->threadStatus = SENSOR_THREAD_START; + while (true) { + if (drvData->threadStatus == SENSOR_THREAD_RUNNING) { + if (drvData->ops.ReadData != NULL) { + (void)drvData->ops.ReadData(drvData->accelCfg); + } + interval = OsalDivS64(drvData->interval, (SENSOR_CONVERT_UNIT * SENSOR_CONVERT_UNIT)); + OsalMSleep(interval); + } else if (drvData->threadStatus == SENSOR_THREAD_DESTROY) { + break; + } else { + OsalMSleep(ACC_DEFAULT_SAMPLING_200_MS / SENSOR_CONVERT_UNIT / SENSOR_CONVERT_UNIT); + } + + if ((!drvData->initStatus) || (drvData->interval < 0) || drvData->threadStatus != SENSOR_THREAD_RUNNING) { + continue; + } + } + + return HDF_SUCCESS; +} +/* 创建传感器定时器和器件初始化 */ +static int32_t InitAccelConfig(void) +{ + int32_t ret; + struct AccelDrvData *drvData = AccelGetDrvData(); + + if (drvData->threadStatus != SENSOR_THREAD_NONE && drvData->threadStatus != SENSOR_THREAD_DESTROY) { + HDF_LOGE("%s: accel thread have created", __func__); + return HDF_SUCCESS; + } + + ret = CreateSensorThread(&drvData->thread, ReadAccelDataThreadWorker, "hdf_sensor_accel", drvData); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel create thread failed", __func__); + drvData->threadStatus = SENSOR_THREAD_NONE; + return HDF_FAILURE; + } + + CHECK_NULL_PTR_RETURN_VALUE(drvData->ops.Init, HDF_ERR_INVALID_PARAM); + + ret = drvData->ops.Init(drvData->accelCfg); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: accel create thread failed", __func__); + drvData->threadStatus = SENSOR_THREAD_NONE; + return HDF_FAILURE; + } + drvData->initStatus = true; + return HDF_SUCCESS; +} +``` + +- 主要的数据结构 + +``` +/* 传感器转换单位*/ +#define SENSOR_CONVERT_UNIT 1000 +#define SENSOR_1K_UNIT 1024 +/* 传感器2g对应灵敏度转换值 */ +#define BMI160_ACC_SENSITIVITY_2G 61 +/* 传感器数据采样寄存器地址 */ +#define BMI160_ACCEL_X_LSB_ADDR 0X12 +#define BMI160_ACCEL_X_MSB_ADDR 0X13 +#define BMI160_ACCEL_Y_LSB_ADDR 0X14 +#define BMI160_ACCEL_Y_MSB_ADDR 0X15 +#define BMI160_ACCEL_Z_LSB_ADDR 0X16 +#define BMI160_ACCEL_Z_MSB_ADDR 0X17 +/* 传感器数据维度 */ +enum AccelAxisNum { + ACCEL_X_AXIS = 0, + ACCEL_Y_AXIS = 1, + ACCEL_Z_AXIS = 2, + ACCEL_AXIS_NUM = 3, +}; +/* 传感器每个维度值 */ +struct AccelData { + int32_t x; + int32_t y; + int32_t z; +}; +/* 传感器私有数据结构体 */ +struct AccelDrvData { + bool detectFlag; + uint8_t threadStatus; + uint8_t initStatus; + int64_t interval; + struct SensorCfgData *accelCfg; + struct OsalThread thread; + struct AccelOpsCall ops; +}; +/* 差异化适配函数 */ +struct AccelOpsCall { + int32_t (*Init)(struct SensorCfgData *data); + int32_t (*ReadData)(struct SensorCfgData *data); +}; +``` + +## 测试指导 + +驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 + +``` +/* 标识是否上报传感器数据 */ +static int32_t g_sensorDataFlag = 0; +/* 保持获取的传感器接口实例地址 */ +static const struct SensorInterface *g_sensorDev = nullptr; + +/* 订阅者注册数据上报函数 */ +static int SensorTestDataCallback(struct SensorEvents *event) +{ + if (event == nullptr) { + return -1; + } + float *data = (float*)event->data; + printf("time [%lld] sensor id [%d] x-[%f] y-[%f] z-[%f]\n\r", event->timestamp, + event->sensorId, (*data), *(data + 1), *(data + g_axisZ)); + if (*data > 1e-5) { + g_sensorDataFlag = 1; + } + return 0; +} +/* 用例执行前,初始化传感器接口实例 */ +void HdfSensorTest::SetUpTestCase() +{ + g_sensorDev = NewSensorInterfaceInstance(); + if (g_sensorDev == nullptr) { + printf("test sensorHdi get Module instace failed\n\r"); + } +} +/* 用例资源释放 */ +void HdfSensorTest::TearDownTestCase() +{ + if (g_sensorDev != nullptr) { + FreeSensorInterfaceInstance(); + g_sensorDev = nullptr; + } +} +/* 传感器驱动测试验证 */ +HWTEST_F(HdfSensorTest,TestAccelDriver_001, TestSize.Level0) +{ + int32_t sensorInterval = 1000000000; /* 数据采样率单位纳秒 */ + int32_t pollTime = 5; /* 数据采样时间单位秒 */ + int32_t accelSensorId = 1; /* 加速度传感器类型标识为1 */ + int32_t count = 0; + int ret; + struct SensorInformation *sensorInfo = nullptr; + + ret = g_sensorDev->Register(SensorTestDataCallback) + EXPECT_EQ(SENSOR_NULL_PTR, ret); + + ret = g_sensorDev->GetAllSensors(&sensorInfo, &count); + EXPECT_EQ(0, ret); + if (sensorInfo == nullptr) { + EXPECT_NE(nullptr, sensorInfo); + return; + } + /* 打印获取的传感器列表 */ + for (int i = 0; i < count; i++) { + printf("get sensoriId[%d], info name[%s]\n\r", sensorInfo[i]->sensorId, sensorInfo[i]->sensorName); + } + ret = g_sensorDev->Enable(accelSensorId); + EXPECT_EQ(0, ret); + g_sensorDataFlag = 0; + + ret = g_sensorDev->SetBatch(accelSensorId, sensorInterval, pollTime); + EXPECT_EQ(0, ret); + /* 在时间pollTime内,观察输出打印数据 */ + OsalSleep(pollTime); + EXPECT_EQ(1, g_sensorDataFlag); + + ret = g_sensorDev->Disable(accelSensorId); + g_sensorDataFlag = 0; + EXPECT_EQ(0, ret); + + ret = g_sensorDev->Unregister(); + EXPECT_EQ(0, ret); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals-touch-des.md b/zh-cn/device-dev/driver/drive-peripherals-touch-des.md new file mode 100644 index 0000000000000000000000000000000000000000..107b2ce618e66348e2cead078b1827b5dd9d6320 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals-touch-des.md @@ -0,0 +1,410 @@ +# TOUCHSCREEN + +- [概述](#section175431838101617) + - [接口说明](#section17667171301711) + +- [开发指导](#section65745222184) + - [开发步骤](#section865734181916) + +- [开发实例](#section263714411191) + - [设备描述配置](#section18249155619195) + - [板级配置及器件私有配置](#section3571192072014) + - [添加器件驱动](#section6356758162015) + + +## 概述 + +- **Touchscreen驱动主要任务** + + Touchscreen驱动用于驱动触摸屏使其正常工作,该驱动主要完成如下工作:对触摸屏驱动IC进行上电、配置硬件管脚并初始化其状态、注册中断、配置通信接口(I2C或SPI)、设定input相关配置、下载及更新固件等操作。 + + +- **Touchscreen驱动层次说明** + + 本节主要介绍基于input驱动模型开发touchscreen器件驱动,其整体的框架模型如[图1](#fig6251184817261)。 + + Input驱动模型基于HDF驱动框架、PLATFORM接口、OSAL接口进行开发,向上对接规范化的驱动接口HDI(Hardware Driver Interface)层,通过Input-HDI层对外提供硬件能力,即上层input service可以通过HDI接口层获取相应的驱动能力,进而操控touchscreen等输入设备。 + + +**图 1** 基于HDF驱动框架的input驱动模型 +![](figure/基于HDF驱动框架的input驱动模型.png "基于HDF驱动框架的input驱动模型") + +- **Input驱动模型介绍** + + Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。器件产生的数据借助平台数据通道能力从内核传递到用户态,驱动模型通过配置文件适配不同器件及硬件平台,提高开发者的器件驱动开发效率。如下部分为模型各部分的说明: + + (1)input设备管理:为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; + + (2)input平台驱动:指各类input设备的公共抽象驱动(例如触摸屏的公共驱动),负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; + + (3)input器件驱动:指各器件厂家的差异化驱动,通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; + + (4)input数据通道:提供一套通用的数据上报通道,各类别的input设备驱动均可用此通道上报input事件; + + (5)input配置解析:负责对input设备的板级配置及器件私有配置进行解析及管理。 + + +- **基于HDF驱动框架开发器件驱动的优势** + + 在HDF(Hardware Driver Foundation)[驱动管理框架](drive-hdf-development.md)的基础上,input驱动模型调用OSAL接口层和Platfom接口层提供的基础接口进行开发,包括bus通信接口、操作系统原生接口(memory、lock、thread、timer等)。由于OSAL接口和Platform接口屏蔽了芯片平台差异,所以基于input驱动模型实现的touchscreen驱动可以进行跨平台、跨OS迁移,以便逐步实现驱动的一次开发,多端部署。 + + +### 接口说明 + +Touchscreen器件的硬件接口相对简单,根据PIN脚的属性,可以简单分为如下三类: + +- 电源接口 +- IO控制接口 +- 通信接口 + +**图 2** Touchscreen器件常用管脚 +![](figure/Touchscreen器件常用管脚.png "Touchscreen器件常用管脚") + +如上图所示的三类接口,分别做简要说明如下: + +1. **电源接口** + - LDO\_1P8:1.8v数字电路 + - LDO\_3P3:3.3v模拟电路 + + 通常情况下,touchscreen驱动IC和LCD驱动IC是相互分离的,这种情况下,touchscreen驱动IC一般同时需要1.8v和3.3v两路供电。随着芯片演进,业内已有touchscreen驱动IC和LCD驱动IC集成在一颗IC中的芯片案例,对touchscreen而言,只需要关注1.8v供电即可,其内部需要的3.3v电源,会在驱动IC内部从LCD的VSP电源(典型值5.5V)中分出来。 + + +2. **IO控制接口** + - Reset:reset管脚,用于在系统休眠、唤醒时,由主机侧对驱动IC进行复位操作。 + - INT:中断管脚,需要在驱动初始化时,配置为输入上拉状态。在驱动IC检测到外部触摸信号后,通过操作中断管脚来触发中断,器件驱动则会在中断处理函数中进行报点数据读取等操作。 + +3. **通信接口** + - I2C:由于touchscreen的报点数据量相对较少,所以一般选用I2C方式传输数据。I2C的具体协议及对应操作接口,可以参考Platform接口层中的[“I2C”使用指南](drive-platform-i2c-des.md#section1695201514281)。 + - SPI:部分厂商,由于需要传递的数据不止报点坐标,而是需要获取基础容值,数据量较大,所以会选用SPI通信方式。SPI的具体协议及对应操作接口,可以参考Platform接口层中的[“SPI” 使用指南](drive-platform-spi-des.md#section71363452477)。 + + +## 开发指导 + +Input驱动模型是基于HDF框架、Platform接口和OSAL接口开发,不区分操作系统和芯片平台,为touchscreen等输入器件提供统一的驱动开发架构。 + +- 如下以touchscreen器件驱动为例,说明input驱动模型的完整加载流程: + + (1)设备描述配置:由开发者参考已有模板进行设备描述配置,包括驱动加载顺序、板级硬件信息、器件私有数据信息等。 + + (2)加载input设备管理驱动:input设备管理驱动由HDF驱动加载,完成设备manager的创建并对其初始化。 + + (3)加载平台驱动:平台驱动由HDF框架加载,主要完成板级配置解析及硬件初始化,并提供器件注册接口。 + + (4)加载器件驱动:器件驱动也由HDF框架加载,完成器件设备的实例化,包括器件私有配置解析和平台预留的差异化接口适配。 + + (5)器件设备向平台驱动注册:将实例化的器件设备向平台驱动注册,实现设备和驱动的绑定,并完成中断注册、上下电等器件初始化工作。 + + (6)input设备注册:在器件初始化完成后,实例化input设备,并将其注册到input manager进行管理。 + + +### 开发步骤 + +1. 设备描述配置 + + 目前Input驱动基于HDF驱动框架编写,驱动的加载启动由HDF驱动管理框架统一处理。首先需要在对应的配置文件中,将驱动信息注册进去,如是否加载、加载优先级,此后HDF驱动框架会逐一启动注册过的驱动模块。驱动的相关配置请参考[HDF驱动框架配置指导](drive-hdf-development.md#section1969312275533)。 + +2. 板级配置及Touchscreen器件私有配置 + + 配置对应的IO管脚功能,例如对单板上为touchscreen设计预留的I2C Pin脚,需设置对应的寄存器,使其选择I2C的通信功能。 + +3. 实现器件差异化适配接口 + + 根据硬件单板设计的通信接口,使用Platform接口层提供的管脚操作接口配置对应的复位管脚、中断管脚以及电源操作,对于GPIO的操作,可参考[GPIO操作接口指导](drive-platform-gpio-des.md#section259614242196) + + +## 开发实例 + +本实例提供touchscreen驱动开发示例,并简要对具体关键点进行开发说明。 + +### 设备描述配置 + +如下配置主要包含input驱动模型各模块层级信息,具体原理可参考[HDF驱动开发指南](drive-hdf-development.md),HDF框架依据该配置信息实现对Input模型各模块的依次加载等。 + +``` +input :: host { + hostName = "input_host"; + priority = 100; + device_input_manager :: device { + device0 :: deviceNode { + policy = 2; // 向外发布服务 + priority = 100; // 加载优先级,在input模块内,manager模块优先级应为最高 + preload = 0; // 加载该驱动 0:加载 1:不加载 + permission = 0660; + moduleName = "HDF_INPUT_MANAGER"; + serviceName = "input_dev_manager"; + deviceMatchAttr = ""; + } + } + device_hdf_touch :: device { + device0 :: deviceNode { + policy = 2; + priority = 120; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH"; + serviceName = "event1"; + deviceMatchAttr = "touch_device1"; + } + } + + device_touch_chip :: device { + device0 :: deviceNode { + policy = 0; + priority = 130; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH_SAMPLE"; + serviceName = "hdf_touch_sample_service"; + deviceMatchAttr = "zsj_sample_5p5"; + } + } +} +``` + +### 板级配置及器件私有配置 + +如下配置包含板级硬件配置及器件私有数据配置,实际业务开发时,可根据具体需求增删及修改如下配置文件信息。 + +``` +root { + input_config { + touchConfig { + touch0 { + boardConfig { + match_attr = "touch_device1"; + inputAttr { + inputType = 0; // 0代表触摸屏 + solutionX = 480; + solutionY = 960; + devName = "main_touch"; // 设备名称 + } + busConfig { + busType = 0; // 0代表I2C + busNum = 6; + clkGpio = 86; + dataGpio = 87; + i2cClkIomux = [0x114f0048, 0x403]; // i2c_clk对应pin的寄存器配置 + i2cDataIomux = [0x114f004c, 0x403]; // i2c_data对应pin的寄存器配置 + } + pinConfig { + rstGpio = 3; + intGpio = 4; + rstRegCfg = [0x112f0094, 0x400]; // reset对应pin的寄存器配置 + intRegCfg = [0x112f0098, 0x400]; // interrupt对应pin的寄存器配置 + } + powerConfig { + vccType = 2; // 1代表LDO、2代表GPIO、3代表PMIC + vccNum = 20; // GPIO号为20 + vccValue = 1800; // 电压幅值为1800mV + vciType = 1; + vciNum = 12; + vciValue = 3300; + } + featureConfig { + capacitanceTest = 0; + gestureMode = 0; + gloverMOde = 0; + coverMode = 0; + chargerMode = 0; + knuckleMode = 0; + } + } + chipConfig { + template touchChip { + match_attr = ""; + chipName = "sample"; + vendorName = "zsj"; + chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 + busType = 0; + deviceAddr = 0x5D; + irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 + maxSpeed = 400; + chipVersion = 0; + powerSequence { + /* 上电时序的配置含义说明: + [类型, 状态, 方向 , 延时] + 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 + 0代表下电或拉低,1代表上电或拉高,2代表无操作 + 0代表输入方向,1代表输出方向,2代表无操作 + 代表延时多少毫秒, 例如20代表延时20ms + */ + powerOnSeq = [4, 0, 1, 0, + 3, 0, 1, 10, + 3, 1, 2, 60, + 4, 2, 0, 0]; + suspendSeq = [3, 0, 2, 10]; + resumeSeq = [3, 1, 2, 10]; + powerOffSeq = [3, 0, 2, 10, + 1, 0, 2, 20]; + } + } + chip0 :: touchChip { + match_attr = "zsj_sample_5p5"; + chipInfo = "ZIDN45100"; + chipVersion = 0; + } + } + } + } + } +} +``` + +### 添加器件驱动 + +在器件驱动中,主要实现了平台预留的差异化接口,以器件数据获取及解析进行示例说明。具体开发过程,需要根据实际使用的单板及器件进行适配。 + +``` +/* 将从器件中读取到的报点数据解析为坐标 */ +static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) +{ + int32_t resX = device->driver->boardCfg->attr.resolutionX; + int32_t resY = device->driver->boardCfg->attr.resolutionY; + + for (int32_t i = 0; i < pointNum; i++) { + frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + frame->fingers[i].valid = true; + } +} +/* 从器件中获取报点数据 */ +static int32_t ChipDataHandle(ChipDevice *device) +{ + int32_t ret; + uint8_t touchStatus = 0; + uint8_t pointNum; + uint8_t buf[GT_POINT_SIZE * MAX_SUPPORT_POINT] = {0}; + InputI2cClient *i2cClient = &device->driver->i2cClient; + uint8_t reg[GT_ADDR_LEN] = {0}; + FrameData *frame = &device->driver->frameData; + reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; + ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); + if (ret < 0 || touchStatus == GT_EVENT_INVALID) { + return HDF_FAILURE; + } + OsalMutexLock(&device->driver->mutex); + (void)memset_s(frame, sizeof(FrameData), 0, sizeof(FrameData)); + if (touchStatus == GT_EVENT_UP) { + frame->realPointNum = 0; + frame->definedEvent = TOUCH_UP; + goto exit; + } + reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; + pointNum = touchStatus & GT_FINGER_NUM_MASK; + if (pointNum <= 0 || pointNum > MAX_SUPPORT_POINT) { + HDF_LOGE("%s: pointNum is invalid, %d", __func__, pointNum); + (void)ChipCleanBuffer(i2cClient); + OsalMutexUnlock(&device->driver->mutex); + return HDF_FAILURE; + } + frame->realPointNum = pointNum; + frame->definedEvent = TOUCH_DOWN; + /* 从寄存器中读取报点值 */ + (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); + /* 解析报点值 */ + ParsePointData(device, frame, buf, pointNum); +exit: + OsalMutexUnlock(&device->driver->mutex); + if (ChipCleanBuffer(i2cClient) != HDF_SUCCESS) { + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +static struct TouchChipOps g_sampleChipOps = { + .Init = ChipInit, + .Detect = ChipDetect, + .Resume = ChipResume, + .Suspend = ChipSuspend, + .DataHandle = ChipDataHandle, +}; + +static TouchChipCfg *ChipConfigInstance(struct HdfDeviceObject *device) +{ + TouchChipCfg *chipCfg = (TouchChipCfg *)OsalMemAlloc(sizeof(TouchChipCfg)); + if (chipCfg == NULL) { + HDF_LOGE("%s: instance chip config failed", __func__); + return NULL; + } + (void)memset_s(chipCfg, sizeof(TouchChipCfg), 0, sizeof(TouchChipCfg)); + /* 解析器件私有配置 */ + if (ParseTouchChipConfig(device->property, chipCfg) != HDF_SUCCESS) { + HDF_LOGE("%s: parse chip config failed", __func__); + OsalMemFree(chipCfg); + chipCfg = NULL; + } + return chipCfg; +} + +static ChipDevice *ChipDeviceInstance(void) +{ + ChipDevice *chipDev = (ChipDevice *)OsalMemAlloc(sizeof(ChipDevice)); + if (chipDev == NULL) { + HDF_LOGE("%s: instance chip device failed", __func__); + return NULL; + } + (void)memset_s(chipDev, sizeof(ChipDevice), 0, sizeof(ChipDevice)); + return chipDev; +} + +static void FreeChipConfig(TouchChipCfg *config) +{ + if (config->pwrSeq.pwrOn.buf != NULL) { + OsalMemFree(config->pwrSeq.pwrOn.buf); + } + if (config->pwrSeq.pwrOff.buf != NULL) { + OsalMemFree(config->pwrSeq.pwrOff.buf); + } + OsalMemFree(config); +} + +static int32_t HdfSampleChipInit(struct HdfDeviceObject *device) +{ + TouchChipCfg *chipCfg = NULL; + ChipDevice *chipDev = NULL; + HDF_LOGE("%s: enter", __func__); + if (device == NULL) { + return HDF_ERR_INVALID_PARAM; + } + /* 器件私有配置解析 */ + chipCfg = ChipConfigInstance(device); + if (chipCfg == NULL) { + return HDF_ERR_MALLOC_FAIL; + } + /* 器件设备实例化 */ + chipDev = ChipDeviceInstance(); + if (chipDev == NULL) { + goto freeCfg; + } + chipDev->chipCfg = chipCfg; + chipDev->ops = &g_sampleChipOps; + chipDev->chipName = chipCfg->chipName; + chipDev->vendorName = chipCfg->vendorName; + + /* 器件设备注册到平台驱动 */ + if (RegisterChipDevice(chipDev) != HDF_SUCCESS) { + goto freeDev; + } + HDF_LOGI("%s: exit succ, chipName = %s", __func__, chipCfg->chipName); + return HDF_SUCCESS; + +freeDev: + OsalMemFree(chipDev); +freeCfg: + FreeChipConfig(chipCfg); + return HDF_FAILURE; +} + +struct HdfDriverEntry g_touchSampleChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_SAMPLE", + .Init = HdfSampleChipInit, +}; + +HDF_INIT(g_touchSampleChipEntry); +``` + diff --git a/zh-cn/device-dev/driver/drive-peripherals.md b/zh-cn/device-dev/driver/drive-peripherals.md new file mode 100644 index 0000000000000000000000000000000000000000..176fb421cd809e1e793f81fbe5892d30230b5e42 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-peripherals.md @@ -0,0 +1,11 @@ +# 外设 + +- **[LCD](drive-peripherals-lcd-des.md)** + +- **[TOUCHSCREEN](drive-peripherals-touch-des.md)** + +- **[SENSOR](drive-peripherals-sensor-des.md)** + +- **[WLAN](drive-peripherals-external-des.md)** + + diff --git a/zh-cn/device-dev/driver/drive-platform-gpio-des.md b/zh-cn/device-dev/driver/drive-platform-gpio-des.md new file mode 100644 index 0000000000000000000000000000000000000000..d4e67c7a5167857f6a3091f277b3da9a98c26490 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-gpio-des.md @@ -0,0 +1,560 @@ +# GPIO + +- [概述](#section1635911016188) + - [接口说明](#section17715915181611) + +- [使用指导](#section259614242196) + - [使用流程](#section103477714216) + - [确定GPIO管脚号](#section370083272117) + - [使用API操作GPIO管脚](#section13604050132118) + +- [使用实例](#section25941262111) + +## 概述 + +GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。 + +GPIO接口定义了操作GPIO管脚的标准方法集合,包括: + +- 设置管脚方向: 方向可以是输入或者输出\(暂不支持高阻态\) + +- 读写管脚电平值: 电平值可以是低电平或高电平 +- 设置管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式 +- 使能和禁止管脚中断:禁止或使能管脚中断 + +### 接口说明 + +**表 1** GPIO驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

GPIO读写

+

GpioRead

+

读管脚电平值

+

GpioWrite

+

写管脚电平值

+

GPIO配置

+

GpioSetDir

+

设置管脚方向

+

GpioGetDir

+

获取管脚方向

+

GPIO中断设置

+

GpioSetIrq

+

设置管脚对应的中断服务函数

+

GpioUnSetIrq

+

取消管脚对应的中断服务函数

+

GpioEnableIrq

+

使能管脚中断

+

GpioDisableIrq

+

禁止管脚中断

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如[图1](#fig1399416053717)所示。 + +**图 1** GPIO使用流程图 + + +![](figure/zh-cn_image_0000001170187071.png) + +### 确定GPIO管脚号 + +不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。 + +- Hi3516DV300 + + 控制器管理12组GPIO管脚,每组8个。 + + GPIO号 = GPIO组索引 \(0\~11\) \* 每组GPIO管脚数\(8\) + 组内偏移 + + 举例:GPIO10\_3的GPIO号 = 10 \* 8 + 3 = 83 + +- Hi3518EV300 + + 控制器管理10组GPIO管脚,每组10个。 + + GPIO号 = GPIO组索引 \(0\~9\) \* 每组GPIO管脚数\(10\) + 组内偏移 + + 举例:GPIO7\_3的GPIO管脚号 = 7 \* 10 + 3 = 73 + + +### 使用API操作GPIO管脚 + +- 设置GPIO管脚方向 + + 在进行GPIO管脚读写前,需要先通过如下函数设置GPIO管脚方向: + + int32\_t GpioSetDir\(uint16\_t gpio, uint16\_t dir\); + + **表 2** GpioSetDir参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

待设置的GPIO管脚号

+

dir

+

待设置的方向值

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ + +- 读写GPIO管脚 + + 如果要读取一个GPIO管脚电平,通过以下函数完成: + + int32\_t GpioRead\(uint16\_t gpio, uint16\_t \*val\); + + **表 3** GpioRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

待读取的GPIO管脚号

+

val

+

接收读取电平值的指针

+

返回值

+

返回值描述

+

0

+

读取成功

+

负数

+

读取失败

+
+ + 如果要向GPIO管脚写入电平值,通过以下函数完成: + + int32\_t GpioWrite\(uint16\_t gpio, uint16\_t val\); + + **表 4** GpioWrite参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

待写入的GPIO管脚号

+

val

+

待写入的电平值

+

返回值

+

返回值描述

+

0

+

写入成功

+

负数

+

写入失败

+
+ + 示例代码: + + ``` + int32_t ret; + uint16_t val; + /* 将3号GPIO管脚配置为输出 */ + ret = GpioSetDir(3, GPIO_DIR_OUT); + if (ret != 0) { + HDF_LOGE("GpioSerDir: failed, ret %d\n", ret); + return; + } + /* 向3号GPIO管脚写入低电平GPIO_VAL_LOW */ + ret = GpioWrite(3, GPIO_VAL_LOW); + if (ret != 0) { + HDF_LOGE("GpioWrite: failed, ret %d\n", ret); + return; + } + /* 将6号GPIO管脚配置为输入 */ + ret = GpioSetDir(6, GPIO_DIR_IN); + if (ret != 0) { + HDF_LOGE("GpioSetDir: failed, ret %d\n", ret); + return; + } + /* 读取6号GPIO管脚的电平值 */ + ret = GpioRead(6, &val); + ``` + + +- 设置GPIO中断 + + 如果要为一个GPIO管脚设置中断响应程序,使用如下函数: + + int32\_t GpioSetIrq\(uint16\_t gpio, uint16\_t mode, GpioIrqFunc func, void \*arg\); + + **表 5** GpioSetIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

GPIO管脚号

+

mode

+

中断触发模式

+

func

+

中断服务程序

+

arg

+

传递给中断服务程序的入参

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ + >![](../public_sys-resources/icon-caution.gif) **注意:** + >同一时间,只能为某个GPIO管脚设置一个中断服务函数,如果重复调用GpioSetIrq函数,则之前设置的中断服务函数会被取代。 + + 当不再需要响应中断服务函数时,使用如下函数取消中断设置: + + int32\_t GpioUnSetIrq\(uint16\_t gpio\); + + **表 6** GpioUnSetIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

GPIO管脚号

+

返回值

+

返回值描述

+

0

+

取消成功

+

负数

+

取消失败

+
+ + 在中断服务程序设置完成后,还需要先通过如下函数使能GPIO管脚的中断: + + int32\_t GpioEnableIrq\(uint16\_t gpio\); + + **表 7** GpioEnableIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

GPIO管脚号

+

返回值

+

返回值描述

+

0

+

使能成功

+

负数

+

使能失败

+
+ + >![](../public_sys-resources/icon-caution.gif) **注意:** + >必须通过此函数使能管脚中断,之前设置的中断服务函数才能被正确响应。 + + 如果要临时屏蔽此中断,可以通过如下函数禁止GPIO管脚中断: + + int32\_t GpioDisableIrq\(uint16\_t gpio\); + + **表 8** GpioDisableIrq参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

gpio

+

GPIO管脚号

+

返回值

+

返回值描述

+

0

+

禁止成功

+

负数

+

禁止失败

+
+ + 示例代码: + + ``` + /* 中断服务函数 + */ + int32_t MyCallBackFunc(uint16_t gpio, void *data) + { + HDF_LOGI("%s: gpio:%u interrupt service in! data=%p\n", __func__, gpio, data); + return 0; + } + + int32_t ret; + /* 设置中断服务程序为MyCallBackFunc,入参为NULL,中断触发模式为上升沿触发 */ + ret = GpioSetIrq(3, OSAL_IRQF_TRIGGER_RISING, MyCallBackFunc, NULL); + if (ret != 0) { + HDF_LOGE("GpioSetIrq: failed, ret %d\n", ret); + return; + } + + /* 使能3号GPIO管脚中断 */ + ret = GpioEnableIrq(3); + if (ret != 0) { + HDF_LOGE("GpioEnableIrq: failed, ret %d\n", ret); + return; + } + + /* 禁止3号GPIO管脚中断 */ + ret = GpioDisableIrq(3); + if (ret != 0) { + HDF_LOGE("GpioDisableIrq: failed, ret %d\n", ret); + return; + } + + /* 取消3号GPIO管脚中断服务程序 */ + ret = GpioUnSetIrq(3); + if (ret != 0) { + HDF_LOGE("GpioUnSetIrq: failed, ret %d\n", ret); + return; + } + ``` + + +## 使用实例 + +本实例程序中,我们将测试一个GPIO管脚的中断触发:为管脚设置中断服务函数,触发方式为边沿触发,然后通过交替写高低电平到管脚,产生电平波动,制造触发条件,观察中断服务函数的执行。 + +首先需要选取一个空闲的GPIO管脚,本例程基于Hi3516DV300某开发板,GPIO管脚选择GPIO10\_3,换算成GPIO号为83。 + +读者可以根据自己使用的开发板,参考其原理图,选择一个空闲的GPIO管脚即可。 + +``` +#include "gpio_if.h" +#include "hdf_log.h" +#include "osal_irq.h" +#include "osal_time.h" + +static uint32_t g_irqCnt; + +/* 中断服务函数*/ +static int32_t TestCaseGpioIrqHandler(uint16_t gpio, void *data) +{ + HDF_LOGE("%s: irq triggered! on gpio:%u, data=%p", __func__, gpio, data); + g_irqCnt++; /* 如果中断服务函数触发执行,则将全局中断计数加1 */ + return GpioDisableIrq(gpio); +} + +/* 测试用例函数 */ +static int32_t TestCaseGpioIrqEdge(void) +{ + int32_t ret; + uint16_t valRead; + uint16_t mode; + uint16_t gpio = 83; /* 待测试的GPIO管脚号 */ + uint32_t timeout; + + /* 将管脚方向设置为输出 */ + ret = GpioSetDir(gpio, GPIO_DIR_OUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set dir fail! ret:%d\n", __func__, ret); + return ret; + } + + /* 先禁止该管脚中断 */ + ret = GpioDisableIrq(gpio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: disable irq fail! ret:%d\n", __func__, ret); + return ret; + } + + /* 为管脚设置中断服务函数,触发模式为上升沿和下降沿共同触发 */ + mode = OSAL_IRQF_TRIGGER_RISING | OSAL_IRQF_TRIGGER_FALLING; + HDF_LOGE("%s: mode:%0x\n", __func__, mode); + ret = GpioSetIrq(gpio, mode, TestCaseGpioIrqHandler, NULL); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set irq fail! ret:%d\n", __func__, ret); + return ret; + } + + /* 使能此管脚中断 */ + ret = GpioEnableIrq(gpio); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: enable irq fail! ret:%d\n", __func__, ret); + (void)GpioUnSetIrq(gpio); + return ret; + } + + g_irqCnt = 0; /* 清除全局计数器 */ + timeout = 0; /* 等待时间清零 */ + /* 等待此管脚中断服务函数触发,等待超时时间为1000毫秒 */ + while (g_irqCnt <= 0 && timeout < 1000) { + (void)GpioRead(gpio, &valRead); + (void)GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW); + HDF_LOGE("%s: wait irq timeout:%u\n", __func__, timeout); + OsalMDelay(200); /* wait for irq trigger */ + timeout += 200; + } + (void)GpioUnSetIrq(gpio); + return (g_irqCnt > 0) ? HDF_SUCCESS : HDF_FAILURE; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-i2c-des.md b/zh-cn/device-dev/driver/drive-platform-i2c-des.md new file mode 100644 index 0000000000000000000000000000000000000000..915c5f440eeb70bb1ebff2640306885b272c33e9 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-i2c-des.md @@ -0,0 +1,426 @@ +# I2C + +- [概述](#section5361140416) + - [接口说明](#section459052019177) + +- [使用指导](#section1695201514281) + - [使用流程](#section1338373417288) + - [打开I2C控制器](#section13751110132914) + - [进行I2C通信](#section9202183372916) + - [关闭I2C控制器](#section19481164133018) + +- [使用实例](#section5302202015300) + +## 概述 + +- I2C\(Inter Integrated Circuit\)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。 +- I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA\(SerialData\)串行数据线以及SCL\(SerialClock\)串行时钟线两根线相连,如[图1 ](#fig1135561232714)所示。 + +- I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。 +- I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。 + +- I2C接口定义了完成I2C传输的通用方法集合,包括: + + - I2C控制器管理: 打开或关闭I2C控制器 + - I2C消息传输:通过消息传输结构体数组进行自定义传输 + + **图 1** I2C物理连线示意图 + ![](figure/I2C物理连线示意图.png "I2C物理连线示意图") + + +### 接口说明 + +**表 1** I2C驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

I2C控制器管理接口

+

I2cOpen

+

打开I2C控制器

+

I2cClose

+

关闭I2C控制器

+

I2c消息传输接口

+

I2cTransfer

+

自定义传输

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用I2C设备的一般流程如[图2](#fig166181128151112)所示。 + +**图 2** I2C设备使用流程图 + + +![](figure/zh-cn_image_0000001123509750.png) + +### 打开I2C控制器 + +在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。 + +DevHandle I2cOpen\(int16\_t number\); + +**表 2** I2cOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

number

+

I2C控制器号

+

返回值

+

返回值描述

+

NULL

+

打开I2C控制器失败

+

设备句柄

+

打开的I2C控制器设备句柄

+
+ +假设系统中存在8个I2C控制器,编号从0到7,那么我们现在获取3号控制器 + +``` +DevHandle i2cHandle = NULL; /* I2C控制器句柄 / + +/* 打开I2C控制器 */ +i2cHandle = I2cOpen(3); +if (i2cHandle == NULL) { + HDF_LOGE("I2cOpen: failed\n"); + return; +} +``` + +### 进行I2C通信 + +消息传输 + +int32\_t I2cTransfer\(DevHandle handle, struct I2cMsg \*msgs, int16\_t count\); + +**表 3** I2cTransfer参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I2C控制器设备句柄

+

msgs

+

待传输数据的消息结构体数组

+

count

+

消息数组长度

+

返回值

+

返回值描述

+

正整数

+

成功传输的消息结构体数目

+

负数

+

执行失败

+
+ +I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。 + +``` +int32_t ret; +uint8_t wbuff[2] = { 0x12, 0x13 }; +uint8_t rbuff[2] = { 0 }; +struct I2cMsg msgs[2]; /* 自定义传输的消息结构体数组 */ +msgs[0].buf = wbuff; /* 写入的数据 */ +msgs[0].len = 2; /* 写入数据长度为2 */ +msgs[0].addr = 0x5A; /* 写入设备地址为0x5A */ +msgs[0].flags = 0; /* 传输标记为0,默认为写 */ +msgs[1].buf = rbuff; /* 要读取的数据 */ +msgs[1].len = 2; /* 读取数据长度为2 */ +msgs[1].addr = 0x5A; /* 读取设备地址为0x5A */ +msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ置位 */ +/* 进行一次自定义传输,传输的消息个数为2 */ +ret = I2cTransfer(i2cHandle, msgs, 2); +if (ret != 2) { + HDF_LOGE("I2cTransfer: failed, ret %d\n", ret); + return; +} +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>- I2cMsg结构体中的设备地址不包含读写标志位,读写信息由flags成员变量的读写控制位传递。 +>- 本函数不对消息结构体个数count做限制,其最大个数度由具体I2C控制器决定。 +>- 本函数也不对每个消息结构体中的数据长度做限制,同样由具体I2C控制器决定。 +>- 本函数可能会引起系统休眠,不允许在中断上下文调用 + +### 关闭I2C控制器 + +I2C通信完成之后,需要关闭I2C控制器,关闭函数如下所示: + +void I2cClose\(DevHandle handle\); + +**表 4** I2cClose参数和返回值描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

I2C控制器设备句柄

+
+ +``` +I2cClose(i2cHandle); /* 关闭I2C控制器 */ +``` + +## 使用实例 + +本例程以操作开发板上的I2C设备为例,详细展示I2C接口的完整使用流程。 + +本例拟对Hi3516DV300某开发板上TouchPad设备进行简单的寄存器读写访问,基本硬件信息如下: + +- SOC:hi3516dv300。 + +- Touch IC:I2C地址为0x38, IC内部寄存器位宽为1字节。 + +- 原理图信息:TouchPad设备挂接在3号I2C控制器下;IC的复位管脚为3号GPIO。 + +本例程首先对Touch IC进行复位操作(开发板上电默认会给TouchIC供电,本例程不考虑供电),然后对其内部寄存器进行随机读写,测试I2C通路是否正常。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>本例程重点在于展示I2C设备访问流程,并验证I2C通路,所以对于设备寄存器读写值不做关注,读写寄存器导致的行为由设备自身决定。 + +示例如下: + +``` +#include "i2c_if.h" /* I2C标准接口头文件 */ +#include "gpio_if.h" /* GPIO标准接口头文件 */ +#include "hdf_log.h" /* 标准日志打印头文件 */ +#include "osal_io.h" /* 标准IO读写接口头文件 */ +#include "osal_time.h" /* 标准延迟&睡眠接口头文件 */ + +/* 定义一个表示TP设备的结构体,存储i2c及gpio相关硬件信息 */ +struct TpI2cDevice { + uint16_t rstGpio; /* 复位管脚 */ + uint16_t busId; /* I2C总线号 */ + uint16_t addr; /* I2C设备地址 */ + uint16_t regLen; /* 寄存器字节宽度 */ + DevHandle i2cHandle; /* I2C控制器句柄 */ +}; + +/* I2C管脚io配置,需要查阅SOC寄存器手册 */ +#define I2C3_DATA_REG_ADDR 0x112f008c /* 3号I2C控制器SDA管脚配置寄存器地址 */ +#define I2C3_CLK_REG_ADDR 0x112f0090 /* 3号I2C控制器SCL管脚配置寄存器地址 */ +#define I2C_REG_CFG 0x5f1 /* 3号I2C控制器SDA及SCL管脚配置值 */ + +static void TpSocIoCfg(void) +{ + /* 将3号I2C控制器对应两个管脚的IO功能设置为I2C */ + OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_DATA_REG_ADDR)); + OSAL_WRITEL(I2C_REG_CFG, IO_DEVICE_ADDR(I2C3_CLK_REG_ADDR)); +} + +/* 对TP的复位管脚进行初始化, 拉高维持20ms, 再拉底维持50ms,最后再拉高维持20ms, 完成复位动作 */ +static int32_t TestCaseGpioInit(struct TpI2cDevice *tpDevice) +{ + int32_t ret; + + /* 设置复位管脚方向为输出 */ + ret = GpioSetDir(tpDevice->rstGpio, GPIO_DIR_OUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst dir fail!:%d", __func__, ret); + return ret; + } + + ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst hight fail!:%d", __func__, ret); + return ret; + } + OsalMSleep(20); + + ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_LOW); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst low fail!:%d", __func__, ret); + return ret; + } + OsalMSleep(50); + + ret = GpioWrite(tpDevice->rstGpio, GPIO_VAL_HIGH); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set rst high fail!:%d", __func__, ret); + return ret; + } + OsalMSleep(20); + + return HDF_SUCCESS; +} + +/* 基于I2cTransfer方法封装一个寄存器读写的辅助函数, 通过flag表示读或写 */ +static int TpI2cReadWrite(struct TpI2cDevice *tpDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen, uint8_t flag) +{ + int index = 0; + unsigned char regBuf[4] = {0}; + struct I2cMsg msgs[2] = {0}; + + /* 单双字节寄存器长度适配 */ + if (tpDevice->regLen == 1) { + regBuf[index++] = regAddr & 0xFF; + } else { + regBuf[index++] = (regAddr >> 8) & 0xFF; + regBuf[index++] = regAddr & 0xFF; + } + + /* 填充I2cMsg消息结构 */ + msgs[0].addr = tpDevice->addr; + msgs[0].flags = 0; /* 标记为0,表示写入 */ + msgs[0].len = tpDevice->regLen; + msgs[0].buf = regBuf; + + msgs[1].addr = tpDevice->addr; + msgs[1].flags = (flag == 1) ? I2C_FLAG_READ : 0; /* 添加读标记位,表示读取 */ + msgs[1].len = dataLen; + msgs[1].buf = regData; + + if (I2cTransfer(tpDevice->i2cHandle, msgs, 2) != 2) { + HDF_LOGE("%s: i2c read err", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; +} + +/* TP寄存器读函数 */ +static inline int TpI2cReadReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 1); +} + +/* TP寄存器写函数 */ +static inline int TpI2cWriteReg(struct TpI2cDevice *tpDevice, unsigned int regAddr, + unsigned char *regData, unsigned int dataLen) +{ + return TpI2cReadWrite(tpDevice, regAddr, regData, dataLen, 0); +} + +/* I2C例程总入口 */ +static int32_t TestCaseI2c(void) +{ + int32_t i; + int32_t ret; + unsigned char bufWrite[7] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xA, 0xB, 0xC }; + unsigned char bufRead[7] = {0}; + static struct TpI2cDevice tpDevice; + + /* IO管脚功能配置 */ + TpSocIoCfg(); + + /* TP设备信息初始化 */ + tpDevice.rstGpio = 3; + tpDevice.busId = 3; + tpDevice.addr = 0x38; + tpDevice.regLen = 1; + tpDevice.i2cHandle = NULL; + + /* GPIO管脚初始化 */ + ret = TestCaseGpioInit(&tpDevice); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: gpio init fail!:%d", __func__, ret); + return ret; + } + + /* 打开I2C控制器 */ + tpDevice.i2cHandle = I2cOpen(tpDevice.busId); + if (tpDevice.i2cHandle == NULL) { + HDF_LOGE("%s: Open I2c:%u fail!", __func__, tpDevice.busId); + return -1; + } + + /* 向TP-IC的0xD5寄存器连续写7字节数据 */ + ret = TpI2cWriteReg(&tpDevice, 0xD5, bufWrite, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp i2c write reg fail!:%d", __func__, ret); + I2cClose(tpDevice.i2cHandle); + return -1; + } + OsalMSleep(10); + + /* 从TP-IC的0xDO寄存器连续读7字节数据 */ + ret = TpI2cReadReg(&tpDevice, 0xD5, bufRead, 7); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: tp i2c read reg fail!:%d", __func__, ret); + I2cClose(tpDevice.i2cHandle); + return -1; + } + + HDF_LOGE("%s: tp i2c write&read reg success!", __func__); + for (i = 0; i < 7; i++) { + HDF_LOGE("%s: bufRead[%d] = 0x%x", __func__, i, bufRead[i]); + } + + /* 访问完毕关闭I2C控制器 */ + I2cClose(tpDevice.i2cHandle); + return ret; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-mipidsi-des.md b/zh-cn/device-dev/driver/drive-platform-mipidsi-des.md new file mode 100644 index 0000000000000000000000000000000000000000..c7cf01ca02d5c96f9c97447abf11a0d7bdb79ee7 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-mipidsi-des.md @@ -0,0 +1,554 @@ +# MIPI DSI + +- [概述](#section16806142183217) + - [接口说明](#section129611916132011) + +- [使用指导](#section037231715335) + - [使用流程](#section49299119344) + - [获取MIPI-DSI操作句柄](#section5126155683811) + - [MIPI-DSI相应配置](#section201164274344) + - [发送/回读控制指令](#section199401342173415) + - [释放MIPI-DSI操作句柄](#section161011610357) + +- [使用实例](#section17470126123520) + +## 概述 + +- DSI(Display Serial Interface)是由移动行业处理器接口联盟(Mobile Industry Processor Interface \(MIPI\) Alliance)制定的规范,旨在降低移动设备中显示控制器的成本。它以串行的方式发送像素数据或指令给外设\(通常是LCD或者类似的显示设备\),或从外设中读取状态信息或像素信息;它定义了主机、图像数据源和目标设备之间的串行总线和通信协议。 + +- MIPI-DSI具备高速模式和低速模式两种工作模式,全部数据通道都可以用于单向的高速传输,但只有第一个数据通道才可用于低速双向传输,从属端的状态信息、像素等是通过该数据通道返回。时钟通道专用于在高速传输数据的过程中传输同步时钟信号。 +- 图1显示了简化的DSI接口。从概念上看,符合DSI的接口与基于DBI-2和DPI-2标准的接口具有相同的功能。它向外围设备传输像素或命令数据,并且可以从外围设备读取状态或像素信息。主要区别在于,DSI对所有像素数据、命令和事件进行序列化,而在传统接口中,这些像素数据、命令和事件通常需要附加控制信号才能在并行数据总线上传输。 + + **图 1** DSI发送、接收接口 + ![](figure/DSI发送-接收接口.png "DSI发送-接收接口") + + +### 接口说明 + +**表 1** MIPI-DSI API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

设置/获取当前MIPI-DSI相关配置

+

MipiDsiSetCfg

+

设置MIPI-DSI相关配置

+

MipiDsiGetCfg

+

获取当前MIPI-DSI相关配置

+

获取/释放MIPI-DSI操作句柄

+

MipiDsiOpen

+

获取MIPI-DSI操作句柄

+

MipiDsiClose

+

释放MIPI-DSI操作句柄

+

设置MIPI-DSI进入Low power模式/High speed模式

+

MipiDsiSetLpMode

+

设置MIPI-DSI进入Low power模式

+

MipiDsiSetHsMode

+

设置MIPI-DSI进入High speed模式

+

MIPI-DSI发送/回读指令

+

MipiDsiTx

+

MIPI-DSI发送相应指令的接口

+

MipiDsiRx

+

MIPI-DSI按期望长度回读的接口

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用 + +## 使用指导 + +### 使用流程 + +使用MIPI-DSI的一般流程如[图2](#fig99821771782)所示。 + +**图 2** MIPI-DSI使用流程图 + + +![](figure/zh-cn_image_0000001123514210.png) + +### 获取MIPI-DSI操作句柄 + +在进行MIPI-DSI进行通信前,首先要调用MipiDsiOpen获取操作句柄,该函数会返回指定通道ID的操作句柄。 + +DevHandle MipiDsiOpen\(uint8\_t id\); + +**表 2** MipiDsiOpen的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

id

+

MIPI DSI通道ID

+

返回值

+

返回值描述

+

NULL

+

获取失败

+

设备句柄

+

获取到指令通道的操作句柄, 类型为DevHandle

+
+ +假设系统中的MIPI-DSI通道为0,获取该通道操作句柄的示例如下: + +``` +DevHandle mipiDsiHandle = NULL; /* 设备句柄 */ +chnId = 0; /* MIPI-DSI通道ID */ + +/* 获取操作句柄 */ +mipiDsiHandle = MipiDsiOpen(chnId); +if (mipiDsiHandle == NULL) { + HDF_LOGE("MipiDsiOpen: failed\n"); + return; +} +``` + +### MIPI-DSI相应配置 + +- 写入MIPI-DSI配置 + +int32\_t MipiDsiSetCfg\(DevHandle handle, struct MipiCfg \*cfg\); + +**表 3** MipiDsiSetCfg的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

操作句柄

+

cfg

+

MIPI-DSI相应配置buf 指针

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +``` +int32_t ret; +struct MipiCfg cfg = {0}; + +/* 当前对接的屏幕配置如下 */ +cfg.lane = DSI_4_LANES; +cfg.mode = DSI_CMD_MODE; +cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; +cfg.format = FORMAT_RGB_24_BIT; +cfg.pixelClk = 174; +cfg.phyDataRate = 384; +cfg.timingInfo.hsaPixels = 50; +cfg.timingInfo.hbpPixels = 55; +cfg.timingInfo.hlinePixels = 1200; +cfg.timingInfo.yResLines = 1800; +cfg.timingInfo.vbpLines = 33; +cfg.timingInfo.vsaLines = 76; +cfg.timingInfo.vfpLines = 120; +cfg.timingInfo.xResPixels = 1342; +/* 写入配置数据 */ +ret = MipiDsiSetCfg(g_handle, &cfg); +if (ret != 0) { + HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); + return -1; +} +``` + +- 获取当前MIPI-DSI的配置 + +int32\_t MipiDsiGetCfg\(DevHandle handle, struct MipiCfg \*cfg\); + +**表 4** MipiDsiGetCfg的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

操作句柄

+

cfg

+

MIPI-DSI相应配置buf 指针

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +``` +int32_t ret; +struct MipiCfg cfg; +memset(&cfg, 0, sizeof(struct MipiCfg)); +ret = MipiDsiGetCfg(g_handle, &cfg); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: GetMipiCfg fail!\n", __func__); + return HDF_FAILURE; +} +``` + +### 发送/回读控制指令 + +- 发送指令 + +int32\_t MipiDsiTx\(PalHandle handle, struct DsiCmdDesc \*cmd\); + +**表 5** MipiDsiTx的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

操作句柄

+

cmd

+

需要发送的指令数据指针

+

返回值

+

返回值描述

+

0

+

发送成功

+

负数

+

发送失败

+
+ +``` +int32_t ret; +struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); +if (cmd == NULL) { + return HDF_FAILURE; +} +cmd->dtype = DTYPE_DCS_WRITE; +cmd->dlen = 1; +cmd->payload = OsalMemCalloc(sizeof(uint8_t)); +if (cmd->payload == NULL) { + HdfFree(cmd); + return HDF_FAILURE; +} +*(cmd->payload) = DTYPE_GEN_LWRITE; +MipiDsiSetLpMode(mipiHandle); +ret = MipiDsiTx(mipiHandle, cmd); +MipiDsiSetHsMode(mipiHandle); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: PalMipiDsiTx fail! ret=%d\n", __func__, ret); + HdfFree(cmd->payload); + HdfFree(cmd); + return HDF_FAILURE; +} +HdfFree(cmd->payload); +HdfFree(cmd); +``` + +- 回读指令 + +int32\_t MipiDsiRx\(DevHandle handle, struct DsiCmdDesc \*cmd, uint32\_t readLen, uint8\_t \*out\); + +**表 6** MipiDsiRx的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

操作句柄

+

cmd

+

需要回读的指令数据指针

+

readLen

+

期望回读的数据长度

+

out

+

回读的数据buf指针

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +``` +int32_t ret; +uint8_t readVal = 0; + +struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); +if (cmdRead == NULL) { + return HDF_FAILURE; +} +cmdRead->dtype = DTYPE_DCS_READ; +cmdRead->dlen = 1; +cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); +if (cmdRead->payload == NULL) { + HdfFree(cmdRead); + return HDF_FAILURE; +} +*(cmdRead->payload) = DDIC_REG_STATUS; +MipiDsiSetLpMode(g_handle); +ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); +MipiDsiSetHsMode(g_handle); +if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); + HdfFree(cmdRead->payload); + HdfFree(cmdRead); + return HDF_FAILURE; +} +HdfFree(cmdRead->payload); +HdfFree(cmdRead); +``` + +### 释放MIPI-DSI操作句柄 + +MIPI-DSI使用完成之后,需要释放操作句柄,释放句柄的函数如下所示: + +void MipiDsiClose\(DevHandle handle\); + +该函数会释放掉由MipiDsiOpen申请的资源。 + +**表 7** MipiDsiClose的参数和返回值描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

MIPI-DSI操作句柄

+
+ +``` +MipiDsiClose(mipiHandle); /* 释放掉MIPI-DSI操作句柄 */ +``` + +## 使用实例 + +MIPI-DSI完整的使用示例如下所示: + +``` +#include "hdf.h" +#include "mipi_dsi_if.h" + +void PalMipiDsiTestSample(void) +{ + uint8_t chnId; + int32_t ret; + DevHandle handle = NULL; + + /* 设备通道编号 */ + chnId = 0; + /* 获取操作句柄 */ + handle = MipiDsiOpen(chnId); + if (handle == NULL) { + HDF_LOGE("MipiDsiOpen: failed!\n"); + return; + } + /* 配置相应参数 */ + struct MipiCfg cfg = {0}; + cfg.lane = DSI_4_LANES; + cfg.mode = DSI_CMD_MODE; + cfg.burstMode = VIDEO_NON_BURST_MODE_SYNC_EVENTS; + cfg.format = FORMAT_RGB_24_BIT; + cfg.pixelClk = 174; + cfg.phyDataRate = 384; + cfg.timingInfo.hsaPixels = 50; + cfg.timingInfo.hbpPixels = 55; + cfg.timingInfo.hlinePixels = 1200; + cfg.timingInfo.yResLines = 1800; + cfg.timingInfo.vbpLines = 33; + cfg.timingInfo.vsaLines = 76; + cfg.timingInfo.vfpLines = 120; + cfg.timingInfo.xResPixels = 1342; + /* 写入配置数据 */ + ret = MipiDsiSetCfg(g_handle, &cfg); + if (ret != 0) { + HDF_LOGE("%s: SetMipiCfg fail! ret=%d\n", __func__, ret); + return; + } + /* 发送PANEL初始化指令 */ + struct DsiCmdDesc *cmd = OsalMemCalloc(sizeof(struct DsiCmdDesc)); + if (cmd == NULL) { + return; + } + cmd->dtype = DTYPE_DCS_WRITE; + cmd->dlen = 1; + cmd->payload = OsalMemCalloc(sizeof(uint8_t)); + if (cmd->payload == NULL) { + HdfFree(cmd); + return; + } + *(cmd->payload) = DTYPE_GEN_LWRITE; + MipiDsiSetLpMode(mipiHandle); + ret = MipiDsiTx(mipiHandle, cmd); + MipiDsiSetHsMode(mipiHandle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: MipiDsiTx fail! ret=%d\n", __func__, ret); + HdfFree(cmd->payload); + HdfFree(cmd); + return; + } + HdfFree(cmd->payload); + HdfFree(cmd); + /* 回读panel状态寄存器 */ + uint8_t readVal = 0; + struct DsiCmdDesc *cmdRead = OsalMemCalloc(sizeof(struct DsiCmdDesc)); + if (cmdRead == NULL) { + return; + } + cmdRead->dtype = DTYPE_DCS_READ; + cmdRead->dlen = 1; + cmdRead->payload = OsalMemCalloc(sizeof(uint8_t)); + if (cmdRead->payload == NULL) { + HdfFree(cmdRead); + return; + } + *(cmdRead->payload) = DDIC_REG_STATUS; + MipiDsiSetLpMode(g_handle); + ret = MipiDsiRx(g_handle, cmdRead, sizeof(readVal), &readVal); + MipiDsiSetHsMode(g_handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: MipiDsiRx fail! ret=%d\n", __func__, ret); + HdfFree(cmdRead->payload); + HdfFree(cmdRead); + return; + } + HdfFree(cmdRead->payload); + HdfFree(cmdRead); + /* 释放MIPI DSI设备句柄 */ + MipiDsiClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-rtc-des.md b/zh-cn/device-dev/driver/drive-platform-rtc-des.md new file mode 100644 index 0000000000000000000000000000000000000000..fb55001feb78e4e003f25a829f51539e4893d310 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-rtc-des.md @@ -0,0 +1,944 @@ +# RTC + +- [概述](#section104842041574) + - [接口说明](#section3373340142215) + +- [使用指导](#section20636145604113) + - [使用流程](#section16919828134215) + - [创建RTC设备句柄](#section1131212144310) + - [销毁RTC设备句柄](#section10744117144314) + - [注册RTC定时报警回调函数](#section14839440184320) + - [操作RTC](#section161927578433) + +- [使用实例](#section1186111020456) + +## 概述 + +RTC\(real-time clock\)为操作系统中的实时时钟设备,为操作系统提供精准的实时时间和定时报警功能。当设备下电后,通过外置电池供电,RTC继续记录操作系统时间;设备上电后,RTC提供实时时钟给操作系统,确保断电后系统时间的连续性。 + +### 接口说明 + +**表 1** RTC设备API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

RTC句柄操作

+

RtcOpen

+

获取RTC设备驱动句柄

+

RtcClose

+

释放RTC设备驱动句柄

+

RTC时间操作接口

+

RtcReadTime

+

读RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

+

RtcWriteTime

+

写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

+

RTC报警操作接口

+

RtcReadAlarm

+

读RTC报警时间信息

+

RtcWriteAlarm

+

写RTC报警时间信息

+

RtcRegisterAlarmCallback

+

注册报警超时回调函数

+

RtcAlarmInterruptEnable

+

使能/去使能RTC报警中断

+

RTC配置操作

+

RtcGetFreq

+

读RTC外接晶振频率

+

RtcSetFreq

+

配置RTC外接晶振频率

+

RtcReset

+

RTC复位

+

读写用户定义寄存器

+

RtcReadReg

+

读用户自定义寄存器

+

RtcWriteReg

+

写用户自定义寄存器

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +在操作系统启动过程中,驱动管理模块根据配置文件加载RTC驱动,RTC驱动会检测RTC器件并初始化驱动。 + +使用RTC设备的一般流程如[图1](#fig166181128151112)所示。 + +**图 1** RTC设备使用流程图 + + +![](figure/zh-cn_image_0000001123675706.png) + +### 创建RTC设备句柄 + +RTC驱动加载成功后,驱动开发者使用驱动框架提供的查询接口并调用RTC设备驱动接口。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前操作系统支持一个RTC设备。 + +DevHandle RtcOpen\(void\); + +**表 2** RtcOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

void

+

NA

+

返回值

+

返回值描述

+

handle

+

操作成功返回 指针类型

+

NULL

+

操作失败

+
+ +``` +DevHandle handle = NULL; + +/* 获取RTC句柄 */ +handle = RtcOpen(); +if (handle == NULL) { + /* 错误处理 */ +} +``` + +### 销毁RTC设备句柄 + +销毁RTC设备句柄,系统释放对应的资源。 + +void RtcClose\(DevHandle handle\); + +**表 3** RtcClose参数描述 + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+
+ +``` +/* 销毁RTC句柄 */ +RtcClose(handle); +``` + +### 注册RTC定时报警回调函数 + +系统启动后需要注册RTC定时报警回调函数,报警超时后触发回调函数。 + +int32\_t RtcRegisterAlarmCallback\(DevHandle handle, enum RtcAlarmIndex alarmIndex, RtcAlarmCallback cb\); + +**表 4** RtcRegisterAlarmCallback参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

alarmIndex

+

报警索引

+

cb

+

定时报警回调函数

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +注册RTC\_ALARM\_INDEX\_A的定时报警处理函数, 示例如下: + +``` +/* 用户注册RTC定时报警回调函数的方法 */ +int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) +{ + if (alarmIndex == RTC_ALARM_INDEX_A) { + /* 报警A的处理 */ + } else if (alarmIndex == RTC_ALARM_INDEX_B) { + /* 报警B的处理 */ + } else { + /* 错误处理 */ + } + return 0; +} +int32_t ret; +/* 注册报警A的定时回调函数 */ +ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); +if (ret != 0) { + /* 错误处理 */ +} +``` + +### 操作RTC + +- 读取RTC时间。 + +系统从RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒,则可以通过以下函数完成: + +int32\_t RtcReadTime\(DevHandle handle, struct RtcTime \*time\); + +**表 5** RtcReadTime参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

time

+

RTC读取时间信息,包括年、月、星期、日、时、分、秒、毫秒

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; +struct RtcTime tm; + +/* 系统从RTC读取时间信息 */ +ret = RtcReadTime(handle, &tm); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置RTC时间 + +设置RTC时间,则可以通过以下函数完成: + +int32\_t RtcWriteTime\(DevHandle handle, struct RtcTime \*time\); + +**表 6** RtcWriteTime参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

time

+

写RTC时间信息,包括年、月、星期、日、时、分、秒、毫秒

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 + +``` +int32_t ret; +struct RtcTime tm; + +/* 设置RTC时间为 UTC 2020/01/01 00:59:00 .000 */ +tm.year = 2020; +tm.month = 01; +tm.day = 01; +tm.hour= 00; +tm.minute = 59; +tm.second = 00; +tm.millisecond = 0; +/* 写RTC时间信息 */ +ret = RtcWriteTime(handle, &tm); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 读取RTC报警时间 + +如果需要读取定时报警时间,则可以通过以下函数完成: + +int32\_t RtcReadAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); + +**表 7** RtcReadAlarm参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

alarmIndex

+

报警索引

+

time

+

RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; +struct RtcTime alarmTime; + +/* 读RTC_ALARM_INDEX_A索引的RTC定时报警时间信息 */ +ret = RtcReadAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置RTC报警时间 + +根据报警索引设置RTC报警时间,通过以下函数完成: + +int32\_t RtcWriteAlarm\(DevHandle handle, enum RtcAlarmIndex alarmIndex, struct RtcTime \*time\); + +**表 8** RtcWriteAlarm参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

alarmIndex

+

报警索引

+

time

+

RTC报警时间信息,包括年、月、星期、日、时、分、秒、毫秒

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>RTC起始时间为UTC 1970/01/01 Thursday 00:00:00,年的最大取值按照用户器件手册要求计算配置,星期不用配置。 + +``` +int32_t ret; +struct RtcTime alarmTime; + +/* 设置RTC报警时间为2020/01/01 00:59:59 .000 */ +alarmTime.year = 2020; +alarmTime.month = 01; +alarmTime.day = 01; +alarmTime.hour = 00; +alarmTime.minute = 59; +alarmTime.second = 59; +alarmTime.millisecond = 0; +/* 设置RTC_ALARM_INDEX_A索引的定时报警时间 */ +ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置定时报警中断使能或去使能 + +在启动报警操作前,需要先设置报警中断使能,报警超时后会触发告警回调函数,可以通过以下函数完成: + +int32\_t RtcAlarmInterruptEnable\(DevHandle handle, enum RtcAlarmIndex alarmIndex, uint8\_t enable\); + +**表 9** RtcAlarmInterruptEnable参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

alarmIndex

+

报警索引

+

enable

+

RTC报警中断配置,1:使能,0:去使能

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; + +/* 设置RTC报警中断使能 */ +ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 读取RTC外频 + +读取RTC外接晶体振荡频率,可以通过以下函数完成: + +int32\_t RtcGetFreq\(DevHandle handle, uint32\_t \*freq\); + +**表 10** RtcGetFreq参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

freq

+

RTC的外接晶体振荡频率,单位(HZ)

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; +uint32_t freq = 0; + +/* 读取RTC外接晶体振荡频率 */ +ret = RtcGetFreq(handle, &freq); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 配置RTC外频 + +配置RTC外接晶体振荡频率,可以通过以下函数完成: + +int32\_t RtcSetFreq\(DevHandle handle, uint32\_t freq\); + +**表 11** RtcSetFreq参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

freq

+

RTC的外接晶体振荡频率,单位(HZ)

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; +uint32_t freq = 32768; /* 32768 Hz */ + +/* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ +ret = RtcSetFreq(handle, freq); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 复位RTC + +复位RTC,复位RTC后各配置寄存器恢复默认值,可以通过以下函数完成: + +int32\_t RtcReset\(DevHandle handle\); + +**表 12** RtcReset参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; + +/* 复位RTC,复位RTC后各配置寄存器恢复默认值 */ +ret = RtcReset(handle); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 读取RTC自定义寄存器配置 + +按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: + +int32\_t RtcReadReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t \*value\); + +**表 13** RtcReadReg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

usrDefIndex

+

用户定义的寄存器对应索引

+

value

+

寄存器值

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; +uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义的第一个寄存器*/ +uint8_t value = 0; + +/* 按照用户定义的寄存器索引,读取对应的寄存器配置,一个索引对应一字节的配置值 */ +ret = RtcReadReg(handle, usrDefIndex, &value); +if (ret != 0) { + /* 错误处理 */ +} +``` + +- 设置RTC自定义寄存器配置 + +按照用户定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值,通过以下函数完成: + +int32\_t RtcWriteReg\(DevHandle handle, uint8\_t usrDefIndex, uint8\_t value\); + +**表 14** RtcWriteReg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

RTC设备句柄

+

usrDefIndex

+

用户定义的寄存器对应索引

+

value

+

寄存器值

+

返回值

+

返回值描述

+

0

+

操作成功

+

负数

+

操作失败

+
+ +``` +int32_t ret; +uint8_t usrDefIndex = 0; /* 定义0索引对应用户定义第一个寄存器*/ +uint8_t value = 0x10; + +/* 按照用户的定义的寄存器索引,设置对应的寄存器配置,一个索引对应一字节的配置值 */ +ret = RtcWriteReg(handle, usrDefIndex, value); +if (ret != 0) { + /* 错误处理 */ +} +``` + +## 使用实例 + +本实例提供RTC接口的完整使用流程: + +1. 系统启动,驱动管理模块会识别系统当前的RTC器件; +2. 驱动管理模块完成RTC设备的初始化和设备创建; +3. 用户通过不同API,对该RTC设备进行对应的操作; +4. 关闭RTC设备,释放设备资源。 + +示例如下: + +``` +#include "rtc_if.h" +int32_t RtcAlarmACallback(enum RtcAlarmIndex alarmIndex) +{ + if (alarmIndex == RTC_ALARM_INDEX_A) { + /* 报警A的处理 */ + printf("RTC Alarm A callback function\n\r"); + } else if (alarmIndex == RTC_ALARM_INDEX_B) { + /* 报警B的处理 */ + printf("RTC Alarm B callback function\n\r"); + } else { + /* 错误处理 */ + } + return 0; +} + +void RtcTestSample(void) +{ + int32_t ret; + struct RtcTime tm; + struct RtcTime alarmTime; + uint32_t freq; + DevHandle handle = NULL; + + /* 获取RTC设备句柄 */ + handle = RtcOpen(); + if (handle == NULL) { + /* 错误处理 */ + } + /* 注册报警A的定时回调函数 */ + ret = RtcRegisterAlarmCallback(handle, RTC_ALARM_INDEX_A, RtcAlarmACallback); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC外接晶体振荡频率,注意按照器件手册要求配置RTC外频 */ + freq = 32768; /* 32768 Hz */ + ret = RtcSetFreq(handle, freq); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC报警中断使能 */ + ret = RtcAlarmInterruptEnable(handle, RTC_ALARM_INDEX_A, 1); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC时间为2020/01/01 00:00:10 .990 */ + tm.year = 2020; + tm.month = 01; + tm.day = 01; + tm.hour= 0; + tm.minute = 0; + tm.second = 10; + tm.millisecond = 990; + /* 写RTC时间信息 */ + ret = RtcWriteTime(handle, &tm); + if (ret != 0) { + /* 错误处理 */ + } + /* 设置RTC报警时间为2020/01/01 00:00:30 .100 */ + alarmTime.year = 2020; + alarmTime.month = 01; + alarmTime.day = 01; + alarmTime.hour = 0; + alarmTime.minute = 0; + alarmTime.second = 30; + alarmTime.millisecond = 100; + /* 设置RTC_ALARM_INDEX_A索引定时报警时间信息, 定时时间到后会打印"RTC Alarm A callback function" */ + ret = RtcWriteAlarm(handle, RTC_ALARM_INDEX_A, &alarmTime); + if (ret != 0) { + /* 错误处理 */ + } + + /* 读取RTC实时时间 */ + ret = RtcReadTime(handle, &tm); + if (ret != 0) { + /* 错误处理 */ + } + sleep(5) + printf("RTC read time:\n\r"); + printf("year-month-date-weekday hour:minute:second .millisecond %04u-%02u-%02u-%u %02u:%02u:%02u .%03u", + tm.year, tm.month, tm.day, tm.weekday, tm.hour, tm.minute, tm.second, tm.millisecond); + /* 销毁RTC设备句柄 */ + RtcClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-sdio-des.md b/zh-cn/device-dev/driver/drive-platform-sdio-des.md new file mode 100644 index 0000000000000000000000000000000000000000..1d85e6496ea6abc547afcdc1536b5068eb1acdbc --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-sdio-des.md @@ -0,0 +1,1068 @@ +# SDIO + +- [概述](#section1155271783811) + - [接口说明](#section08064247248) + +- [使用指导](#section1878939192515) + - [使用流程](#section1490685512255) + - [打开SDIO控制器](#section10782428132616) + - [独占HOST](#section11263172312715) + - [使能SDIO设备](#section17861486271) + - [注册SDIO中断](#section521213262286) + - [进行SDIO通信](#section85661522153420) + - [释放SDIO中断](#section1683449352) + - [去使能SDIO设备](#section15379324143611) + - [释放HOST](#section536018263713) + - [关闭SDIO控制器](#section4752739183716) + +- [使用实例](#section376910122382) + +## 概述 + +- SDIO是安全数字输入输出接口(Secure Digital Input and Output)的缩写,是从SD内存卡接口的基础上演化出来的一种外设接口。SDIO接口兼容以前的SD内存卡,并且可以连接支持SDIO接口的设备。 +- SDIO的应用比较广泛,目前,有许多手机都支持SDIO功能,并且很多SDIO外设也被开发出来,使得手机外接外设更加容易。常见的SDIO外设有WLAN、GPS、CAMERA、蓝牙等。 +- SDIO总线有两端,其中一端是主机端(HOST),另一端是设备端(DEVICE)。所有的通信都是由HOST端发出命令开始的,在DEVICE端只要能解析HOST的命令,就可以同HOST进行通信了。SDIO的HOST可以连接多个DEVICE,如下图所示: + + - CLK信号:HOST给DEVICE的时钟信号。 + - VDD信号:电源信号。 + - VSS信号:Ground信号。 + - D0-3信号:4条数据线,其中,DAT1信号线复用为中断线,在1BIT模式下DAT0用来传输数据,在4BIT模式下DAT0-DAT3用来传输数据。 + - CMD信号:用于HOST发送命令和DEVICE回复响应。 + + **图 1** SDIO的HOST-DEVICE连接示意图 + + + ![](figure/zh-cn_image_0000001054280608.png) + +- SDIO接口定义了操作SDIO的通用方法集合,包括打开/关闭SDIO控制器、独占/释放HOST、使能/去使能设备、申请/释放中断、读写、获取/设置公共信息等。 + +### 接口说明 + +**表 1** SDIO驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

SDIO设备打开/关闭接口

+

SdioOpen

+

打开指定总线号的SDIO控制器

+

SdioClose

+

关闭SDIO控制器

+

SDIO读写接口

+

SdioReadBytes

+

从指定地址开始,增量读取指定长度的数据

+

SdioWriteBytes

+

从指定地址开始,增量写入指定长度的数据

+

SdioReadBytesFromFixedAddr

+

从固定地址读取指定长度的数据

+

SdioWriteBytesToFixedAddr

+

向固定地址写入指定长度的数据

+

SdioReadBytesFromFunc0

+

从SDIO function 0的指定地址空间读取指定长度的数据

+

SdioWriteBytesToFunc0

+

向SDIO function 0的指定地址空间写入指定长度的数据

+

SDIO设置块大小接口

+

SdioSetBlockSize

+

设置块的大小

+

SDIO获取/设置公共信息接口

+

SdioGetCommonInfo

+

获取公共信息

+

SdioSetCommonInfo

+

设置公共信息

+

SDIO刷新数据接口

+

SdioFlushData

+

刷新数据

+

SDIO独占/释放HOST接口

+

SdioClaimHost

+

独占Host

+

SdioReleaseHost

+

释放Host

+

SDIO使能/去使能功能设备接口

+

SdioEnableFunc

+

使能SDIO功能设备

+

SdioDisableFunc

+

去使能SDIO功能设备

+

SDIO申请/释放中断接口

+

SdioClaimIrq

+

申请中断

+

SdioReleaseIrq

+

释放中断

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,目前只支持在内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用SDIO的一般流程如[图2](#fig1343742311264)所示。 + +**图 2** SDIO使用流程图 + + +![](figure/zh-cn_image_0000001123540984.png) + +### 打开SDIO控制器 + +在使用SDIO进行通信前,首先要调用SdioOpen获取SDIO控制器的设备句柄,该函数会返回指定总线号的SDIO控制器的设备句柄。 + +DevHandle SdioOpen\(int16\_t mmcBusNum, struct SdioFunctionConfig \*config\); + +**表 2** SdioOpen函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

mmcBusNum

+

总线号

+

config

+

SDIO功能配置信息

+

返回值

+

返回值描述

+

NULL

+

获取SDIO控制器的设备句柄失败

+

设备句柄

+

SDIO控制器的设备句柄

+
+ +打开SDIO控制器的示例如下: + +``` +DevHandle handle = NULL; +struct SdioFunctionConfig config; +config.funcNr = 1; +config.vendorId = 0x123; +config.deviceId = 0x456; +/* 打开总线号为1的SDIO控制器 */ +handle = SdioOpen(1, &config); +if (handle == NULL) { + HDF_LOGE("SdioOpen: failed!\n"); +} +``` + +### 独占HOST + +获取到SDIO控制器的设备句柄之后,需要先独占HOST才能进行SDIO后续的一系列操作,独占HOST函数如下所示: + +void SdioClaimHost\(DevHandle handle\); + +**表 3** SdioClaimHost函数的参数描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+
+ +独占HOST示例如下: + +``` +SdioClaimHost(handle); /* 独占HOST */ +``` + +### 使能SDIO设备 + +在访问寄存器之前,需要先使能SDIO设备,使能SDIO设备的函数如下所示: + +int32\_t SdioEnableFunc\(DevHandle handle\); + +**表 4** SdioEnableFunc函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

返回值

+

返回值描述

+

0

+

SDIO使能成功

+

负数

+

SDIO使能失败

+
+ +使能SDIO设备的示例如下: + +``` +int32_t ret; +/* 使能SDIO设备 */ +ret = SdioEnableFunc(handle); +if (ret != 0) { + HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); +} +``` + +### 注册SDIO中断 + +在通信之前,还需要注册SDIO中断,注册SDIO中断函数如下图所示: + +int32\_t SdioClaimIrq\(DevHandle handle, SdioIrqHandler \*handler\); + +**表 5** SdioClaimIrq函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

handler

+

中断服务函数指针

+

返回值

+

返回值描述

+

0

+

注册中断成功

+

负数

+

注册中断失败

+
+ +注册SDIO中的示例如下: + +``` +/* 中断服务函数需要根据各自平台的情况去实现 */ +static void SdioIrqFunc(void *data) +{ + if (data == NULL) { + HDF_LOGE("SdioIrqFunc: data is NULL.\n"); + return; + } + /* 需要开发者自行添加具体实现 */ +} + +int32_t ret; +/* 注册SDIO中断 */ +ret = SdioClaimIrq(handle, SdioIrqFunc); +if (ret != 0) { + HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); +} +``` + +### 进行SDIO通信 + +- 向SDIO设备增量写入指定长度的数据 + +对应的接口函数如下所示: + +int32\_t SdioWriteBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 6** SdioWriteBytes函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

data

+

待写入数据的指针

+

addr

+

待写入数据的起始地址

+

size

+

待写入数据的长度

+

返回值

+

返回值描述

+

0

+

SDIO写数据成功

+

负数

+

SDIO写数据失败

+
+ +向SDIO设备增量写入指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t wbuff[] = {1,2,3,4,5}; +uint32_t addr = 0x100 + 0x09; +/* 向SDIO设备起始地址0x109,增量写入5个字节的数据 */ +ret = SdioWriteBytes(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0])); +if (ret != 0) { + HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); +} +``` + +- 从SDIO设备增量读取指定长度的数据 + +对应的接口函数如下所示: + +int32\_t SdioReadBytes\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 7** SdioReadBytes函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

data

+

接收读取数据的指针

+

addr

+

待读取数据的起始地址

+

size

+

待读取数据的长度

+

返回值

+

返回值描述

+

0

+

SDIO读数据成功

+

负数

+

SDIO读数据失败

+
+ +从SDIO设备增量读取指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t rbuff[5] = {0}; +uint32_t addr = 0x100 + 0x09; +/* 从SDIO设备起始地址0x109,增量读取5个字节的数据 */ +ret = SdioReadBytes(handle, rbuff, addr, 5); +if (ret != 0) { + HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); +} +``` + +- 向SDIO设备的固定地址写入指定长度的数据 + + 对应的接口函数如下所示: + + int32\_t SdioWriteBytesToFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); + + **表 8** SdioWriteBytesToFixedAddr函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

data

+

待写入数据的指针

+

addr

+

待写入数据的固定地址

+

size

+

待写入数据的长度

+

scatterLen

+

集散表的长度。如果该字段不为0,则data为集散表类型。

+

返回值

+

返回值描述

+

0

+

SDIO写数据成功

+

负数

+

SDIO写数据失败

+
+ + 向SDIO设备的固定地址写入指定长度的数据的示例如下: + + ``` + int32_t ret; + uint8_t wbuff[] = {1,2,3,4,5}; + uint32_t addr = 0x100 + 0x09; + /* 向SDIO设备固定地址0x109写入5个字节的数据 */ + ret = SdioWriteBytesToFixedAddr(handle, wbuff, addr, sizeof(wbuff) / sizeof(wbuff[0]), 0); + if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); + } + ``` + +- 从SDIO设备的固定地址读取指定长度的数据 + + 对应的接口函数如下所示: + + int32\_t SdioReadBytesFromFixedAddr\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size, uint32\_t scatterLen\); + + **表 9** SdioReadBytesFromFixedAddr函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

data

+

接收读取数据的指针

+

addr

+

待读取数据的起始地址

+

size

+

待读取数据的长度

+

scatterLen

+

集散表的长度。如果该字段不为0,则data为集散表类型。

+

返回值

+

返回值描述

+

0

+

SDIO读数据成功

+

负数

+

SDIO读数据失败

+
+ + 从SDIO设备的固定地址读取指定长度的数据的示例如下: + + ``` + int32_t ret; + uint8_t rbuff[5] = {0}; + uint32_t addr = 0x100 + 0x09; + /* 从SDIO设备固定地址0x109中读取5个字节的数据 */ + ret = SdioReadBytesFromFixedAddr(handle, rbuff, addr, 5, 0); + if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); + } + ``` + + +- 向SDIO function 0的指定地址空间写入指定长度的数据 + +当前只支持写入一个字节的数据,对应的接口函数如下所示: + +int32\_t SdioWriteBytesToFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 10** SdioWriteBytesToFunc0函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

data

+

待写入数据的指针

+

addr

+

待写入数据的起始地址

+

size

+

待写入数据的长度

+

返回值

+

返回值描述

+

0

+

SDIO写数据成功

+

负数

+

SDIO写数据失败

+
+ +向SDIO function 0的指定地址空间写入指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t wbuff = 1; +/* 向SDIO function 0地址0x2中写入1字节的数据 */ +ret = SdioWriteBytesToFunc0(handle, &wbuff, 0x2, 1); +if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); +} +``` + +- 从SDIO function 0的指定地址空间读取指定长度的数据 + +当前只支持读取一个字节的数据,对应的接口函数如下所示: + +int32\_t SdioReadBytesFromFunc0\(DevHandle handle, uint8\_t \*data, uint32\_t addr, uint32\_t size\); + +**表 11** SdioReadBytesFromFunc0函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

data

+

接收读取数据的指针

+

addr

+

待读取数据的起始地址

+

size

+

待读取数据的长度

+

返回值

+

返回值描述

+

0

+

SDIO读数据成功

+

负数

+

SDIO读数据失败

+
+ +从SDIO function 0的指定地址空间读取指定长度的数据的示例如下: + +``` +int32_t ret; +uint8_t rbuff; +/* 从SDIO function 0设备地址0x2中读取1字节的数据 */ +ret = SdioReadBytesFromFunc0(handle, &rbuff, 0x2, 1); +if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); +} +``` + +### 释放SDIO中断 + +通信完成之后,需要释放SDIO中断,函数如下所示: + +int32\_t SdioReleaseIrq\(DevHandle handle\); + +**表 12** SdioReleaseIrq函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

返回值

+

返回值描述

+

0

+

释放SDIO中断成功

+

负数

+

释放SDIO中断失败

+
+ +释放SDIO中断的示例如下: + +``` +int32_t ret; +/* 释放SDIO中断 */ +ret = SdioReleaseIrq(handle); +if (ret != 0) { + HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); +} +``` + +### 去使能SDIO设备 + +通信完成之后,还需要去使能SDIO设备,函数如下所示: + +int32\_t SdioDisableFunc\(DevHandle handle\); + +**表 13** SdioDisableFunc函数的参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+

返回值

+

返回值描述

+

0

+

去使能SDIO设备成功

+

负数

+

去使能SDIO设备失败

+
+ +去使能SDIO设备的示例如下: + +``` +int32_t ret; +/* 去使能SDIO设备 */ +ret = SdioDisableFunc(handle); +if (ret != 0) { + HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); +} +``` + +### 释放HOST + +通信完成之后,还需要释放去HOST,函数如下所示: + +void SdioReleaseHost\(DevHandle handle\); + +**表 14** SdioReleaseHost函数的参数描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+
+ +释放HOST的示例如下: + +``` +SdioReleaseHost(handle); /* 释放HOST */ +``` + +### 关闭SDIO控制器 + +SDIO通信完成之后,最后需要关闭SDIO控制器,函数如下所示: + +void SdioClose\(DevHandle handle\); + +该函数会释放掉申请的资源。 + +**表 15** SdioClose函数的参数描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SDIO控制器的设备句柄

+
+ +关闭SDIO控制器的示例如下: + +``` +SdioClose(handle); /* 关闭SDIO控制器 */ +``` + +## 使用实例 + +SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 + +``` +#include "hdf_log.h" +#include "sdio_if.h" + +#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ +#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ +#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ +#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ +#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ + +/* 中断服务函数,需要根据各自平台的情况去实现 */ +static void SdioIrqFunc(void *data) +{ + if (data == NULL) { + HDF_LOGE("SdioIrqFunc: data is NULL.\n"); + return; + } + /* 需要开发者自行添加具体的实现 */ +} + +void SdioTestSample(void) +{ + int32_t ret; + DevHandle handle = NULL; + uint8_t data[TEST_DATA_LEN] = {0}; + struct SdioFunctionConfig config = {1, 0x123, 0x456}; + uint8_t val; + uint32_t addr; + + /* 打开总线号为1的SDIO设备 */ + handle = SdioOpen(1, &config); + if (handle == NULL) { + HDF_LOGE("SdioOpen: failed!\n"); + return; + } + /* 独占HOST */ + SdioClaimHost(handle); + /* 使能SDIO设备 */ + ret = SdioEnableFunc(handle); + if (ret != 0) { + HDF_LOGE("SdioEnableFunc: failed, ret %d\n", ret); + goto ENABLE_ERR; + } + /* 注册中断 */ + ret = SdioClaimIrq(handle, SdioIrqFunc); + if (ret != 0) { + HDF_LOGE("SdioClaimIrq: failed, ret %d\n", ret); + goto CLAIM_IRQ_ERR; + } + /* 设置块大小为2字节 */ + ret = SdioSetBlockSize(handle, TEST_BLOCKSIZE); + if (ret != 0) { + HDF_LOGE("SdioSetBlockSize: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO设备增量地址读取3字节的数据 */ + addr = TEST_FBR_BASE_ADDR * TEST_FUNC_NUM + TEST_ADDR_OFFSET; + ret = SdioReadBytes(handle, data, addr, TEST_DATA_LEN); + if (ret != 0) { + HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO设备增量地址写入3字节的数据 */ + ret = SdioWriteBytes(handle, data, addr, TEST_DATA_LEN); + if (ret != 0) { + HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO设备读取1字节的数据 */ + ret = SdioReadBytes(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioReadBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO设备写入1字节的数据 */ + ret = SdioWriteBytes(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioWriteBytes: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO设备固定地址读取3字节的数据 */ + ret = SdioReadBytesFromFixedAddr(handle, data, addr, TEST_DATA_LEN, 0); + if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFixedAddr: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO设备固定地址写入1字节的数据 */ + ret = SdioWriteBytesToFixedAddr(handle, data, addr, 1, 0); + if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFixedAddr: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 从SDIO function 0读取1字节的数据 */ + addr = 0x02; + ret = SdioReadBytesFromFunc0(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioReadBytesFromFunc0: failed, ret %d\n", ret); + goto COMM_ERR; + } + /* 向SDIO function 0写入1字节的数据 */ + ret = SdioWriteBytesToFunc0(handle, &val, addr, 1); + if (ret != 0) { + HDF_LOGE("SdioWriteBytesToFunc0: failed, ret %d\n", ret); + goto COMM_ERR; + } +COMM_ERR: + /* 释放中断 */ + ret = SdioReleaseIrq(handle); + if (ret != 0) { + HDF_LOGE("SdioReleaseIrq: failed, ret %d\n", ret); + } +CLAIM_IRQ_ERR: + /* 去使能SDIO设备 */ + ret = SdioDisableFunc(handle); + if (ret != 0) { + HDF_LOGE("SdioDisableFunc: failed, ret %d\n", ret); + } +ENABLE_ERR: + /* 释放HOST */ + SdioReleaseHost(handle); + /* 关闭SDIO设备 */ + SdioClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-spi-des.md b/zh-cn/device-dev/driver/drive-platform-spi-des.md new file mode 100644 index 0000000000000000000000000000000000000000..47581f9a40529bf796a1b544cb059d6e8032ff54 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-spi-des.md @@ -0,0 +1,566 @@ +# SPI + +- [概述](#section193356154511) + - [接口说明](#section232141411476) + +- [使用指导](#section71363452477) + - [使用流程](#section32846814820) + - [获取SPI设备句柄](#section1927265711481) + - [获取SPI设备属性](#section541133418493) + - [配置SPI设备属性](#section7870106145010) + - [进行SPI通信](#section13324155195013) + - [销毁SPI设备句柄](#section19661632135117) + +- [使用实例](#section06541058155120) + +## 概述 + +- SPI是串行外设接口(Serial Peripheral Interface)的缩写,是一种高速的,全双工,同步的通信总线。 +- SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信,常用于与闪存、实时时钟、传感器以及模数转换器等进行通信。 +- SPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: + - SCLK – 时钟信号,由主设备产生; + - MOSI – 主设备数据输出,从设备数据输入; + - MISO – 主设备数据输入,从设备数据输出; + - CS – 片选,从设备使能信号,由主设备控制。 + + +- 一个主设备和两个从设备的连接示意图如[图1](#fig15227181812587)所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 + +**图 1** SPI主从设备连接示意图。 + + +![](figure/zh-cn_image_0000001123742254.png) + +- SPI通信通常由主设备发起,通过以下步骤完成一次通信: + +1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 +2. 通过SCLK给选中的从设备提供时钟信号。 +3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。 + +- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: + - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 + - CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。 + - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 + - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 + + +- SPI接口定义了操作SPI设备的通用方法集合,包括: + - SPI设备句柄获取和释放。 + - SPI读写: 从SPI设备读取或写入指定长度数据。 + - SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 + - SPI设备配置:获取和设置SPI设备属性。 + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前只支持主机模式,不支持从机模式。 + +### 接口说明 + +**表 1** SPI驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

SPI设备句柄获取释放接口

+

SpiOpen

+

获取SPI设备句柄

+

SpiClose

+

释放SPI设备句柄

+

SPI读写接口

+

SpiRead

+

读取指定长度的数据

+

SpiWrite

+

写入指定长度的数据

+

SpiTransfer

+

SPI数据传输接口

+

SPI设备配置接口

+

+

SpiSetCfg

+

根据指定参数,配置SPI设备

+

SpiGetCfg

+

获取SPI设备配置参数

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用SPI的一般流程如[图2](#fig23885455594)所示。 + +**图 2** SPI使用流程图 + + +![](figure/zh-cn_image_0000001123703482.png) + +### 获取SPI设备句柄 + +在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 + +DevHandle SpiOpen\(const struct SpiDevInfo \*info\); + +**表 2** SpiOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

info

+

SPI设备描述符

+

返回值

+

返回值描述

+

NULL

+

获取SPI设备句柄失败

+

设备句柄

+

对应的SPI设备句柄

+
+ +假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: + +``` +struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ +DevHandle spiHandle = NULL; /* SPI设备句柄 */ +spiDevinfo.busNum = 0; /* SPI设备总线号 */ +spiDevinfo.csNum = 0; /* SPI设备片选号 */ + +/* 获取SPI设备句柄 */ +spiHandle = SpiOpen(&spiDevinfo); +if (spiHandle == NULL) { + HDF_LOGE("SpiOpen: failed\n"); + return; +} +``` + +### 获取SPI设备属性 + +在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: + +int32\_t SpiGetCfg\(DevHandle handle, struct SpiCfg \*cfg\); + +**表 3** SpiGetCfg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SPI设备句柄

+

cfg

+

SPI设备配置参数

+

返回值

+

返回值描述

+

0

+

获取配置成功

+

负数

+

获取配置失败

+
+ +``` +int32_t ret; +struct SpiCfg cfg = {0}; /* SPI配置信息*/ +ret = SpiGetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ +if (ret != 0) { + HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); +} +``` + +### 配置SPI设备属性 + +在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: + +int32\_t SpiSetCfg\(DevHandle handle, struct SpiCfg \*cfg\); + +**表 4** SpiSetCfg参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SPI设备句柄

+

cfg

+

SPI设备配置参数

+

返回值

+

返回值描述

+

0

+

配置成功

+

负数

+

配置失败

+
+ +``` +int32_t ret; +struct SpiCfg cfg = {0}; /* SPI配置信息*/ +cfg.mode = SPI_MODE_LOOP; /* 以回环模式进行通信 */ +cfg.transferMode = PAL_SPI_POLLING_TRANSFER; /* 以轮询的方式进行通信 */ +cfg.maxSpeedHz = 115200; /* 最大传输频率 */ +cfg.bitsPerWord = 8; /* 读写位宽为8个比特 */ +ret = SpiSetCfg(spiHandle, &cfg); /* 配置SPI设备属性 */ +if (ret != 0) { + HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); +} +``` + +### 进行SPI通信 + +- 向SPI设备写入指定长度的数据 + +如果只向SPI设备写一次数据,则可以通过以下函数完成: + +int32\_t SpiWrite\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); + +**表 5** SpiWrite参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SPI设备句柄

+

buf

+

待写入数据的指针

+

len

+

待写入的数据长度

+

返回值

+

返回值描述

+

0

+

写入成功

+

负数

+

写入失败

+
+ +``` +int32_t ret; +uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; +/* 向SPI设备写入指定长度的数据 */ +ret = SpiWrite(spiHandle, wbuff, 4); +if (ret != 0) { + HDF_LOGE("SpiWrite: failed, ret %d\n", ret); +} +``` + +- 从SPI设备读取指定长度的数据 + +如果只读取一次数据,则可以通过以下函数完成: + +int32\_t SpiRead\(DevHandle handle, uint8\_t \*buf, uint32\_t len\); + +**表 6** SpiRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SPI设备句柄

+

buf

+

待读取数据的指针

+

len

+

待读取的数据长度

+

返回值

+

返回值描述

+

0

+

读取成功

+

负数

+

读取失败

+
+ +``` +int32_t ret; +uint8_t rbuff[4] = {0}; +/* 从SPI设备读取指定长度的数据 */ +ret = SpiRead(spiHandle, rbuff, 4); +if (ret != 0) { + HDF_LOGE("SpiRead: failed, ret %d\n", ret); +} +``` + +- 自定义传输 + +如果需要发起一次自定义传输,则可以通过以下函数完成: + +int32\_t SpiTransfer\(DevHandle handle, struct SpiMsg \*msgs, uint32\_t count\); + +**表 7** SpiTransfer参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

SPI设备句柄

+

msgs

+

待传输数据的数组

+

count

+

msgs数组长度

+

返回值

+

返回值描述

+

0

+

执行成功

+

负数

+

执行失败

+
+ +``` +int32_t ret; +uint8_t wbuff[1] = {0x12}; +uint8_t rbuff[1] = {0}; +struct SpiMsg msg; /* 自定义传输的消息*/ +msg.wbuf = wbuff; /* 写入的数据 */ +msg.rbuf = rbuff; /* 读取的数据 */ +msg.len = 1; /* 读取、写入数据的长度都是1 */ +msg.csChange = 1; /* 进行下一次传输前关闭片选 */ +msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ +msg.speed = 115200; /* 本次传输的速度 */ +/* 进行一次自定义传输,传输的msg个数为1 */ +ret = SpiTransfer(spiHandle, &msg, 1); +if (ret != 0) { + HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); +} +``` + +### 销毁SPI设备句柄 + +SPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: + +void SpiClose\(DevHandle handle\); + +该函数会释放掉申请的资源。 + +**表 8** SpiClose参数描述 + + + + + + + + + +

参数

+

参数描述

+

handle

+

SPI设备句柄

+
+ +``` +SpiClose(spiHandle); /* 销毁SPI设备句柄 */ +``` + +## 使用实例 + +SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 + +``` +#include "hdf_log.h" +#include "spi_if.h" + +void SpiTestSample(void) +{ + int32_t ret; + struct SpiCfg cfg; /* SPI配置信息 */ + struct SpiDevInfo spiDevinfo; /* SPI设备描述符 */ + DevHandle spiHandle = NULL; /* SPI设备句柄 */ + struct SpiMsg msg; /* 自定义传输的消息 */ + uint8_t rbuff[4] = { 0 }; + uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 }; + uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 }; + + spiDevinfo.busNum = 0; /* SPI设备总线号 */ + spiDevinfo.csNum = 0; /* SPI设备片选号 */ + spiHandle = SpiOpen(&spiDevinfo); /* 根据spiDevinfo获取SPI设备句柄 */ + if (spiHandle == NULL) { + HDF_LOGE("SpiOpen: failed\n"); + return; + } + /* 获取SPI设备属性 */ + ret = SpiGetCfg(spiHandle, &cfg); + if (ret != 0) { + HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); + goto err; + } + cfg.maxSpeedHz = 115200; /* 将最大时钟频率改为115200 */ + cfg.bitsPerWord = 8; /* 传输位宽改为8比特 */ + /* 配置SPI设备属性 */ + ret = SpiSetCfg(spiHandle, &cfg); + if (ret != 0) { + HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); + goto err; + } + /* 向SPI设备写入指定长度的数据 */ + ret = SpiWrite(spiHandle, wbuff, 4); + if (ret != 0) { + HDF_LOGE("SpiWrite: failed, ret %d\n", ret); + goto err; + } + /* 从SPI设备读取指定长度的数据 */ + ret = SpiRead(spiHandle, rbuff, 4); + if (ret != 0) { + HDF_LOGE("SpiRead: failed, ret %d\n", ret); + goto err; + } + msg.wbuf = wbuff2; /* 写入的数据 */ + msg.rbuf = rbuff; /* 读取的数据 */ + msg.len = 4; /* 读取写入数据的长度为4 */ + msg.csChange = 1; /* 进行下一次传输前关闭片选 */ + msg.delayUs = 0; /* 进行下一次传输前不进行延时 */ + msg.speed = 115200; /* 本次传输的速度 */ + /* 进行一次自定义传输,传输的msg个数为1 */ + ret = SpiTransfer(spiHandle, &msg, 1); + if (ret != 0) { + HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); + goto err; + } +err: + /* 销毁SPI设备句柄 */ + SpiClose(spiHandle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-uart-des.md b/zh-cn/device-dev/driver/drive-platform-uart-des.md new file mode 100644 index 0000000000000000000000000000000000000000..182cad984a49051847129210d7cce9e9db7bbcdd --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-uart-des.md @@ -0,0 +1,682 @@ +# UART + +- [概述](#section833012453535) + - [接口说明](#section1680292311549) + +- [使用指导](#section12779050105412) + - [使用流程](#section1858116395510) + - [获取UART设备句柄](#section124512065617) + - [UART设置波特率](#section86881004579) + - [UART获取波特率](#section897032965712) + - [UART设置设备属性](#section129141884588) + - [UART获取设备属性](#section18689637165812) + - [设置UART传输模式](#section72713435918) + - [向UART设备写入指定长度的数据](#section128001736155919) + - [从UART设备中读取指定长度的数据](#section92851601604) + - [销毁UART设备句柄](#section1477410521406) + +- [使用实例](#section35404241311) + +## 概述 + +- UART是通用异步收发传输器(Universal Asynchronous Receiver/Transmitter)的缩写,是通用串行数据总线,用于异步通信。该总线双向通信,可以实现全双工传输。 +- UART应用比较广泛,常用于输出打印信息,也可以外接各种模块,如GPS、蓝牙等。 +- 两个UART设备的连接示意图如下,UART与其他模块一般用2线(图1)或4线(图2)相连,它们分别是: + - TX:发送数据端,和对端的RX相连; + - RX:接收数据端,和对端的TX相连; + - RTS:发送请求信号,用于指示本设备是否准备好,可接受数据,和对端CTS相连; + - CTS:允许发送信号,用于判断是否可以向对端发送数据,和对端RTS相连; + + **图 1** 2线UART设备连接示意图 + + + ![](figure/zh-cn_image_0000001170262141.png) + + **图 2** 4线UART设备连接示意图 + + + ![](figure/zh-cn_image_0000001123582482.png) + + +- UART通信之前,收发双方需要约定好一些参数:波特率、数据格式(起始位、数据位、校验位、停止位)等。通信过程中,UART通过TX发送给对端数据,通过RX接收对端发送的数据。当UART接收缓存达到预定的门限值时,RTS变为不可发送数据,对端的CTS检测到不可发送数据,则停止发送数据。 +- UART接口定义了操作UART端口的通用方法集合,包括获取、释放设备句柄、读写数据、获取和设置波特率、获取和设置设备属性。 + +### 接口说明 + +**表 1** UART驱动API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

UART获取/释放设备句柄

+

+

UartOpen

+

UART获取设备句柄

+

UartClose

+

UART释放设备句柄

+

UART读写接口

+

+

UartRead

+

从UART设备中读取指定长度的数据

+

UartWrite

+

向UART设备中写入指定长度的数据

+

UART获取/设置波特率接口

+

UartGetBaud

+

UART获取波特率

+

UartSetBaud

+

UART设置波特率

+

UART获取/设置设备属性

+

+

UartGetAttribute

+

UART获取设备属性

+

UartSetAttribute

+

UART设置设备属性

+

UART设置传输模式

+

UartSetTransMode

+

UART设置传输模式

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用UART的一般流程如[图3](#fig1852173020185)所示。 + +**图 3** UART使用流程图 + + +![](figure/zh-cn_image_0000001170227689.png) + +### 获取UART设备句柄 + +在使用UART进行通信时,首先要调用UartOpen获取UART设备句柄,该函数会返回指定端口号的UART设备句柄。 + +DevHandle UartOpen\(uint32\_t port\); + +**表 2** UartOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

port

+

UART设备号

+

返回值

+

返回值描述

+

NULL

+

获取UART设备句柄失败

+

设备句柄

+

UART设备句柄

+
+ +假设系统中的UART端口号为3,获取该UART设备句柄的示例如下: + +``` +DevHandle handle = NULL; /* UART设备句柄 */ +uint32_t port = 3; /* UART设备端口号 */ +handle = UartOpen(port); +if (handle == NULL) { + HDF_LOGE("UartOpen: failed!\n"); + return; +} +``` + +### UART设置波特率 + +在通信之前,需要设置UART的波特率,设置波特率的函数如下所示: + +int32\_t UartSetBaud\(DevHandle handle, uint32\_t baudRate\); + +**表 3** UartSetBaud参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

baudRate

+

待设置的波特率值

+

返回值

+

返回值描述

+

0

+

UART设置波特率成功

+

负数

+

UART设置波特率失败

+
+ +假设需要设置的UART波特率为9600,设置波特率的实例如下: + +``` +int32_t ret; +/* 设置UART波特率 */ +ret = UartSetBaud(handle, 9600); +if (ret != 0) { + HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); +} +``` + +### UART获取波特率 + +设置UART的波特率后,可以通过获取波特率接口来查看UART当前的波特率,获取波特率的函数如下所示: + +int32\_t UartGetBaud\(DevHandle handle, uint32\_t \*baudRate\); + +**表 4** UartGetBaud参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

baudRate

+

接收波特率值的指针

+

返回值

+

返回值描述

+

0

+

UART获取波特率成功

+

负数

+

UART获取波特率失败

+
+ +获取波特率的实例如下: + +``` +int32_t ret; +uint32_t baudRate; +/* 获取UART波特率 */ +ret = UartGetBaud(handle, &baudRate); +if (ret != 0) { + HDF_LOGE("UartGetBaud: failed, ret %d\n", ret); +} +``` + +### UART设置设备属性 + +在通信之前,需要设置UART的设备属性,设置设备属性的函数如下图所示: + +int32\_t UartSetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); + +**表 5** UartSetAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

attribute

+

待设置的设备属性

+

返回值

+

返回值描述

+

0

+

UART设置设备属性成功

+

负数

+

UART设置设备属性失败

+
+ +设置UART的设备属性的实例如下: + +``` +int32_t ret; +struct UartAttribute attribute; +attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ +attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ +attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ +attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ +attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ +attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ +attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ +/* 设置UART设备属性 */ +ret = UartSetAttribute(handle, &attribute); +if (ret != 0) { + HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); +} +``` + +### UART获取设备属性 + +设置UART的设备属性后,可以通过获取设备属性接口来查看UART当前的设备属性,获取设备属性的函数如下图所示: + +int32\_t UartGetAttribute\(DevHandle handle, struct UartAttribute \*attribute\); + +**表 6** UartGetAttribute参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

attribute

+

接收UART设备属性的指针

+

返回值

+

返回值描述

+

0

+

UART获取设备属性成功

+

负数

+

UART获取设备属性失败

+
+ +获取UART的设备属性的实例如下: + +``` +int32_t ret; +struct UartAttribute attribute; +/* 获取UART设备属性 */ +ret = UartGetAttribute(handle, &attribute); +if (ret != 0) { + HDF_LOGE("UartGetAttribute: failed, ret %d\n", ret); +} +``` + +### 设置UART传输模式 + +在通信之前,需要设置UART的传输模式,设置传输模式的函数如下图所示: + +int32\_t UartSetTransMode\(DevHandle handle, enum UartTransMode mode\); + +**表 7** UartSetTransMode参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

mode

+

待设置的传输模式,

+

返回值

+

返回值描述

+

0

+

UART设置传输模式成功

+

负数

+

UART设置传输模式失败

+
+ +假设需要设置的UART传输模式为UART\_MODE\_RD\_BLOCK,设置传输模式的实例如下: + +``` +int32_t ret; +/* 设置UART传输模式 */ +ret = UartSetTransMode(handle, UART_MODE_RD_BLOCK); +if (ret != 0) { + HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); +} +``` + +### 向UART设备写入指定长度的数据 + +对应的接口函数如下所示: + +int32\_t UartWrite\(DevHandle handle, uint8\_t \*data, uint32\_t size\); + +**表 8** UartWrite参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

data

+

待写入数据的指针

+

size

+

待写入数据的长度

+

返回值

+

返回值描述

+

0

+

UART写数据成功

+

负数

+

UART写数据失败

+
+ +写入指定长度数据的实例如下: + +``` +int32_t ret; +uint8_t wbuff[5] = {1, 2, 3, 4, 5}; +/* 向UART设备写入指定长度的数据 */ +ret = UartWrite(handle, wbuff, 5); +if (ret != 0) { + HDF_LOGE("UartWrite: failed, ret %d\n", ret); +} +``` + +### 从UART设备中读取指定长度的数据 + +对应的接口函数如下所示: + +int32\_t UartRead\(DevHandle handle, uint8\_t \*data, uint32\_t size\); + +**表 9** UartRead参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+

data

+

接收读取数据的指针

+

size

+

待读取数据的长度

+

返回值

+

返回值描述

+

非负数

+

UART读取到的数据长度

+

负数

+

UART读取数据失败

+
+ +读取指定长度数据的实例如下: + +``` +int32_t ret; +uint8_t rbuff[5] = {0}; +/* 从UART设备读取指定长度的数据 */ +ret = UartRead(handle, rbuff, 5); +if (ret < 0) { + HDF_LOGE("UartRead: failed, ret %d\n", ret); +} +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>UART返回值为非负值,表示UART读取成功。若返回值等于0,表示UART无有效数据可以读取。若返回值大于0,表示实际读取到的数据长度,该长度小于或等于传入的参数size的大小,并且不超过当前正在使用的UART控制器规定的最大单次读取数据长度的值。 + +### 销毁UART设备句柄 + +UART通信完成之后,需要销毁UART设备句柄,函数如下所示: + +void UartClose\(DevHandle handle\); + +该函数会释放申请的资源。 + +**表 10** UartClose参数和返回值描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

UART设备句柄

+
+ +销毁UART设备句柄的实例如下: + +``` +UartClose(handle); /* 销毁UART设备句柄 * +``` + +## 使用实例 + +UART设备完整的使用示例如下所示,首先获取UART设备句柄,接着设置波特率、设备属性和传输模式,之后进行UART通信,最后销毁UART设备句柄。 + +``` +#include "hdf_log.h" +#include "uart_if.h" + +void UartTestSample(void) +{ + int32_t ret; + uint32_t port; + DevHandle handle = NULL; + uint8_t wbuff[5] = { 1, 2, 3, 4, 5 }; + uint8_t rbuff[5] = { 0 }; + struct UartAttribute attribute; + attribute.dataBits = UART_ATTR_DATABIT_7; /* UART传输数据位宽,一次传输7个bit */ + attribute.parity = UART_ATTR_PARITY_NONE; /* UART传输数据无校检 */ + attribute.stopBits = UART_ATTR_STOPBIT_1; /* UART传输数据停止位为1位 */ + attribute.rts = UART_ATTR_RTS_DIS; /* UART禁用RTS */ + attribute.cts = UART_ATTR_CTS_DIS; /* UART禁用CTS */ + attribute.fifoRxEn = UART_ATTR_RX_FIFO_EN; /* UART使能RX FIFO */ + attribute.fifoTxEn = UART_ATTR_TX_FIFO_EN; /* UART使能TX FIFO */ + /* UART设备端口号,要填写实际平台上的端口号 */ + port = 1; + /* 获取UART设备句柄 */ + handle = UartOpen(port); + if (handle == NULL) { + HDF_LOGE("UartOpen: failed!\n"); + return; + } + /* 设置UART波特率为9600 */ + ret = UartSetBaud(handle, 9600); + if (ret != 0) { + HDF_LOGE("UartSetBaud: failed, ret %d\n", ret); + goto _ERR; + } + /* 设置UART设备属性 */ + ret = UartSetAttribute(handle, &attribute); + if (ret != 0) { + HDF_LOGE("UartSetAttribute: failed, ret %d\n", ret); + goto _ERR; + } + /* 设置UART传输模式为非阻塞模式 */ + ret = UartSetTransMode(handle, UART_MODE_RD_NONBLOCK); + if (ret != 0) { + HDF_LOGE("UartSetTransMode: failed, ret %d\n", ret); + goto _ERR; + } + /* 向UART设备写入5字节的数据 */ + ret = UartWrite(handle, wbuff, 5); + if (ret != 0) { + HDF_LOGE("UartWrite: failed, ret %d\n", ret); + goto _ERR; + } + /* 从UART设备读取5字节的数据 */ + ret = UartRead(handle, rbuff, 5); + if (ret < 0) { + HDF_LOGE("UartRead: failed, ret %d\n", ret); + goto _ERR; + } +_ERR: + /* 销毁UART设备句柄 */ + UartClose(handle); +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform-watchdog-des.md b/zh-cn/device-dev/driver/drive-platform-watchdog-des.md new file mode 100644 index 0000000000000000000000000000000000000000..b6eba28de3581722b16b58ed7a4e31e6b7054362 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform-watchdog-des.md @@ -0,0 +1,557 @@ +# WATCHDOG + +- [概述](#section14918241977) + - [接口说明](#section20177131219818) + +- [使用指导](#section10103184312813) + - [使用流程](#section10181195910815) + - [打开看门狗设备](#section66089201107) + - [获取看门狗状态](#section786624341011) + - [设置超时时间](#section182386137111) + - [获取超时时间](#section1883310371114) + - [启动看门狗](#section82501405123) + - [喂狗](#section3547530101211) + - [停止看门狗](#section944595841217) + - [关闭看门狗设备](#section96561824121311) + +- [使用实例](#section1724514523135) + +## 概述 + +看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。 + +### 接口说明 + +**表 1** 看门狗 API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

打开/关闭看门狗

+

WatchdogOpen

+

打开看门狗设备

+

WatchdogClose

+

关闭看门狗设备

+

启动/停止看门狗

+

WatchdogStart

+

启动看门狗

+

WatchdogStop

+

停止看门狗

+

设置/获取超时时间

+

WatchdogSetTimeout

+

设置看门狗超时时间

+

WatchdogGetTimeout

+

获取看门狗超时时间

+

获取看门狗状态

+

WatchdogGetStatus

+

获取看门狗状态

+

清除看门狗定时器

+

WatchdogFeed

+

清除看门狗定时器(喂狗)

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>本文涉及看门狗的所有接口,仅限内核态使用,不支持在用户态使用。 + +## 使用指导 + +### 使用流程 + +使用看门狗的一般流程如[图1](#fig19134125410189)所示。 + +**图 1** 看门狗使用流程图 + + +![](figure/zh-cn_image_0000001170229891.png) + +### 打开看门狗设备 + +在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备: + +int32\_t WatchdogOpen\(int16\_t wdtId\); + +**表 2** WatchdogOpen参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

wdtId

+

看门狗设备号

+

返回值

+

返回值描述

+

NULL

+

打开失败

+

DevHandle类型指针

+

看门狗设备句柄

+
+ +``` +DevHandle handle = NULL; +handle = WatchdogOpen(0); /* 打开0号看门狗设备 */ +if (handle == NULL) { + HDF_LOGE("WatchdogOpen: failed, ret %d\n", ret); + return; +} +``` + +### 获取看门狗状态 + +int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\); + +**表 3** WatchdogGetStatus参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+

status

+

获取到的启动状态指针

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +``` +int32_t ret; +int32_t status; +/* 获取Watchdog启动状态 */ +ret = WatchdogGetStatus(handle, &status); +if (ret != 0) { + HDF_LOGE("WatchdogGetStatus: failed, ret %d\n", ret); + return; +} +``` + +### 设置超时时间 + +int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\); + +**表 4** WatchdogSetTimeout参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+

seconds

+

超时时间,单位为秒

+

返回值

+

返回值描述

+

0

+

设置成功

+

负数

+

设置失败

+
+ +``` +int32_t ret; +uint32_t timeOut = 60; +/* 设置超时时间,单位:秒 */ +ret = WatchdogSetTimeout(handle, timeOut); +if (ret != 0) { + HDF_LOGE("WatchdogSetTimeout: failed, ret %d\n", ret); + return; +} +``` + +### 获取超时时间 + +int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\); + +**表 5** WatchdogGetTimeout参数和返回值描述 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+

seconds

+

接收超时时间的指针,单位为秒

+

返回值

+

返回值描述

+

0

+

获取成功

+

负数

+

获取失败

+
+ +``` +int32_t ret; +uint32_t timeOut; +/* 获取超时时间,单位:秒 */ +ret = WatchdogGetTimeout(handle, &timeOut); +if (ret != 0) { + HDF_LOGE("WatchdogGetTimeout: failed, ret %d\n", ret); + return; +} +``` + +### 启动看门狗 + +int32\_t WatchdogStart\(DevHandle handle\); + +**表 6** WatchdogStart参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+

返回值

+

返回值描述

+

0

+

启动成功

+

负数

+

启动失败

+
+ +``` +int32_t ret; +/* 启动看门狗 */ +ret = WatchdogStart(handle); +if (ret != 0) { + HDF_LOGE("WatchdogStart: failed, ret %d\n", ret); + return; +} +``` + +### 喂狗 + +int32\_t WatchdogFeed\(DevHandle handle\); + +**表 7** WatchdogFeed参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+

返回值

+

返回值描述

+

0

+

喂狗成功

+

负数

+

喂狗失败

+
+ +``` +int32_t ret; +/* 喂狗 */ +ret = WatchdogFeed(handle); +if (ret != 0) { + HDF_LOGE("WatchdogFeed: failed, ret %d\n", ret); + return; +} +``` + +### 停止看门狗 + +int32\_t WatchdogStop\(DevHandle handle\); + +**表 8** WatchdogStop参数和返回值描述 + + + + + + + + + + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+

返回值

+

返回值描述

+

0

+

停止成功

+

负数

+

停止失败

+
+ +``` +int32_t ret; +/* 停止看门狗 */ +ret = WatchdogStop(handle); +if (ret != 0) { + HDF_LOGE("WatchdogStop: failed, ret %d\n", ret); + return; +} +``` + +### 关闭看门狗设备 + +当操作完毕时,使用WatchdogClose关闭打开的设备句柄: + +void WatchdogClose\(DevHandle handle\); + +**表 9** WatchdogClose参数和返回值描述 + + + + + + + + + + +

参数

+

参数描述

+

handle

+

看门狗设备句柄

+
+ +``` +/* 关闭看门狗 */ +ret = WatchdogClose(handle); +``` + +## 使用实例 + +本例程提供看门狗的完整使用流程。 + +在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时: + +- 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。 +- 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。 + +示例如下: + +``` +#include "watchdog_if.h" +#include "hdf_log.h" +#include "osal_irq.h" +#include "osal_time.h" + +#define WATCHDOG_TEST_TIMEOUT 2 +#define WATCHDOG_TEST_FEED_TIME 6 + +static int32_t TestCaseWatchdog(void) +{ + int32_t i; + int32_t ret; + uint32_t timeout; + DevHandle handle = NULL; + + /* 打开0号看门狗设备 */ + handle = WatchdogOpen(0); + if (handle == NULL) { + HDF_LOGE("Open watchdog fail!"); + return -1; + } + + /* 设置超时时间 */ + ret = WatchdogSetTimeout(handle, WATCHDOG_TEST_TIMEOUT); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: set timeout fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + + /* 回读设置的超时时间值 */ + ret = WatchdogGetTimeout(handle, &timeout); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: get timeout fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + HDF_LOGI("%s: read timeout back:%u\n", __func__, timeout); + + /* 启动看门狗,开始计时 */ + ret = WatchdogStart(handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: satrt fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + + /* 每隔1S喂狗一次 */ + for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { + HDF_LOGE("%s: feeding watchdog %d times... \n", __func__, i); + ret = WatchdogFeed(handle); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret); + WatchdogClose(handle); + return ret; + } + OsalSleep(1); + } + /* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */ + HDF_LOGE("%s: no reset ... feeding test OK!!!\n", __func__); + + /* 接下来持续不喂狗,使得看门狗计时器超时 */ + for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { + HDF_LOGE("%s: watiting dog buck %d times... \n", __func__, i); + OsalSleep(1); + } + + /* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */ + HDF_LOGE("%s: dog has't buck!!! \n", __func__, i); + WatchdogClose(handle); + return -1; +} +``` + diff --git a/zh-cn/device-dev/driver/drive-platform.md b/zh-cn/device-dev/driver/drive-platform.md new file mode 100644 index 0000000000000000000000000000000000000000..6fd91defa4e17e224eaa56d479b18dea7a68b8a4 --- /dev/null +++ b/zh-cn/device-dev/driver/drive-platform.md @@ -0,0 +1,19 @@ +# 平台驱动 + +- **[GPIO](drive-platform-gpio-des.md)** + +- **[I2C](drive-platform-i2c-des.md)** + +- **[RTC](drive-platform-rtc-des.md)** + +- **[SDIO](drive-platform-sdio-des.md)** + +- **[SPI](drive-platform-spi-des.md)** + +- **[UART](drive-platform-uart-des.md)** + +- **[WATCHDOG](drive-platform-watchdog-des.md)** + +- **[MIPI DSI](drive-platform-mipidsi-des.md)** + + diff --git a/zh-cn/device-dev/driver/drive.md b/zh-cn/device-dev/driver/drive.md new file mode 100644 index 0000000000000000000000000000000000000000..0e8e677c95df4a6aebefedb3ace6d9194778c076 --- /dev/null +++ b/zh-cn/device-dev/driver/drive.md @@ -0,0 +1,19 @@ +# 驱动使用指南 + +- **[HDF开发概述](drive-hdf-overview.md)** + +- **[驱动开发](drive-hdf-development.md)** + +- **[驱动服务管理](drive-hdf-servicemanage.md)** + +- **[驱动消息机制管理](drive-hdf-news.md)** + +- **[配置管理](drive-hdf-manage.md)** + +- **[HDF开发实例](drive-hdf-sample.md)** + +- **[平台驱动](drive-platform.md)** + +- **[外设](drive-peripherals.md)** + + diff --git "a/zh-cn/device-dev/driver/figures/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figure/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figure/DSI\345\217\221\351\200\201-\346\216\245\346\224\266\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figures/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/driver/figure/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/driver/figure/I2C\347\211\251\347\220\206\350\277\236\347\272\277\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/MIPI-DSI\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figure/MIPI-DSI\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/MIPI-DSI\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figure/MIPI-DSI\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" "b/zh-cn/device-dev/driver/figure/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" rename to "zh-cn/device-dev/driver/figure/Sensor\351\251\261\345\212\250\346\250\241\345\236\213\345\233\276.png" diff --git "a/zh-cn/device-dev/driver/figures/TTL\346\216\245\345\217\243.png" "b/zh-cn/device-dev/driver/figure/TTL\346\216\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/TTL\346\216\245\345\217\243.png" rename to "zh-cn/device-dev/driver/figure/TTL\346\216\245\345\217\243.png" diff --git "a/zh-cn/device-dev/driver/figures/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" "b/zh-cn/device-dev/driver/figure/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" rename to "zh-cn/device-dev/driver/figure/Touchscreen\345\231\250\344\273\266\345\270\270\347\224\250\347\256\241\350\204\232.png" diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001053405727.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001053405727.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001053405727.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001053405727.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054280608.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001054280608.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054280608.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001054280608.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054564784.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001054564784.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054564784.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001054564784.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001057902344.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123509750.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001057902344.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123509750.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001072553354.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123514210.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001072553354.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123514210.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054440624.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123540984.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054440624.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123540984.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054007499.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123582482.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054007499.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123582482.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054728498.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123675706.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054728498.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123675706.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054726248.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123703482.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054726248.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123703482.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054142582.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001123742254.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054142582.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001123742254.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001057342245.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170187071.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001057342245.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170187071.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001054006983.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170227689.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001054006983.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170227689.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001057622716.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170229891.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001057622716.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170229891.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001053926237.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170262141.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001053926237.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170262141.png diff --git a/zh-cn/device-dev/driver/figures/zh-cn_image_0000001055299108.png b/zh-cn/device-dev/driver/figure/zh-cn_image_0000001170383063.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/driver/figures/zh-cn_image_0000001055299108.png rename to zh-cn/device-dev/driver/figure/zh-cn_image_0000001170383063.png diff --git "a/zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" "b/zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" rename to "zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204Display\351\251\261\345\212\250\346\250\241\345\236\213.png" diff --git "a/zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" "b/zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" rename to "zh-cn/device-dev/driver/figure/\345\237\272\344\272\216HDF\351\251\261\345\212\250\346\241\206\346\236\266\347\232\204input\351\251\261\345\212\250\346\250\241\345\236\213.png" diff --git "a/zh-cn/device-dev/driver/figures/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" "b/zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/driver/figures/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" rename to "zh-cn/device-dev/driver/figure/\346\216\245\345\217\243\345\210\206\345\270\203\345\233\2764.png" diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/driver/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/driver/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-note.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/driver/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/driver/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/driver/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/driver/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/driver/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/driver/public_sys-resources/icon-warning.gif and /dev/null differ diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100755 index 2222c0fde7eae0be2288c10291da6172cf688401..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,583 +0,0 @@ -# 传感器驱动开发实例 - -基于HDF驱动模型,加载启动加速度计传感器驱动,代码形式如下,具体原理可参考[HDF驱动开发指南](驱动开发.md)。加速度传感器选择通讯接口方式为I2C,厂家选择博世BMI160加速度传感器。 - -1. 加速度计传感器驱动入口注册 - -- 加速度计传感器驱动入口函数实现 - -``` -/* 注册加速度计传感器入口数据结构体对象 */ -struct HdfDriverEntry g_sensorAccelDevEntry = { - .moduleVersion = 1, /* 加速度计传感器模块版本号 */ - .moduleName = "HDF_SENSOR_ACCEL", /* 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样*/ - .Bind = BindAccelDriver, /* 加速度计传感器绑定函数 */ - .Init = InitAccelDriver, /* 加速度计传感器初始化函数 */ - .Release = ReleaseAccelDriver, /* 加速度计传感器资源释放函数 */ -}; - -/* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */ -HDF_INIT(g_sensorAccelDevEntry); -``` - -- 加速度计传感器设备配置描述 - -加速度传感器模型使用HCS作为配置描述源码,HCS配置字段详细介绍参考[配置管理](配置管理.md)介绍。 - -``` -/* 加速度计传感器设备HCS配置 */ -device_sensor_accel :: device { - device0 :: deviceNode { - policy = 1; /* policy字段是驱动服务发布的策略 */ - priority = 105; /* 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 */ - preload = 2; /* 驱动按需加载字段,0表示加载,2表示不加载 */ - permission = 0664; /* 驱动创建设备节点权限 */ - moduleName = "HDF_SENSOR_ACCEL"; /* 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 */ - serviceName = "sensor_accel"; /* 驱动对外发布服务的名称,必须唯一 */ - deviceMatchAttr = "hdf_sensor_accel_driver"; /* 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 */ - } -} -``` - -1. 加速度计传感器驱动初始化和去初始化 - -- 初始化入口函数init - -``` -/* 加速度计传感器驱动对外提供的服务绑定到HDF框架 */ -int32_t BindAccelDriver(struct HdfDeviceObject *device) -{ - CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); - - static struct IDeviceIoService service = { - .object = {0}, - .Dispatch = DispatchAccel, - }; - device->service = &service; - - return HDF_SUCCESS; -} -/*在探测到器件在位后,需要调用RegisterAccelChipOps注册差异化适配函数*/ -int32_t RegisterAccelChipOps(struct AccelOpsCall *ops) -{ - struct AccelDrvData *drvData = NULL; - - CHECK_NULL_PTR_RETURN_VALUE(ops, HDF_ERR_INVALID_PARAM); - - drvData = AccelGetDrvData(); - drvData->ops.Init = ops->Init; - drvData->ops.ReadData = ops->ReadData; - return HDF_SUCCESS; -} -/* 挂载加速度计传感器驱动归一化的接口函数 */ -static int32_t InitAccelOps(struct SensorDeviceInfo *deviceInfo) -{ - struct AccelDrvData *drvData = AccelGetDrvData(); - - (void)memset_s((void *)deviceInfo, sizeof(*deviceInfo), 0, sizeof(*deviceInfo)); - deviceInfo->ops.GetInfo = SetAccelInfo; - deviceInfo->ops.Enable = SetAccelEnable; - deviceInfo->ops.Disable = SetAccelDisable; - deviceInfo->ops.SetBatch = SetAccelBatch; - deviceInfo->ops.SetMode = SetAccelMode; - deviceInfo->ops.SetOption = SetAccelOption; - - if (memcpy_s(&deviceInfo->sensorInfo, sizeof(deviceInfo->sensorInfo), - &drvData->accelCfg->sensorInfo, sizeof(drvData->accelCfg->sensorInfo)) != EOK) { - HDF_LOGE("%s: copy sensor info failed", __func__); - return HDF_FAILURE; - } - /* 传感器类型标识可以在数据HCS配置文件里面配置,也可以在此处 */ - drvData->accelCfg->sensorInfo.sensorTypeId = SENSOR_TAG_ACCELEROMETER; - drvData->accelCfg->sensorInfo.sensorId = SENSOR_TAG_ACCELEROMETER; - - return HDF_SUCCESS; -} -/* 传感器寄存器初始化操作 */ -static int32_t InitAccelAfterConfig(void) -{ - struct SensorDeviceInfo deviceInfo; - - if (InitAccelConfig() != HDF_SUCCESS) { - HDF_LOGE("%s: init accel config failed", __func__); - return HDF_FAILURE; - } - - if (InitAccelOps(&deviceInfo) != HDF_SUCCESS) { - HDF_LOGE("%s: init accel ops failed", __func__); - return HDF_FAILURE; - } - - if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) { - HDF_LOGE("%s: add accel device failed", __func__); - return HDF_FAILURE; - } - - return HDF_SUCCESS; -} -/*通过器件探测函数,挂载器件差异化函数接口*/ -static int32_t DetectAccelChip(void) -{ - int32_t num; - int32_t ret; - int32_t loop; - struct AccelDrvData *drvData = AccelGetDrvData(); - CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); - - num = sizeof(g_accelDetectIfList) / sizeof(g_accelDetectIfList[0]); - for (loop = 0; loop < num; ++loop) { - if (g_accelDetectIfList[loop].DetectChip != NULL) { - ret = g_accelDetectIfList[loop].DetectChip(drvData->accelCfg); - if (ret == HDF_SUCCESS) { - drvData->detectFlag = true; - break; - } - } - } - - if (loop == num) { - HDF_LOGE("%s: detect accel device failed", __func__); - drvData->detectFlag = false; - return HDF_FAILURE; - } - return HDF_SUCCESS; -} -/* 加速度计传感器驱动初始化入口函数,主要功能为对传感器私有数据的结构体对象进行初始化,传感器HCS数据配置对象空间分配,传感器HCS数据配置初始化入口函数调用,传感器设备探测是否在位功能,传感器数据上报定时器创建,传感器归一化接口挂载,传感器设备注册功能 */ -int32_t InitAccelDriver(struct HdfDeviceObject *device) -{ - /* 获取传感器私有数据结构体对象 */ - struct AccelDrvData *drvData = AccelGetDrvData(); - - /* 同类型传感器不同厂家设备探测时,判断此类型传感器是否已经在位,若已经在位,无需再继续探测,直接返回 */ - if (drvData->detectFlag) { - HDF_LOGE("%s: accel sensor have detected", __func__); - return HDF_SUCCESS; - } - - CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM); - /* 分配存放传感器数据配置的私有结构体数据对象,需要在驱动释放时释放分配的资源空间 */ - drvData->accelCfg = (struct SensorCfgData *)OsalMemCalloc(sizeof(*cfg)); - if (drvData->accelCfg == NULL) { - HDF_LOGE("%s: malloc sensor config data failed", __func__); - return HDF_FAILURE; - } - - drvData->accelCfg->regCfgGroup = &g_regCfgGroup[0]; - /* 初始化传感器配置数据主要是解析传感器通讯总线配置类型信息,传感器基本信息,传感器属性信息,传感器是否在位信息,寄存器分组信息 */ - if (GetSensorBaseConfigData(device->property, drvData->accelCfg) != HDF_SUCCESS) { - HDF_LOGE("%s: get sensor base config failed", __func__); - goto Base_CONFIG_EXIT; - } - - if (DetectAccelChip() != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor detect device no exist", __func__); - goto DETECT_CHIP_EXIT; - } - drvData->detectFlag = true; - if (ParseSensorRegConfig(drvData->accelCfg) != HDF_SUCCESS) { - HDF_LOGE("%s: detect sensor device failed", __func__); - goto REG_CONFIG_EXIT; - } - - if (InitAccelAfterConfig() != HDF_SUCCESS) { - HDF_LOGE("%s: init accel after config failed", __func__); - goto INIT_EXIT; - } - - HDF_LOGI("%s: init accel driver success", __func__); - return HDF_SUCCESS; - -INIT_EXIT: - DestroySensorThread(&drvData->thread, &drvData->threadStatus); - (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); -REG_CONFIG_EXIT: - ReleaseSensorAllRegConfig(drvData->accelCfg); - (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); -DETECT_CHIP_EXIT: - drvData->detectFlag = false; -BASE_CONFIG_EXIT: - drvData->accelCfg->root = NULL; - drvData->accelCfg->regCfgGroup = NULL; - OsalMemFree(drvData->accelCfg); - drvData->accelCfg = NULL; - return HDF_FAILURE; -} - -/* 释放驱动初始化时分配的资源 */ -void ReleaseAccelDriver(struct HdfDeviceObject *device) -{ - (void)device; - struct AccelDrvData *drvData = NULL; - - drvData = AccelGetDrvData(); - (void)DestroySensorThread(&drvData->thread, &drvData->threadStatus); - (void)DeleteSensorDevice(SENSOR_TAG_ACCELEROMETER); - drvData->detectFlag = false; - - if (drvData->accelCfg != NULL) { - drvData->accelCfg->root = NULL; - drvData->accelCfg->regCfgGroup = NULL; - ReleaseSensorAllRegConfig(drvData->accelCfg); - (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg); - OsalMemFree(drvData->accelCfg); - drvData->accelCfg = NULL; - } - - drvData->initStatus = false; -} -``` - -1. 加速度计传感器寄存器组配置信息 - -加速度计传感器数据配置只需要按照模板配置即可,基于模板配置的解析功能已经在**InitSensorConfigData**函数完成,只需初始化时调用即可。如果有新增配置项,需要同步修改此函数。 - -``` -加速度传感器数据配置模板(accel_config.hcs) -root { - sensorAccelConfig { - accelChipConfig { - /* 传感器设备信息模板 */ - template sensorInfo { - sensorName = "accelerometer"; /* 加速度计名字,字符最大长度16字节 */ - vendorName = "borsh_bmi160"; /* 传感器设备厂商,字符最大长度16字节 */ - firmwareVersion = "1.0"; /* 传感器固件版本号,默认1.0,字符最大长度16字节 */ - hardwareVersion = "1.0"; /* 传感器硬件版本号,默认1.0,字符最大长度16字节 */ - sensorTypeId = 1; /* 传感器类型编号,详见{@link SensorTypeTag} */ - sensorId = 1; /* 传感器的标识号,有传感器驱动开发者定义,推荐用{@link SensorTypeTag}枚举 */ - maxRange = 8; /* 传感器的最大量程,根据开发者需要配置 */ - precision = 0; /* 传感器的精度,与上报数据配合使用,上报数据结构体{@link SensorEvents } */ - power = 230; /* 传感器的功耗 */ - } - /* 传感器使用的总线类型和配置信息模板 */ - template sensorBusConfig { - busType = 0; /* 0:i2c 1:spi */ - busNum = 6; /* 芯片上分配给传感器的器件号 */ - busAddr = 0; /* 芯片上分配给传感器的地址 */ - regWidth = 1; /* 传感器寄存器地址宽度 */ - regBigEndian = 0; /* 传感器寄存器大小端 */ - } - /* 传感器设备属性模板 */ - template sensorAttr { - chipName = ""; /* 传感器芯片名字 */ - chipIdRegister = 0xf; /* 传感器在位检测寄存器地址 */ - chipIdValue = 0xd1; /* 校验传感器在位检测寄存器值 */ - } - } - } -} - -/* 根据不同器件硬件差异,修改模板配置,不修改的就会默认采用模板配置 */ -root { - sensorAccelConfig { - accel_bmi160_chip_config : accelChipConfig { - match_attr = "hdf_sensor_accel_driver"; /* 需要和加速度传感器设备配置match_attr字段保持一致 */ - accelInfo :: sensorInfo { - vendorName = "borsh_bmi160"; - sensorTypeId = 1; - sensorId = 1; - } - accelBusConfig :: sensorBusConfig { - busType = 0; /* i2c通讯方式 */ - busNum = 6; - busAddr = 0x68; - regWidth = 1; /* 1字节位宽 */ - } - accelAttr :: sensorAttr { - chipName = "bmi160"; - chipIdRegister = 0x00; - chipIdValue = 0xd1; - } - accelRegConfig { - /* regAddr: 寄存器地址 - value: 寄存器值 - mask: 寄存器值的掩码 - len: 寄存器值的数据长度(字节) - delay: 配置寄存器延时(ms) - opsType:操作类型 0-无 1-读 2-写 3-读并检查 4-位更新 - calType: 计算类型 0-无 1-写 2-取反 3-异或 4-左移 5-右移 - shiftNum: 移动位数 - debug: 调试开关,0-调试关闭 1-调试打开 - save: 保存数据开关,0-不保存数据 1-保存数据 - */ - /* 传感器寄存器操作分组,按照分组进行有序配置 */ - /* 寄存器地址, 寄存器值, 寄存器值的掩码, 寄存器值的数据长度, 配置寄存器延时, 操作类型, 计算类型, 移动位数, 调试开关, 保存开关 */ - /* 初始化寄存器组 */ - initSeqConfig = [ - 0x7e, 0xb6, 0xff, 1, 5, 2, 0, 0, 0, 0, - 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 - ]; - /* 使能寄存器组 */ - enableSeqConfig = [ - 0x7e, 0x11, 0xff, 1, 5, 2, 0, 0, 0, 0, - 0x41, 0x03, 0xff, 1, 0, 2, 0, 0, 0, 0, - 0x40, 0x08, 0xff, 1, 0, 2, 0, 0, 0, 0 - ]; - /* 去使能寄存器组 */ - disableSeqConfig = [ - 0x7e, 0x10, 0xff, 1, 5, 2, 0, 0, 0, 0 - ]; - } - } - } -} -``` - -1. 加速度计传感器驱动操作接口实现 - -开发者需要根据每种类型的传感器实现归一化接口。 - -``` -/* 不使用函数暂时置空 */ -static int32_t SetAccelInfo(struct SensorBasicInfo *info) -{ - (void)info; - - return HDF_ERR_NOT_SUPPORT; -} -/* 下发使能寄存器组的配置 */ -static int32_t SetAccelEnable(void) -{ - int32_t ret; - struct AccelDrvData *drvData = AccelGetDrvData(); - - CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); - ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor disable config failed", __func__); - return HDF_FAILURE; - } - - drvData->threadStatus = SENSOR_THREAD_RUNNING; - - return HDF_SUCCESS; -} -/* 下发去使能寄存器组的配置 */ -static int32_t SetAccelDisable(void) -{ - int32_t ret; - struct AccelDrvData *drvData = AccelGetDrvData(); - - CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM); - - ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_DISABLE_GROUP]); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel sensor disable config failed", __func__); - return HDF_FAILURE; - } - - drvData->threadStatus = SENSOR_THREAD_STOPPED; - - return HDF_SUCCESS; -} -/* 配置传感器采样率和数据上报间隔 */ -static int32_t SetAccelBatch(int64_t samplingInterval, int64_t interval) -{ - (void)interval; - - struct AccelDrvData *drvData = AccelGetDrvData(); - drvData->interval = samplingInterval; - - return HDF_SUCCESS; -} -/* 设置传感器工作模式,当前支持实时模式 */ -static int32_t SetAccelMode(int32_t mode) -{ - return (mode == SENSOR_WORK_MODE_REALTIME) ? HDF_SUCCESS : HDF_FAILURE; -} -/* 设置传感器可选配置 */ -static int32_t SetAccelOption(uint32_t option) -{ - (void)option; - return HDF_ERR_NOT_SUPPORT; -} -``` - -- 差异化处理接口 - - ``` - /* 器件探测时,如果探测成功,则注册差异化处理函数到accel驱动模型里 */ - int32_t DetectAccelBim160Chip(struct SensorCfgData *data) - { - int32_t ret; - struct AccelOpsCall ops; - CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); - - if (strcmp(ACCEL_CHIP_NAME_BMI160, data->sensorAttr.chipName) != 0) { - return HDF_SUCCESS; - } - ret = InitAccelPreConfig(); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: init BMI160 bus mux config", __func__); - return HDF_FAILURE; - } - if (DetectSensorDevice(data) != HDF_SUCCESS) { - return HDF_FAILURE; - } - - /* 差异化处理函数 */ - ops.Init = InitBmi160; - ops.ReadData = ReadBmi160Data; - ret = RegisterAccelChipOps(&ops); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: register BMI160 accel failed", __func__); - (void)ReleaseSensorBusHandle(&data->busCfg); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - /* 初始化处理函数 */ - static int32_t InitBmi160(struct SensorCfgData *data) - { - int32_t ret; - - CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); - ret = SetSensorRegCfgArray(&data->busCfg, data->regCfgGroup[SENSOR_INIT_GROUP]); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: bmi160 sensor init config failed", __func__); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - /* 数据处理函数 */ - int32_t ReadBmi160Data(struct SensorCfgData *data) - { - int32_t ret; - struct AccelData rawData = { 0, 0, 0 }; - int32_t tmp[ACCEL_AXIS_NUM]; - struct SensorReportEvent event; - - (void)memset_s(&event, sizeof(event), 0, sizeof(event)); - - ret = ReadBmi160RawData(data, &rawData, &event.timestamp); - if (ret != HDF_SUCCESS) { - return HDF_FAILURE; - } - - event.sensorId = SENSOR_TAG_ACCELEROMETER; - event.option = 0; - event.mode = SENSOR_WORK_MODE_REALTIME; - - rawData.x = rawData.x * BMI160_ACC_SENSITIVITY_2G; - rawData.y = rawData.y * BMI160_ACC_SENSITIVITY_2G; - rawData.z = rawData.z * BMI160_ACC_SENSITIVITY_2G; - - tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; - tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; - tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_1K_UNIT) / SENSOR_CONVERT_UNIT; - - event.dataLen = sizeof(tmp); - event.data = (uint8_t *)&tmp; - ret = ReportSensorEvent(&event); - return ret; - } - ``` - -- 数据处理函数 - -创建传感器定时器,按照配置的采样率定时采样,并上报给数据订阅者。 - -``` -/* 传感器定时工作线程 */ -static int32_t ReadAccelDataThreadWorker(void *arg) -{ - (void)arg; - int64_t interval; - struct AccelDrvData *drvData = AccelGetDrvData(); - - drvData->threadStatus = SENSOR_THREAD_START; - while (true) { - if (drvData->threadStatus == SENSOR_THREAD_RUNNING) { - if (drvData->ops.ReadData != NULL) { - (void)drvData->ops.ReadData(drvData->accelCfg); - } - interval = OsalDivS64(drvData->interval, (SENSOR_CONVERT_UNIT * SENSOR_CONVERT_UNIT)); - OsalMSleep(interval); - } else if (drvData->threadStatus == SENSOR_THREAD_DESTROY) { - break; - } else { - OsalMSleep(ACC_DEFAULT_SAMPLING_200_MS / SENSOR_CONVERT_UNIT / SENSOR_CONVERT_UNIT); - } - - if ((!drvData->initStatus) || (drvData->interval < 0) || drvData->threadStatus != SENSOR_THREAD_RUNNING) { - continue; - } - } - - return HDF_SUCCESS; -} -/* 创建传感器定时器和器件初始化 */ -static int32_t InitAccelConfig(void) -{ - int32_t ret; - struct AccelDrvData *drvData = AccelGetDrvData(); - - if (drvData->threadStatus != SENSOR_THREAD_NONE && drvData->threadStatus != SENSOR_THREAD_DESTROY) { - HDF_LOGE("%s: accel thread have created", __func__); - return HDF_SUCCESS; - } - - ret = CreateSensorThread(&drvData->thread, ReadAccelDataThreadWorker, "hdf_sensor_accel", drvData); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel create thread failed", __func__); - drvData->threadStatus = SENSOR_THREAD_NONE; - return HDF_FAILURE; - } - - CHECK_NULL_PTR_RETURN_VALUE(drvData->ops.Init, HDF_ERR_INVALID_PARAM); - - ret = drvData->ops.Init(drvData->accelCfg); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: accel create thread failed", __func__); - drvData->threadStatus = SENSOR_THREAD_NONE; - return HDF_FAILURE; - } - drvData->initStatus = true; - return HDF_SUCCESS; -} -``` - -- 主要的数据结构 - -``` -/* 传感器转换单位*/ -#define SENSOR_CONVERT_UNIT 1000 -#define SENSOR_1K_UNIT 1024 -/* 传感器2g对应灵敏度转换值 */ -#define BMI160_ACC_SENSITIVITY_2G 61 -/* 传感器数据采样寄存器地址 */ -#define BMI160_ACCEL_X_LSB_ADDR 0X12 -#define BMI160_ACCEL_X_MSB_ADDR 0X13 -#define BMI160_ACCEL_Y_LSB_ADDR 0X14 -#define BMI160_ACCEL_Y_MSB_ADDR 0X15 -#define BMI160_ACCEL_Z_LSB_ADDR 0X16 -#define BMI160_ACCEL_Z_MSB_ADDR 0X17 -/* 传感器数据维度 */ -enum AccelAxisNum { - ACCEL_X_AXIS = 0, - ACCEL_Y_AXIS = 1, - ACCEL_Z_AXIS = 2, - ACCEL_AXIS_NUM = 3, -}; -/* 传感器每个维度值 */ -struct AccelData { - int32_t x; - int32_t y; - int32_t z; -}; -/* 传感器私有数据结构体 */ -struct AccelDrvData { - bool detectFlag; - uint8_t threadStatus; - uint8_t initStatus; - int64_t interval; - struct SensorCfgData *accelCfg; - struct OsalThread thread; - struct AccelOpsCall ops; -}; -/* 差异化适配函数 */ -struct AccelOpsCall { - int32_t (*Init)(struct SensorCfgData *data); - int32_t (*ReadData)(struct SensorCfgData *data); -}; -``` - diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index a544f96506316543a7c9444cc156b80d2f366e7c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,16 +0,0 @@ -# 传感器驱动开发指导 - -- [开发步骤](#section18816105182315) - -Sensor驱动是基于HDF框架、PLATFORM和OSAL基础接口进行开发,不区分操作系统和芯片平台,为不同Sensor器件提供统一的驱动模型。本篇开发指导以加速度计传感器为例,介绍传感器驱动开发。 - -## 开发步骤 - -1. 加速度计传感器驱动注册。HDF驱动框架会提供统一的驱动管理模型,通过加速计传感器模块配置信息,识别并加载对应模块驱动。 -2. 加速度计传感器驱动初始化和去初始化。HDF驱动框架通过init入口函数,依次启动传感器设备驱动加载和分配传感器设备数据配置资源。HDF驱动框架通过release函数,释放驱动加载的资源和配置。 -3. 加速度计传感器寄存器组配置解析。不同类型传感器需要在hcs里配置器件对应的HCS配置文件,然后再设备驱动启动过程中探测器件是否在位,然后加载对应的配置文件,生成配置的结构体对象。 -4. 加速度计传感器驱动操作接口实现。实现各个类型传感器归一化驱动接口,如init,GetInfo,Enable,Disable,SetBatch,SetMode,SetOption,ReadSensorData等函数,完成传感器驱动配置下发和数据上报功能。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->传感器驱动模型已经提供一部分能力集,包括驱动设备管理能力,抽象总线和平台操作接口能力,通用配置操作接口能力,配置解析操作接口能力,接口参考[表2](传感器驱动开发概述.md#table1156812588320)。需要开发人员实现部分有:1、传感器部分操作接口([表3](传感器驱动开发概述.md#table1083014911336));2、传感器HCS差异化数据配置;3、驱动基本功能验证。 - diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index 6319a9086c6c8754c6a8d36cf9abc7827d24e20b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,244 +0,0 @@ -# 传感器驱动开发概述 - -- [简介](#section667413271505) -- [接口说明](#section7255104114110) - -## 简介 - -Sensor(传感器)驱动模块为上层Sensor服务系统提供稳定的Sensor基础能力API,包括Sensor列表查询、Sensor启停、Sensor订阅及去订阅,Sensor参数配置等功能;基于HDF(**H**ardware **D**river **F**oundation)驱动框架开发的Sensor驱动模型,实现跨操作系统迁移,器件差异配置等功能。Sensor驱动模型如下图1所示: - -**图 1** Sensor驱动模型图 -![](figures/Sensor驱动模型图.png "Sensor驱动模型图") - -Sensor驱动模型对外开放的API接口能力如下: - -- 提供Sensor HDI(**H**ardware **D**river **I**nterface)能力接口,简化服务开发。 -- 提供Sensor驱动模型能力接口:依赖HDF驱动框架实现Sensor器件驱动的注册,加载,去注册,器件探测等能力,提供同一类型Sensor器件驱动归一接口, 寄存器配置解析操作接口,总线访问抽象接口,平台抽象接口。 -- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS\(**H**DF **C**onfiguration **S**ource\)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。 - -## 接口说明 - -Sensor驱动模型对HDI开放的API接口功能,参考表1。 - -**表 1** Sensor驱动模型对外API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

功能描述

-

查询操作

-

int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count)

-

获取系统中注册的所有传感器信息,一种类型传感器信息包括传感器名字、设备厂商、固件版本号、硬件版本号、传感器类型编号、传感器标识、最大量程、精度、功耗。

-

配置操作

-

int32_t Enable(int32_t sensorId)

-

使能一种传感器设备,只有数据订阅者使能传感器后,才能获取订阅的传感器数据。

-

int32_t Disable(int32_t sensorId)

-

去使能一种传感器设备。

-

int32_t SetBatch(iint32_t sensorId, int64_t samplingInterval, int64_t reportInterval)

-

设置一种传感器的数据采样间隔和数据上报间隔。

-

int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

-

设置一种传感器的工作模式,不同的工作模式,上报数据方式不同。

-

int32_t SetOption(int32_t sensorId, uint32_t option)

-

设置一种传感器量程,精度等可选配置。

-

数据订阅操作

-

int32_t Register(RecordDataCallback cb)

-

订阅者注册传感器数据回调函数,系统会将获取到的传感器数据上报给订阅者。

-

int32_t Unregister(void)

-

订阅者去注册传感器数据回调函数。

-

接口实例

-

const struct SensorInterface *NewSensorInterfaceInstance(void)

-

创建传感器接口实例。

-

int32_t FreeSensorInterfaceInstance(void)

-

释放传感器接口实例。

-
- -Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无需实现,直接使用,参考表2: - -**表 2** Sensor驱动模型对驱动开发者开放的功能接口列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

功能描述

-

设备管理操作接口

-

int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo)

-

添加当前类型的传感器设备到传感器设备管理。

-

int32_t DeleteSensorDevice(int32_t sensorId)

-

删除传感器设备管理里指定的传感器设备。

-

int32_t ReportSensorEvent(const struct SensorReportEvent *events)

-

上报指定类型传感器的数据到用户侧。

-

Sensor抽象总线和平台操作接口

-

int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen)

-

按照配置的总线方式,读取传感器寄存器配置数据。

-

int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len)

-

按照配置的总线方式,传感器配置数据写入寄存器。

-

int32_t CreateSensorThread(struct OsalThread *thread, OsalThreadEntry threadEntry, char *name, void *entryPara)

-

创建指定传感器的定时线程,用于传感器数据上报处理。

-

void DestroySensorThread(struct OsalThread *thread, uint8_t *status);

-

销毁传感器创建的定时线程。

-

通用配置操作接口

-

int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group);

-

根据传感器总线类型信息,下发寄存器分组配置。

-

配置解析操作接口

-

-

int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config)

-

根据传感器设备HCS资源配置,获取传感器信息,总线配置信息,属性配置等基本配置信息,并初始化对应的基本配置数据结构体。

-

int32_t ParseSensorRegConfig(struct SensorCfgData *config)

-

根据传感器设备HCS资源配置,解析寄存器分组信息,并初始化配置数据结构体。

-

void ReleaseSensorAllRegConfig(struct SensorCfgData *config)

-

释放传感器配置数据结构体里分配的资源。

-

int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg)

-

获取传感器总线句柄信息。

-

int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg)

-

释放传感器句柄信息。

-
- -Sensor驱动模型要求驱动开发者实现的接口功能,参考表3 - -**表 3** Sensor驱动模型要求驱动开发者实现的接口列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

功能描述

-

基本功能操作

-

int32_t init(void)

-

传感器器设备探测成功后,需要对传感器器设备初始化配置。

-

int32_t GetInfo(struct SensorBasicInfo *info)

-

从传感器器设备的HCS配置里,获取当前传感器设备的基本信息。

-

int32_t Enable(void)

-

根据当前传感器器设备的HCS配置,下发传感器设备使能操作组的寄存器配置。

-

int32_t Disable(void)

-

根据当前传感器器设备的HCS配置,下发传感器设备去使能操作组的寄存器配置。

-

int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval)

-

根据数据采样率和数据上报间隔,配置当前传感器设备的数据上报线程处理时间。

-

int32_t SetMode(int32_t mode)

-

配置当前传感器设备数据上报方式。

-

int32_t SetOption(uint32_t option)

-

根据可选配置,下发量程,精度等寄存器配置。

-

void ReadSensorData(void)

-

实现传感器的数据读取函数。

-
- -接口实现参考[SENSOR](传感器驱动开发实例.md)章节。 - diff --git "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" deleted file mode 100755 index 7bf51251601d13df14cc81398af44c826228f2d9..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\344\274\240\346\204\237\345\231\250\351\251\261\345\212\250\346\265\213\350\257\225\346\214\207\345\257\274.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 传感器驱动测试指导 - -驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 - -``` -/* 标识是否上报传感器数据 */ -static int32_t g_sensorDataFlag = 0; -/* 保持获取的传感器接口实例地址 */ -static const struct SensorInterface *g_sensorDev = nullptr; - -/* 订阅者注册数据上报函数 */ -static int SensorTestDataCallback(struct SensorEvents *event) -{ - if (event == nullptr) { - return -1; - } - float *data = (float*)event->data; - printf("time [%lld] sensor id [%d] x-[%f] y-[%f] z-[%f]\n\r", event->timestamp, - event->sensorId, (*data), *(data + 1), *(data + g_axisZ)); - if (*data > 1e-5) { - g_sensorDataFlag = 1; - } - return 0; -} -/* 用例执行前,初始化传感器接口实例 */ -void HdfSensorTest::SetUpTestCase() -{ - g_sensorDev = NewSensorInterfaceInstance(); - if (g_sensorDev == nullptr) { - printf("test sensorHdi get Module instace failed\n\r"); - } -} -/* 用例资源释放 */ -void HdfSensorTest::TearDownTestCase() -{ - if (g_sensorDev != nullptr) { - FreeSensorInterfaceInstance(); - g_sensorDev = nullptr; - } -} -/* 传感器驱动测试验证 */ -HWTEST_F(HdfSensorTest,TestAccelDriver_001, TestSize.Level0) -{ - int32_t sensorInterval = 1000000000; /* 数据采样率单位纳秒 */ - int32_t pollTime = 5; /* 数据采样时间单位秒 */ - int32_t accelSensorId = 1; /* 加速度传感器类型标识为1 */ - int32_t count = 0; - int ret; - struct SensorInformation *sensorInfo = nullptr; - - ret = g_sensorDev->Register(SensorTestDataCallback) - EXPECT_EQ(SENSOR_NULL_PTR, ret); - - ret = g_sensorDev->GetAllSensors(&sensorInfo, &count); - EXPECT_EQ(0, ret); - if (sensorInfo == nullptr) { - EXPECT_NE(nullptr, sensorInfo); - return; - } - /* 打印获取的传感器列表 */ - for (int i = 0; i < count; i++) { - printf("get sensoriId[%d], info name[%s]\n\r", sensorInfo[i]->sensorId, sensorInfo[i]->sensorName); - } - ret = g_sensorDev->Enable(accelSensorId); - EXPECT_EQ(0, ret); - g_sensorDataFlag = 0; - - ret = g_sensorDev->SetBatch(accelSensorId, sensorInterval, pollTime); - EXPECT_EQ(0, ret); - /* 在时间pollTime内,观察输出打印数据 */ - OsalSleep(pollTime); - EXPECT_EQ(1, g_sensorDataFlag); - - ret = g_sensorDev->Disable(accelSensorId); - g_sensorDataFlag = 0; - EXPECT_EQ(0, ret); - - ret = g_sensorDev->Unregister(); - EXPECT_EQ(0, ret); -} -``` - diff --git "a/zh-cn/device-dev/driver/\345\244\226\350\256\276.md" "b/zh-cn/device-dev/driver/\345\244\226\350\256\276.md" deleted file mode 100755 index 26824613db5c020fc05e256f6b6aca62f34cbc47..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\345\244\226\350\256\276.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 外设 - -- **[LCD](LCD.md)** - -- **[TOUCHSCREEN](TOUCHSCREEN.md)** - -- **[SENSOR](SENSOR.md)** - -- **[WLAN](WLAN.md)** - - diff --git "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index b8d64e53b754037b4ec6335e683f32bfbd1b6a34..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,86 +0,0 @@ -# 看门狗使用实例 - -本例程提供看门狗的完整使用流程。 - -在本例程中,我们打开一个看门狗设备,设置超时时间并启动计时: - -- 首先定期喂狗,即按时清除看门狗定时器,确保系统不会因定时器超时而复位。 -- 接着再停止喂狗,观察定时器到期后系统是否发生复位行为。 - -示例如下: - -``` -#include "watchdog_if.h" -#include "hdf_log.h" -#include "osal_irq.h" -#include "osal_time.h" - -#define WATCHDOG_TEST_TIMEOUT 2 -#define WATCHDOG_TEST_FEED_TIME 6 - -static int32_t TestCaseWatchdog(void) -{ - int32_t i; - int32_t ret; - uint32_t timeout; - DevHandle handle = NULL; - - /* 打开0号看门狗设备 */ - handle = WatchdogOpen(0); - if (handle == NULL) { - HDF_LOGE("Open watchdog fail!"); - return -1; - } - - /* 设置超时时间 */ - ret = WatchdogSetTimeout(handle, WATCHDOG_TEST_TIMEOUT); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: set timeout fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - - /* 回读设置的超时时间值 */ - ret = WatchdogGetTimeout(handle, &timeout); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: get timeout fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - HDF_LOGI("%s: read timeout back:%u\n", __func__, timeout); - - /* 启动看门狗,开始计时 */ - ret = WatchdogStart(handle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: satrt fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - - /* 每隔1S喂狗一次 */ - for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { - HDF_LOGE("%s: feeding watchdog %d times... \n", __func__, i); - ret = WatchdogFeed(handle); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: feed dog fail! ret:%d\n", __func__, ret); - WatchdogClose(handle); - return ret; - } - OsalSleep(1); - } - /* 由于喂狗间隔小于超时时间,系统不会发生复位,此日志可以正常打印 */ - HDF_LOGE("%s: no reset ... feeding test OK!!!\n", __func__); - - /* 接下来持续不喂狗,使得看门狗计时器超时 */ - for (i = 0; i < WATCHDOG_TEST_FEED_TIME; i++) { - HDF_LOGE("%s: watiting dog buck %d times... \n", __func__, i); - OsalSleep(1); - } - - /* 当不喂狗时间到达之前设定的超时时间的时候,系统会发生复位,理论上观察不到此日志的打印 */ - HDF_LOGE("%s: dog has't buck!!! \n", __func__, i); - WatchdogClose(handle); - return -1; -} -``` - diff --git "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index b8fd5753d462e8fd80df1f64d6d757d385d3998f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,391 +0,0 @@ -# 看门狗使用指导 - -- [使用流程](#section0719414187) -- [打开看门狗设备](#section198171379261) -- [获取看门狗状态](#section206592910275) -- [设置超时时间](#section19605128182714) -- [获取超时时间](#section11111516208) -- [启动看门狗](#section141174192814) -- [喂狗](#section179101435113910) -- [停止看门狗](#section15282123192816) -- [关闭看门狗设备](#section7857850173411) - -## 使用流程 - -使用看门狗的一般流程如[图1](#fig19134125410189)所示。 - -**图 1** 看门狗使用流程图 - - -![](figures/zh-cn_image_0000001057622716.png) - -## 打开看门狗设备 - -在操作看门狗之前,需要使用WatchdogOpen打开一个看门狗设备,一个系统可能有多个看门狗,通过ID号来打开指定的看门狗设备: - -int32\_t WatchdogOpen\(int16\_t wdtId\); - -**表 1** WatchdogOpen参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

wdtId

-

看门狗设备号

-

返回值

-

返回值描述

-

NULL

-

打开失败

-

DevHandle类型指针

-

看门狗设备句柄

-
- -``` -DevHandle handle = NULL; -handle = WatchdogOpen(0); /* 打开0号看门狗设备 */ -if (handle == NULL) { - HDF_LOGE("WatchdogOpen: failed, ret %d\n", ret); - return; -} -``` - -## 获取看门狗状态 - -int32\_t WatchdogGetStatus\(DevHandle handle, int32\_t \*status\); - -**表 2** WatchdogGetStatus参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-

status

-

获取到的启动状态指针

-

返回值

-

返回值描述

-

0

-

获取成功

-

负数

-

获取失败

-
- -``` -int32_t ret; -int32_t status; -/* 获取Watchdog启动状态 */ -ret = WatchdogGetStatus(handle, &status); -if (ret != 0) { - HDF_LOGE("WatchdogGetStatus: failed, ret %d\n", ret); - return; -} -``` - -## 设置超时时间 - -int32\_t WatchdogSetTimeout\(PalHandle \*handle, uint32\_t seconds\); - -**表 3** WatchdogSetTimeout参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-

seconds

-

超时时间,单位为秒

-

返回值

-

返回值描述

-

0

-

设置成功

-

负数

-

设置失败

-
- -``` -int32_t ret; -uint32_t timeOut = 60; -/* 设置超时时间,单位:秒 */ -ret = WatchdogSetTimeout(handle, timeOut); -if (ret != 0) { - HDF_LOGE("WatchdogSetTimeout: failed, ret %d\n", ret); - return; -} -``` - -## 获取超时时间 - -int32\_t WatchdogGetTimeout\(PalHandle \*handle, uint32\_t \*seconds\); - -**表 4** WatchdogGetTimeout参数和返回值描述 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-

seconds

-

接收超时时间的指针,单位为秒

-

返回值

-

返回值描述

-

0

-

获取成功

-

负数

-

获取失败

-
- -``` -int32_t ret; -uint32_t timeOut; -/* 获取超时时间,单位:秒 */ -ret = WatchdogGetTimeout(handle, &timeOut); -if (ret != 0) { - HDF_LOGE("WatchdogGetTimeout: failed, ret %d\n", ret); - return; -} -``` - -## 启动看门狗 - -int32\_t WatchdogStart\(DevHandle handle\); - -**表 5** WatchdogStart参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-

返回值

-

返回值描述

-

0

-

启动成功

-

负数

-

启动失败

-
- -``` -int32_t ret; -/* 启动看门狗 */ -ret = WatchdogStart(handle); -if (ret != 0) { - HDF_LOGE("WatchdogStart: failed, ret %d\n", ret); - return; -} -``` - -## 喂狗 - -int32\_t WatchdogFeed\(DevHandle handle\); - -**表 6** WatchdogFeed参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-

返回值

-

返回值描述

-

0

-

喂狗成功

-

负数

-

喂狗失败

-
- -``` -int32_t ret; -/* 喂狗 */ -ret = WatchdogFeed(handle); -if (ret != 0) { - HDF_LOGE("WatchdogFeed: failed, ret %d\n", ret); - return; -} -``` - -## 停止看门狗 - -int32\_t WatchdogStop\(DevHandle handle\); - -**表 7** WatchdogStop参数和返回值描述 - - - - - - - - - - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-

返回值

-

返回值描述

-

0

-

停止成功

-

负数

-

停止失败

-
- -``` -int32_t ret; -/* 停止看门狗 */ -ret = WatchdogStop(handle); -if (ret != 0) { - HDF_LOGE("WatchdogStop: failed, ret %d\n", ret); - return; -} - -``` - -## 关闭看门狗设备 - -当操作完毕时,使用WatchdogClose关闭打开的设备句柄: - -void WatchdogClose\(DevHandle handle\); - -**表 8** WatchdogClose参数和返回值描述 - - - - - - - - - - -

参数

-

参数描述

-

handle

-

看门狗设备句柄

-
- -``` -/* 关闭看门狗 */ -ret = WatchdogClose(handle); -``` - diff --git "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" "b/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" deleted file mode 100755 index 467e21ba08ef672247327cd100b8c2db7e4f9a01..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\347\234\213\351\227\250\347\213\227\346\246\202\350\277\260.md" +++ /dev/null @@ -1,78 +0,0 @@ -# 看门狗概述 - -- [简介](#section3579126111816) -- [接口说明](#section17429111981812) - -## 简介 - -看门狗(watchdog),又叫看门狗计时器(watchdog timer),是一种硬件的计时设备,当系统的主程序发生某些错误时,导致未及时清除看门狗计时器的计时值,这时看门狗计时器就会对系统发出复位信号,使系统从悬停状态恢复到正常运作状态。 - -## 接口说明 - -**表 1** 看门狗 API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

打开/关闭看门狗

-

WatchdogOpen

-

打开看门狗设备

-

WatchdogClose

-

关闭看门狗设备

-

启动/停止看门狗

-

WatchdogStart

-

启动看门狗

-

WatchdogStop

-

停止看门狗

-

设置/获取超时时间

-

WatchdogSetTimeout

-

设置看门狗超时时间

-

WatchdogGetTimeout

-

获取看门狗超时时间

-

获取看门狗状态

-

WatchdogGetStatus

-

获取看门狗状态

-

清除看门狗定时器

-

WatchdogFeed

-

清除看门狗定时器(喂狗)

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->本文涉及看门狗的所有接口,仅限内核态使用,不支持在用户态使用。 - diff --git "a/zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" "b/zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" deleted file mode 100755 index 3fd2a0701a9c5e9f734021d7520e773f8c5e136e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\351\205\215\347\275\256\347\256\241\347\220\206.md" +++ /dev/null @@ -1,437 +0,0 @@ -# 配置管理 - -- [配置概述](#section59914284576) -- [配置语法](#section533713333580) -- [关键字](#section1316625413586) -- [基本结构](#section173481622115918) -- [数据类型](#section96521601302) -- [预处理](#section8164295515) -- [注释](#section0338205819610) -- [引用修改](#section179799204716) -- [节点复制](#section382424014712) -- [删除](#section165211112586) -- [属性引用](#section192841514490) -- [模板](#section520134294) -- [配置生成](#section106152531919) -- [hc-gen介绍](#section8260625101012) - -## 配置概述 - -HCS\(**H**DF **C**onfiguration **S**ource\)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。 - -HC-GEN**\(H**DF **C**onfiguration **G**enerator**\)**是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式: - -- 在弱性能环境中,转换为配置树源码,驱动可直接调用C代码获取配置。 -- 在高性能环境中,转换为HCB\(**H**DF **C**onfiguration **B**inary\)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。 - -以下是使用HCB模式的典型应用场景: - -**图 1** 配置使用流程图 - - -![](figures/zh-cn_image_0000001053405727.png) - -HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。 - -## 配置语法 - -HCS的语法介绍如下: - -## 关键字 - -HCS配置语法保留了以下关键字。 - -**表 1** HCS配置语法保留关键字 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

关键字

-

用途

-

说明

-

root

-

配置根节点

-

-

-

include

-

引用其他HCS配置文件

-

-

-

delete

-

删除节点或属性

-

只能用于操作include导入的配置树

-

template

-

定义模板节点

-

-

-

match_attr

-

用于标记节点的匹配查找属性

-

解析配置时可以使用该属性的值查找到对应节点

-
- -## 基本结构 - -HCS主要分为属性\(Attribute\)和节点\(Node\)两种结构。 - -**属性** - -属性即最小的配置单元,是一个独立的配置项。语法如下: - -``` - attribute_name = value; -``` - -- attribute\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 - -- value的可用格式如下: - - - 数字常量,支持二进制、八进制、十进制、十六进制数,具体参考数据类型节。 - - - 字符串,内容使用双引号\(""\)引用。 - - - 节点引用。 - - -- attribute 必须以分号\(;\)结束且必须属于一个node。 - - -**节点** - -节点是一组属性的集合,语法如下: - -``` - node_name { - module = "sample"; - ... - } -``` - -- node\_name 是**字母、数字、下划线**的组合且必须以字母或下划线开头,字母区分大小写。 - -- 大括号后无需添加结束符“;”。 - -- root为保留关键字,用于声明配置表的根节点。每个配置表必须以root节点开始。 - -- root节点中必须包含module属性,其值应该为一个字符串,用于表征该配置所属模块。 - -- 节点中可以增加match\_attr属性,其值为一个全局唯一的字符串。在解析配置时可以调用查找接口以该属性的值查找到包含该属性的节点。 - -## 数据类型 - -在属性定义中使用自动数据类型,不显式指定类型,属性支持的数据类型如下: - -**整型** - -整型长度自动推断,根据实际数据长度给与最小空间占用的类型。 - -- 二进制,0b前缀,示例:0b1010。 - -- 八进制,0前缀,示例:0664。 -- 十进制 ,无前缀,且支持有符号与无符号,示例:1024,+1024均合法。负值在读取时注意使用有符号数读取接口。 - -- 十六进制,0x前缀,示例:0xff00、0xFF。 - - -**字符串** - -字符串使用双引号\(""\)表示。 - -**数组** - -数组元素支持整型、字符串,不支持混合类型。整型数组中uint32\_t uint64\_t混用会向上转型为uint64\_t 数组。整型数组与字符串数组示例如下: - -``` -attr_foo = [0x01, 0x02, 0x03, 0x04]; -attr_bar = ["hello", "world"]; -``` - -**bool类型** - -bool类型中**true**表示真,**false**表示假。 - -## 预处理 - -**include** - -用于导入其他HCS文件。语法示例如下: - -``` -#include "foo.hcs" -#include "../bar.hcs" -``` - -- 文件名必须使用双引号\(""\),不在同一目录使用相对路径引用。被include文件也必须是合法的HCS文件。 -- 多个include,如果存在相同的节点,后者覆盖前者,其余的节点依次展开。 - -## 注释 - -支持两种注释风格。 - -- 单行注释。 - - ``` - // comment - ``` - -- 多行注释。 - - ``` - /* - comment - */ - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >多行注释不支持嵌套。 - - -## 引用修改 - -引用修改可以实现修改另外任意一个节点的内容,语法为: - -``` - node :& source_node -``` - -上述语句表示node中的内容是对source\_node节点内容的修改。示例如下: - -``` -root { - module = "sample"; - foo { - foo_ :& root.bar{ - attr = "foo"; - } - foo1 :& foo2 { - attr = 0x2; - } - foo2 { - attr = 0x1; - } - } - - bar { - attr = "bar"; - } -} -``` - -最终生成配置树为: - -``` -root { - module = "sample"; - foo { - foo2 { - attr = 0x2; - } - } - bar { - attr = "foo"; - } -} -``` - -在以上示例中,可以看到foo.foo\_节点通过引用将bar.attr属性的值修改为了"foo",foo.foo1节点通过引用将foo.foo2.attr属性的值修改为了0x2。foo.foo\_以及foo.foo1节点表示对目标节点内容的修改,其自身并不会存在最终生成的配置树中。 - -- 引用同级node,可以直接使用node名称,否则被引用的节点必须使用绝对路径,节点间使用“.”分隔,root表示根节点,格式为root开始的节点路径序列,例如root.foo.bar即为一个合法的绝对路径。 -- 如果出现修改冲突(即多处修改同一个属性),编译器将提示warning,因为这种情况下只会生效某一个修改而导致最终结果不确定。 - -## 节点复制 - -节点复制可以实现在节点定义时从另一个节点先复制内容,用于定义内容相似的节点。语法为: - -``` - node : source_node -``` - -上述语句表示在定义"node"节点时将另一个节点"source\_node"的属性复制过来。示例如下: - -``` -root { - module = "sample"; - foo { - attr_0 = 0x0; - } - bar:foo { - attr_1 = 0x1; - } -} -``` - -上述代码的最终生成配置树为: - -``` -root { - module = "sample"; - foo { - attr_0 = 0x0; - } - bar { - attr_1 = 0x1; - attr_0 = 0x0; - } -} -``` - -在上述示例中,编译后bar节点即包含attr\_0属性也包含attr\_1属性,在bar中对attr\_0的修改不会影响到foo。 - -在foo和bar在同级node中可不指定foo的路径,否则需要使用绝对路径引用,参考[引用修改](#section179799204716)。 - -## 删除 - -要对include导入的base配置树中不需要的节点或属性进行删除,可以使用delete关键字。下面的举例中sample1.hcs通过include导入了sample2.hcs中的配置内容,并使用delete删除了sample2.hcs中的attribute2属性和foo\_2节点,示例如下: - -``` -// sample2.hcs -root { - attr_1 = 0x1; - attr_2 = 0x2; - foo_2 { - t = 0x1; - } -} - -// sample1.hcs -#include "sample2.hcs" -root { - attr_2 = delete; - foo_2 : delete { - } -} -``` - -上述代码在生成过程中将会删除root.foo\_2节点与attr\_2,最终生成配置树为: - -``` -root { - attr_1 = 0x1; -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->在同一个HCS文件中不允许使用delete,建议直接删除不需要的属性。 - -## 属性引用 - -为了在解析配置时快速定位到关联的节点,可以把节点作为属性的右值,通过读取属性查找到对应节点。语法为: - -``` - attribute = &node; -``` - -上述语句表示attribute的值是一个节点node的引用,在解析时可以用这个attribute快速定位到node,便于关联和查询其他node。示例如下: - -``` -node1 { - attributes; -} - -node2 { - attr_1 = &node1; -} -``` - -## 模板 - -模板的用途在于生成严格一致的node结构,以便对同类型node进行遍历和管理。 - -使用template关键字定义模板node,子node通过双冒号“::”声明继承关系。子节点可以改写但不能新增和删除template中的属性,子节点中没有定义的属性将使用template中的定义作为默认值。示例如下: - -``` -root { - module = "sample"; - template foo { - attr_1 = 0x1; - attr_2 = 0x2; - } - - bar :: foo { - } - - bar_1 :: foo { - attr_1 = 0x2; - } -} -``` - -生成配置树如下: - -``` -root { - module = "sample"; - bar { - attr_1 = 0x1; - attr_2 = 0x2; - } - bar_1 { - attr_1 = 0x2; - attr_2 = 0x2; - } -} -``` - -在上述示例中,bar和bar\_1节点继承了foo节点,生成配置树节点结构与foo保持了完全一致,只是属性的值不同。 - -## 配置生成 - -hc-gen是配置生成的工具,可以对HCS配置语法进行检查并把HCS源文件转化成HCB二进制文件。 - -## hc-gen介绍 - -hc-gen参数说明: - -``` -Usage: hc-gen [Options] [File] -options: - -o output file name, default same as input - -a hcb align with four bytes - -b output binary output, default enable - -t output config in C language source file style - -i output binary hex dump in C language source file style - -p prefix of generated symbol name - -d decompile hcb to hcs - -V show verbose info - -v show version - -h show this help message -``` - -生成.c/.h 配置文件方法: - -``` -hc-gen -o [OutputCFileName] -t [SourceHcsFileName] -``` - -生成HCB 配置文件方法: - -``` -hc-gen -o [OutputHcbFileName] -b [SourceHcsFileName] -``` - -反编译HCB文件为HCS方法: - -``` -hc-gen -o [OutputHcsFileName] -d [SourceHcbFileName] -``` - diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" "b/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" deleted file mode 100755 index 7d5a5437f750b6c60b8b249c40c5ae1c6ab0d30b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\271\263\345\217\260.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 驱动平台 - -- **[GPIO](GPIO.md)** - -- **[I2C](I2C.md)** - -- **[RTC](RTC.md)** - -- **[SDIO](SDIO.md)** - -- **[SPI](SPI.md)** - -- **[UART](UART.md)** - -- **[WATCHDOG](WATCHDOG.md)** - -- **[MIPI DSI](MIPI-DSI.md)** - - diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" "b/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" deleted file mode 100755 index e35139db59ca7df253ee0134e5afb379d596e300..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\345\274\200\345\217\221.md" +++ /dev/null @@ -1,175 +0,0 @@ -# 驱动开发 - -- [驱动模型介绍](#section157425168112) -- [驱动开发步骤](#section1969312275533) - -## 驱动模型介绍 - -HDF框架以组件化的驱动模型作为核心设计思路,为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF框架将一类设备驱动放在同一个host里面,开发者也可以将驱动功能分层独立开发和部署,支持一个驱动多个node,HDF框架管理驱动模型如下图所示: - -**图 1** HDF框架管理驱动模型 - - -![](figures/zh-cn_image_0000001054564784.png) - -## 驱动开发步骤 - -基于HDF框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示: - -1. 驱动实现 - - 驱动实现包含驱动业务代码和驱动入口注册,具体写法如下: - - - 驱动业务代码 - - ``` - #include "hdf_device_desc.h" // HDF框架对驱动开放相关能力接口的头文件 - #include "hdf_log.h" // HDF 框架提供的日志接口头文件 - - #define HDF_LOG_TAG "sample_driver" // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签 - - //驱动对外提供的服务能力,将相关的服务接口绑定到HDF框架 - int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject) - { - HDF_LOGD("Sample driver bind success"); - return 0; - } - - // 驱动自身业务初始的接口 - int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject) - { - HDF_LOGD("Sample driver Init success"); - return 0; - } - - // 驱动资源释放的接口 - void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject) - { - HDF_LOGD("Sample driver release success"); - return; - } - ``` - - - 驱动入口注册到HDF框架 - - ``` - // 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 - struct HdfDriverEntry g_sampleDriverEntry = { - .moduleVersion = 1, - .moduleName = "sample_driver", - .Bind = HdfSampleDriverBind, - .Init = HdfSampleDriverInit, - .Release = HdfSampleDriverRelease, - }; - - // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - HDF_INIT(g_sampleDriverEntry); - ``` - - -2. 驱动编译 - - 驱动代码的编译必须要使用HDF框架提供的Makefile模板进行编译。 - - ``` - include $(LITEOSTOPDIR)/../../drivers/adapter/lite/khdf/lite.mk #导入hdf预定义内容,必需 - MODULE_NAME := #生成的结果文件 - LOCAL_INCLUDE := #本驱动的头文件目录 - LOCAL_SRCS := #本驱动的源代码文件 - LOCAL_CFLAGS := #自定义的编译选项 - include $(HDF_DRIVER) #导入模板makefile完成编译 - ``` - - - 编译结果文件链接到内核镜像,添加到vendor目录下的hdf\_vendor.mk里面,示例如下: - - ``` - LITEOS_BASELIB += -lxxx #链接生成的静态库 - LIB_SUBDIRS += #驱动代码Makefile的目录 - ``` - - -3. 驱动配置 - - HDF使用HCS作为配置描述源码,HCS详细介绍参考[配置管理](配置管理.md)介绍。 - - 驱动配置包含两部分,HDF框架定义的驱动设备描述和驱动的私有配置信息,具体写法如下: - - - 驱动设备描述(必选) - - HDF框架加载驱动所需要的信息来源于HDF框架定义的驱动设备描述,因此基于HDF框架开发的驱动必须要在HDF框架定义的device\_info.hcs配置文件中添加对应的设备描述,驱动的设备描述填写如下所示: - - ``` - root { - device_info { - match_attr = "hdf_manager"; - template host { // host模板,继承该模板的节点(如下sample_host)如果使用模板中的默认值,则节点字段可以缺省 - hostName = ""; - priority = 100; - template device { - template deviceNode { - policy = 0; - priority = 100; - preload = 0; - permission = 0664; - moduleName = ""; - serviceName = ""; - deviceMatchAttr = ""; - } - } - } - sample_host :: host{ - hostName = "host0"; // host名称,host节点是用来存放某一类驱动的容器 - priority = 100; // host启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证host的加载顺序 - device_sample :: device { // sample设备节点 - device0 :: deviceNode { // sample驱动的DeviceNode节点 - policy = 1; // policy字段是驱动服务发布的策略,在驱动服务管理章节有详细介绍 - priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议默认配100,优先级相同则不保证device的加载顺序 - preload = 0; // 驱动按需加载字段,在本章节最后的说明有详细介绍 - permission = 0664; // 驱动创建设备节点权限 - moduleName = "sample_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "sample_service"; // 驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 - } - } - } - } - } - ``` - - - 驱动私有配置信息(可选) - - 如果驱动有私有配置,则可以添加一个驱动的配置文件,用来填写一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](#li35182436435))传递给驱动,驱动的配置信息示例如下: - - ``` - root { - SampleDriverConfig { - sample_version = 1; - sample_bus = "I2C_0"; - match_attr = "sample_config"; //该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 - } - } - ``` - - 配置信息定义之后,需要将该配置文件添加到板级配置入口文件hdf.hcs(这一块可以通过OpenHarmony驱动子系统在DevEco集成驱动开发套件工具一键式配置,具体使用方法参考驱动开发套件中的介绍),示例如下: - - ``` - #include "device_info/device_info.hcs" - #include "sample/sample_config.hcs" - ``` - - - ->![](public_sys-resources/icon-note.gif) **说明:** ->驱动加载方式支持按需加载和按序加载两种方式,具体使用方法如下: ->- 按需加载 -> ``` -> typedef enum { -> DEVICE_PRELOAD_ENABLE = 0, -> DEVICE_PRELOAD_ENABLE_STEP2, -> DEVICE_PRELOAD_DISABLE, -> DEVICE_PRELOAD_INVALID -> } DevicePreload; -> ``` -> 配置文件中preload 字段配成 0 (DEVICE\_PRELOAD\_ENABLE ),则系统启动过程中默认加载;配成1(DEVICE\_PRELOAD\_ENABLE\_STEP2),当系统支持快启的时候,则在系统系统完成之后再加载这一类驱动,否则和DEVICE\_PRELOAD\_ENABLE 含义相同;配成2(DEVICE\_PRELOAD\_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务(参考[消息机制](驱动消息机制管理.md))时,如果驱动服务不存在时,HDF框架会尝试动态加载该驱动。 ->- 按序加载(需要驱动为默认加载) -> 配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。 - diff --git "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" "b/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" deleted file mode 100755 index ac271c2f1e520c0d8d1c31cf4ab5ab79ef498727..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/driver/\351\251\261\345\212\250\346\266\210\346\201\257\346\234\272\345\210\266\347\256\241\347\220\206.md" +++ /dev/null @@ -1,193 +0,0 @@ -# 驱动消息机制管理 - -- [使用场景](#section33014541954) -- [接口说明](#section538852311616) -- [开发步骤](#section946912121153) - -## 使用场景 - -当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。 - -## 接口说明 - -消息机制的功能主要有以下两种: - -1. 用户态应用发送消息到驱动。 -2. 用户态应用接收驱动主动上报事件。 - -**表 1** 消息机制接口 - - - - - - - - - - - - - - - - - - - -

方法

-

描述

-

struct HdfIoService *HdfIoServiceBind(const char *serviceName)

-

用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。

-

void HdfIoServiceRecycle(struct HdfIoService *service);

-

释放驱动服务。

-

int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener);

-

用户态程序注册接收驱动上报事件的操作方法。

-

int HdfDeviceSendEvent(struct HdfDeviceObject *deviceObject, uint32_t id, struct HdfSBuf *data);

-

驱动主动上报事件接口。

-
- -## 开发步骤 - -1. 将驱动配置信息中服务策略policy字段设置为2(SERVICE\_POLICY\_CAPACITY,参考[policy定义](驱动服务管理.md))。 - - ``` - device_sample :: Device { - policy = 2; - ... - } - ``` - -2. 配置驱动信息中的服务设备节点权限(permission字段)是框架给驱动创建设备节点的权限,默认是0666,驱动开发者根据驱动的实际使用场景配置驱动设备节点的权限。 -3. 在服务实现过程中,实现服务基类成员IDeviceIoService中的Dispatch方法。 - - ``` - // Dispatch是用来处理用户态发下来的消息 - int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) - { - HDF_LOGE("sample driver lite A dispatch"); - return 0; - } - int32_t SampleDriverBind(struct HdfDeviceObject *device) - { - HDF_LOGE("test for lite os sample driver A Open!"); - if (device == NULL) { - HDF_LOGE("test for lite os sample driver A Open failed!"); - return -1; - } - static struct ISampleDriverService sampleDriverA = { - .ioService.Dispatch = SampleDriverDispatch, - .ServiceA = SampleDriverServiceA, - .ServiceB = SampleDriverServiceB, - }; - device->service = (struct IDeviceIoService *)(&sampleDriverA); - return 0; - } - ``` - -4. 驱动定义消息处理函数中的cmd类型。 - - ``` - #define SAMPLE_WRITE_READ 1 // 读写操作码1 - ``` - -5. 用户态获取服务接口并发送消息到驱动。 - - ``` - int SendMsg(const char *testMsg) - { - if (testMsg == NULL) { - HDF_LOGE("test msg is null"); - return -1; - } - struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); - if (serv == NULL) { - HDF_LOGE("fail to get service"); - return -1; - } - struct HdfSBuf *data = HdfSBufObtainDefaultSize(); - if (data == NULL) { - HDF_LOGE("fail to obtain sbuf data"); - return -1; - } - struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); - if (reply == NULL) { - HDF_LOGE("fail to obtain sbuf reply"); - ret = HDF_DEV_ERR_NO_MEMORY; - goto out; - } - if (!HdfSbufWriteString(data, testMsg)) { - HDF_LOGE("fail to write sbuf"); - ret = HDF_FAILURE; - goto out; - } - int ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); - if (ret != HDF_SUCCESS) { - HDF_LOGE("fail to send service call"); - goto out; - } - out: - HdfSBufRecycle(data); - HdfSBufRecycle(reply); - HdfIoServiceRecycle(serv); - return ret; - } - ``` - -6. 用户态接收该驱动上报的消息。 - 1. 用户态编写驱动上报消息的处理函数。 - - ``` - static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data) - { - OsalTimespec time; - OsalGetTime(&time); - HDF_LOGE("%s received event at %llu.%llu", (char *)priv, time.sec, time.usec); - - const char *string = HdfSbufReadString(data); - if (string == NULL) { - HDF_LOGE("fail to read string in event data"); - return -1; - } - HDF_LOGE("%s: dev event received: %d %s", (char *)priv, id, string); - return 0; - } - ``` - - 2. 用户态注册接收驱动上报消息的操作方法。 - - ``` - int RegisterListen() - { - struct HdfIoService *serv = HdfIoServiceBind("sample_driver"); - if (serv == NULL) { - HDF_LOGE("fail to get service"); - return -1; - } - static struct HdfDevEventlistener listener = { - .callBack = OnDevEventReceived, - .priv ="Service0" - }; - if (HdfDeviceRegisterEventListener(serv, &listener) != 0) { - HDF_LOGE("fail to register event listener"); - return -1; - } - ...... - HdfDeviceUnregisterEventListener(serv, &listener); - HdfIoServiceRecycle(serv); - return 0; - } - ``` - - 3. 驱动上报事件。 - - ``` - int32_t SampleDriverDispatch(struct HdfDeviceObject *device, int cmdCode, struct HdfSBuf *data, struct HdfSBuf *reply) - { - ... // process api call here - return HdfDeviceSendEvent(deviceObject, cmdCode, data); - } - ``` - - - diff --git "a/zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" "b/zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" deleted file mode 100644 index c15f1861f152e8616fc86c629472fdef6a0df991..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/get-code/Docker\347\274\226\350\257\221\347\216\257\345\242\203.md" +++ /dev/null @@ -1,313 +0,0 @@ -# Docker编译环境 - -- [Docker环境介绍](#section107932281315) -- [环境准备](#section7337134183512) -- [独立Docker环境](#section2858536103611) - - [搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section319412277287) - - [编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section631485163615) - - [搭建Docker环境-标准系统类设备(参考内存≥128MB)](#section13585262391) - - [编译源码-标准系统类设备(参考内存≥128MB)](#section193711513406) - -- [基于HPM的Docker环境](#section485713518337) - - [搭建Docker环境](#section3295842510) - - [获取及编译源码](#section69141039143518) - - -## Docker环境介绍 - -OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下: - -- 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。 -- 基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。 - -**表 1** Docker镜像介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Docker环境

-

系统类型

-

运行平台

-

Docker镜像仓库

-

标签

-

独立 Docker环境

-

轻量和小型系统

-

Ubuntu/Windows

-

swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

-

0.0.5

-

标准系统

-

Ubuntu

-

swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard

-

0.0.1

-

HPM Docker环境

-

轻量和小型系统

-

Ubuntu/Windows

-

swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

-

0.0.3

-
- -## 环境准备 - -在使用docker环境前需要先完成以下操作: - -1. 安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/)。 -2. 获取OpenHarmony源码,请参考[获取源码](源码获取.md)。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >HPM Docker环境无需单独获取源码。 - - -## 独立Docker环境 - -OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud.com/swr/?region=cn-south-1#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage)上。开发者可以通过该镜像在很大程度上简化编译前的环境配置。下文将介绍具体使用步骤。 - -### 搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) - -**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** - -1. 获取Docker镜像。 - - ``` - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - -2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ubuntu下执行: - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - windows下执行(假设源码目录为D:\\OpenHarmony): - - ``` - docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - -**方式二:通过Dockerfile 构建本地Docker镜像进行构建** - -1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 - - ``` - git clone https://gitee.com/openharmony/docs.git - ``` - -2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 - - ``` - cd docs/docker - ./build.sh - ``` - -3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ubuntu下执行: - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - windows下执行(假设源码目录为D:\\OpenHarmony): - - ``` - docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 - ``` - - -### 编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) - -通过如下编译脚本启动轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)的编译。下文以Hi3516平台为例说明具体编译步骤。 - -设置编译路径,选择当前路径。 - -``` -hb set - . -``` - -**图 1** 设置编译界面 - - -![](figures/zh-cn_image_0000001101413884.png) - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前开发板平台和编译界面的对应关系如下: ->- Hi3861:wifiiot\_hispark\_pegasus@hisilicon ->- Hi3516:ipcamera\_hispark\_taurus@hisilicon ->- Hi3518:ipcamera\_hispark\_aries@hisilicon - -1. 选择ipcamera\_hispark\_taurus@hisilicon并回车。 -2. 执行编译。 - - ``` - hb build -f - ``` - -3. 查看编译结果。 - - 编译结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 - - -### 搭建Docker环境-标准系统类设备(参考内存≥128MB) - -**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** - -1. 获取Docker镜像。 - - ``` - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - -2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - - -**方式二:通过Dockerfile 构建本地Docker镜像进行构建** - -1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 - - ``` - git clone https://gitee.com/openharmony/docs.git - ``` - -2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 - - ``` - cd docs/docker/standard - ./build.sh - ``` - -3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 - ``` - - -### 编译源码-标准系统类设备(参考内存≥128MB) - -1. 在源码的根目录执行预处理脚本。 - - ``` - ../scripts/prepare.sh - ``` - -2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - - ->![](public_sys-resources/icon-note.gif) **说明:** ->退出Docker执行exit命令即可。 - -## 基于HPM的Docker环境 - -docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件,能够帮助用户快速初始化HPM工程,利用docker镜像来快速编译OpenHarmony发行版,在很大程度上简化了编译前的环境配置。开发者在配置好Ubuntu和[hpm-cli](https://device.harmonyos.com/cn/docs/develop/bundles/oem_bundle_guide_prepare-0000001050129846)开发环境后,可以通过以下步骤来使用我们提供的Docker环境。 - -### 搭建Docker环境 - -1. 初始化安装模板。在任意工作目录中执行以下命令。 - - ``` - hpm init -t @ohos/docker_dist - ``` - -2. 修改publishAs。 - - 因为获取到的是模板类型的包,要把包的类型改为需要的类型。 在当前目录下打开bundle.json文件,把"publishAs"字段的值由"template"改为"distribution"。 - - -### 获取及编译源码 - -执行编译。自动安装docker只能在Ubuntu环境下执行,如果其他环境,需要用户自行安装docker,然后拉取镜像,执行编译。 - -- **自动安装docker(Ubuntu环境)** - - 以下命令可以帮助用户自动安装docker, 拉取镜像,并且在容器中开始运行对应解决方案的拉取和编译。 - - **方式一:** - - 命令后接参数指定解决方案,格式如下: - - ``` - hpm run docker solution={product} - ``` - - \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 - - **方式二:** - - 设置环境变量来选择解决方案,再执行编译命令。 - - 1. 选择解决方案。 - - ``` - export solution={product} - ``` - - \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 - - 2. 获取源码及执行编译。 - - ``` - hpm run docker - ``` - - - 以上两种方式以@ohos/hispark\_taurus为例,执行成功结果如下: - - ``` - ...... - ohos ipcamera_hispark_taurus build success! - @ohos/hispark_taurus: distribution building completed. - ``` - - -- **自行安装docker(非Ubuntu环境)** - - 自行安装docker相关操作如下: - - ``` - # 拉取镜像 - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译 - hpm run distWithDocker solution={product} - # windows下的编译,需要配置gitbash - hpm config set shellPath "gitbash路径" - hpm run distWithDocker solution={product} - ``` - - diff --git a/zh-cn/device-dev/get-code/IDE.md b/zh-cn/device-dev/get-code/IDE.md deleted file mode 100644 index 144b67418be2f44e4a5854bdb799be24b4142b7a..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/get-code/IDE.md +++ /dev/null @@ -1,17 +0,0 @@ -# IDE - -- [获取设备开发工具(HUAWEI DevEco Device Tool)](#section2452141120244) -- [获取应用开发工具(HUAWEI DevEco Studio)](#section0904101019258) - -## 获取设备开发工具(HUAWEI DevEco Device Tool) - -HUAWEI DevEco Device Tool是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录、调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。具体可参见[获取工具](https://device.harmonyos.com/cn/ide)和[工具使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905)**。** - -Huawei DevEco Device Tool支持 OpenHarmony设备开发的演进路标如下: - -![](figures/3.png) - -## 获取应用开发工具(HUAWEI DevEco Studio) - -HUAWEI DevEco Studio(以下简称DevEco Studio)是面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的OpenHarmony应用开发服务。通过使用DevEco Studio,开发者可以更高效的开发具备OpenHarmony分布式能力的应用,进而提升创新效率。具体可参见[获取工具](https://developer.harmonyos.com/cn/develop/deveco-studio)和[工具使用指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)。 - diff --git a/zh-cn/device-dev/get-code/Readme-CN.md b/zh-cn/device-dev/get-code/Readme-CN.md index a2dbbc91bbebb45f6609d07ca87191ed509e3ab4..82da2d561e3ade5ee95dbe4c1411c4114ad6ad2b 100755 --- a/zh-cn/device-dev/get-code/Readme-CN.md +++ b/zh-cn/device-dev/get-code/Readme-CN.md @@ -1,7 +1,9 @@ # 获取源码 -- [源码获取](源码获取.md) -- [获取工具](获取工具.md) - - [Docker编译环境](Docker编译环境.md) - - [IDE](IDE.md) +- [获取源码](sourcecode.md) + - [源码获取](sourcecode-acquire.md) + +- [获取工具](gettools.md) + - [Docker编译环境](gettools-acquire.md) + - [IDE](gettools-ide.md) diff --git a/zh-cn/device-dev/get-code/figures/3.png b/zh-cn/device-dev/get-code/figure/3-20.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/3.png rename to zh-cn/device-dev/get-code/figure/3-20.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001101413884.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001101413884.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001101413884.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001101413884.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119755646.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119755646.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119755646.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119755646.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119915556.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119915556.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001119915556.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001119915556.png diff --git a/zh-cn/device-dev/get-code/figures/zh-cn_image_0000001166715379.png b/zh-cn/device-dev/get-code/figure/zh-cn_image_0000001166715379.png similarity index 100% rename from zh-cn/device-dev/get-code/figures/zh-cn_image_0000001166715379.png rename to zh-cn/device-dev/get-code/figure/zh-cn_image_0000001166715379.png diff --git a/zh-cn/device-dev/get-code/gettools-acquire.md b/zh-cn/device-dev/get-code/gettools-acquire.md new file mode 100644 index 0000000000000000000000000000000000000000..942635e189a91797d3624a574a4d2892d52e6a7d --- /dev/null +++ b/zh-cn/device-dev/get-code/gettools-acquire.md @@ -0,0 +1,313 @@ +# Docker编译环境 + +- [Docker环境介绍](#section107932281315) +- [环境准备](#section7337134183512) +- [独立Docker环境](#section2858536103611) + - [搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section319412277287) + - [编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)](#section631485163615) + - [搭建Docker环境-标准系统类设备(参考内存≥128MB)](#section13585262391) + - [编译源码-标准系统类设备(参考内存≥128MB)](#section193711513406) + +- [基于HPM的Docker环境](#section485713518337) + - [搭建Docker环境](#section3295842510) + - [获取及编译源码](#section69141039143518) + + +## Docker环境介绍 + +OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下: + +- 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。 +- 基于HPM的Docker环境:适用于使用HPM工具进行发行版编译的场景。 + +**表 1** Docker镜像介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Docker环境

+

系统类型

+

运行平台

+

Docker镜像仓库

+

标签

+

独立 Docker环境

+

轻量和小型系统

+

Ubuntu/Windows

+

swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

+

0.0.5

+

标准系统

+

Ubuntu

+

swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard

+

0.0.1

+

HPM Docker环境

+

轻量和小型系统

+

Ubuntu/Windows

+

swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker

+

0.0.3

+
+ +## 环境准备 + +在使用docker环境前需要先完成以下操作: + +1. 安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/)。 +2. 获取OpenHarmony源码,请参考[获取源码](sourcecode-acquire.md)。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >HPM Docker环境无需单独获取源码。 + + +## 独立Docker环境 + +OpenHarmony的Docker镜像托管在[HuaweiCloud SWR](https://console.huaweicloud.com/swr/?region=cn-south-1#/app/warehouse/warehouseMangeDetail/goldensir/openharmony-docker/openharmony-docker?type=ownImage)上。开发者可以通过该镜像在很大程度上简化编译前的环境配置。下文将介绍具体使用步骤。 + +### 搭建Docker环境-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) + +**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** + +1. 获取Docker镜像。 + + ``` + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + +2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ubuntu下执行: + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + windows下执行(假设源码目录为D:\\OpenHarmony): + + ``` + docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + +**方式二:通过Dockerfile 构建本地Docker镜像进行构建** + +1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 + + ``` + git clone https://gitee.com/openharmony/docs.git + ``` + +2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 + + ``` + cd docs/docker + ./build.sh + ``` + +3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ubuntu下执行: + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + windows下执行(假设源码目录为D:\\OpenHarmony): + + ``` + docker run -it -v D:\OpenHarmony:/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.5 + ``` + + +### 编译源码-轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB) + +通过如下编译脚本启动轻量系统类设备(参考内存≥128KB)和小型系统类设备(参考内存≥1MB)的编译。下文以Hi3516平台为例说明具体编译步骤。 + +设置编译路径,选择当前路径。 + +``` +hb set + . +``` + +**图 1** 设置编译界面 + + +![](figure/zh-cn_image_0000001101413884.png) + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前开发板平台和编译界面的对应关系如下: +>- Hi3861:wifiiot\_hispark\_pegasus@hisilicon +>- Hi3516:ipcamera\_hispark\_taurus@hisilicon +>- Hi3518:ipcamera\_hispark\_aries@hisilicon + +1. 选择ipcamera\_hispark\_taurus@hisilicon并回车。 +2. 执行编译。 + + ``` + hb build -f + ``` + +3. 查看编译结果。 + + 编译结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 + + +### 搭建Docker环境-标准系统类设备(参考内存≥128MB) + +**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** + +1. 获取Docker镜像。 + + ``` + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + +2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + + +**方式二:通过Dockerfile 构建本地Docker镜像进行构建** + +1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 + + ``` + git clone https://gitee.com/openharmony/docs.git + ``` + +2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 + + ``` + cd docs/docker/standard + ./build.sh + ``` + +3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 + ``` + + +### 编译源码-标准系统类设备(参考内存≥128MB) + +1. 在源码的根目录执行预处理脚本。 + + ``` + ../scripts/prepare.sh + ``` + +2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + + +>![](../public_sys-resources/icon-note.gif) **说明:** +>退出Docker执行exit命令即可。 + +## 基于HPM的Docker环境 + +docker\_dist是一个[HPM](https://hpm.harmonyos.com/)系统中的模板组件,能够帮助用户快速初始化HPM工程,利用docker镜像来快速编译OpenHarmony发行版,在很大程度上简化了编译前的环境配置。开发者在配置好Ubuntu和[hpm-cli](../bundles/bundles-guide-prepare.md)开发环境后,可以通过以下步骤来使用我们提供的Docker环境。 + +### 搭建Docker环境 + +1. 初始化安装模板。在任意工作目录中执行以下命令。 + + ``` + hpm init -t @ohos/docker_dist + ``` + +2. 修改publishAs。 + + 因为获取到的是模板类型的包,要把包的类型改为需要的类型。 在当前目录下打开bundle.json文件,把"publishAs"字段的值由"template"改为"distribution"。 + + +### 获取及编译源码 + +执行编译。自动安装docker只能在Ubuntu环境下执行,如果其他环境,需要用户自行安装docker,然后拉取镜像,执行编译。 + +- **自动安装docker(Ubuntu环境)** + + 以下命令可以帮助用户自动安装docker, 拉取镜像,并且在容器中开始运行对应解决方案的拉取和编译。 + + **方式一:** + + 命令后接参数指定解决方案,格式如下: + + ``` + hpm run docker solution={product} + ``` + + \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 + + **方式二:** + + 设置环境变量来选择解决方案,再执行编译命令。 + + 1. 选择解决方案。 + + ``` + export solution={product} + ``` + + \{product\}为需编译的解决方案,如:@ohos/hispark\_taurus、@ohos/hispark\_aries、@ohos/hispark\_pegasus。 + + 2. 获取源码及执行编译。 + + ``` + hpm run docker + ``` + + + 以上两种方式以@ohos/hispark\_taurus为例,执行成功结果如下: + + ``` + ...... + ohos ipcamera_hispark_taurus build success! + @ohos/hispark_taurus: distribution building completed. + ``` + + +- **自行安装docker(非Ubuntu环境)** + + 自行安装docker相关操作如下: + + ``` + # 拉取镜像 + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:0.0.3# linux环境下的编译 + hpm run distWithDocker solution={product} + # windows下的编译,需要配置gitbash + hpm config set shellPath "gitbash路径" + hpm run distWithDocker solution={product} + ``` + + diff --git a/zh-cn/device-dev/get-code/gettools-ide.md b/zh-cn/device-dev/get-code/gettools-ide.md new file mode 100644 index 0000000000000000000000000000000000000000..8217ddc1222045e4633d5cd05289e20169ce90e4 --- /dev/null +++ b/zh-cn/device-dev/get-code/gettools-ide.md @@ -0,0 +1,17 @@ +# IDE + +- [获取设备开发工具(HUAWEI DevEco Device Tool)](#section2452141120244) +- [获取应用开发工具(HUAWEI DevEco Studio)](#section0904101019258) + +## 获取设备开发工具(HUAWEI DevEco Device Tool) + +HUAWEI DevEco Device Tool是OpenHarmony面向智能设备开发者提供的一站式集成开发环境,支持OpenHarmony的组件按需定制,支持代码编辑、编译、烧录、调试等功能,支持C/C++语言,以插件的形式部署在Visual Studio Code上。具体可参见[获取工具](https://device.harmonyos.com/cn/ide)和[工具使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905)**。** + +Huawei DevEco Device Tool支持 OpenHarmony设备开发的演进路标如下: + +![](figure/3-20.png) + +## 获取应用开发工具(HUAWEI DevEco Studio) + +HUAWEI DevEco Studio(以下简称DevEco Studio)是面向华为终端全场景多设备的一站式集成开发环境(IDE),为开发者提供工程模板创建、开发、编译、调试、发布等E2E的OpenHarmony应用开发服务。通过使用DevEco Studio,开发者可以更高效的开发具备OpenHarmony分布式能力的应用,进而提升创新效率。具体可参见[获取工具](https://developer.harmonyos.com/cn/develop/deveco-studio)和[工具使用指南](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)。 + diff --git a/zh-cn/device-dev/get-code/gettools.md b/zh-cn/device-dev/get-code/gettools.md new file mode 100644 index 0000000000000000000000000000000000000000..4e35772567489dde5083791a9ac2596331588446 --- /dev/null +++ b/zh-cn/device-dev/get-code/gettools.md @@ -0,0 +1,7 @@ +# 获取工具 + +- **[Docker编译环境](gettools-acquire.md)** + +- **[IDE](gettools-ide.md)** + + diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/get-code/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/get-code/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-note.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/get-code/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/get-code/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/get-code/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/get-code/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/get-code/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/get-code/public_sys-resources/icon-warning.gif and /dev/null differ diff --git a/zh-cn/device-dev/get-code/sourcecode-acquire.md b/zh-cn/device-dev/get-code/sourcecode-acquire.md new file mode 100644 index 0000000000000000000000000000000000000000..de62e5dd995d6a7de8b758b06d859999648a7e1f --- /dev/null +++ b/zh-cn/device-dev/get-code/sourcecode-acquire.md @@ -0,0 +1,426 @@ +# 源码获取 + +- [OpenHarmony介绍](#section6370143622110) +- [源码获取概述](#section12763342204) +- [获取方式1:从代码仓库获取](#section537312010229) + - [适用场景](#section10881513459) + - [前提条件](#section102871547153314) + - [操作步骤](#section429012478331) + +- [获取方式2:从HPM获取](#section463013147412) + - [适用场景](#section26661067443) + - [前提条件](#section17544943123315) + - [操作步骤](#section954619433333) + +- [获取方式3:从镜像站点获取](#section1186691118430) +- [源码目录简介](#section1072115612811) + +## OpenHarmony介绍 + +OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。 + +开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com) + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前的OpenHarmony源代码仅支持在Linux环境下编译。 + +## 源码获取概述 + +本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以[组件](../bundles/bundles-standard-rules.md)的形式开放,开发者可以通过如下其中一种方式获取: + +- **获取方式1**:从代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。 +- **获取方式2**:通过HPM包管理器获取。在[HPM](https://hpm.harmonyos.com)网站,查找满足需求的开源发行版,直接下载(或者定制后下载),再通过hpm-cli命令工具将所需的组件及工具链下载、安装到本地。 +- **获取方式3**:从镜像站点下载归档后的发行版压缩文件。如果要获取旧版本的源码,也可通过此方式获取,此方式下载速度较快。 + +## 获取方式1:从代码仓库获取 + +### 适用场景 + +- 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。 + +- 已经完成自身软件与OpenHarmony的对接,需要进行OpenHarmony官方认证。 + +- 芯片/模组/app通过OpenHarmony官方认证后,贡献代码到OpenHarmony社区。 + +- 修复OpenHarmony的问题。 + +- 学习OpenHarmony的源码。 + + +### 前提条件 + +1. 注册码云gitee账号。 +2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 +3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 + + ``` + git config --global user.name "yourname" + git config --global user.email "your-email-address" + git config --global credential.helper store + ``` + +4. 安装码云repo工具,可以执行如下命令。 + + ``` + curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 + chmod a+x /usr/local/bin/repo + pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests + ``` + + +### 操作步骤 + +**获取轻量/小型/标准系统(2.0 Canary)源码** + +>![](../public_sys-resources/icon-note.gif) **说明:** +>主干代码为开发分支,开发者可通过主干代码获取最新特性。release分支代码相对比较稳定,开发者可基于release分支代码进行商用功能开发。 + +- **OpenHarmony主干代码获取** + + 方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 + + ``` + repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify + repo sync -c + repo forall -c 'git lfs pull' + ``` + + 方式二:通过repo + https 下载。 + + ``` + repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify + repo sync -c + repo forall -c 'git lfs pull' + ``` + + +- **OpenHarmony release 分支最新代码获取** + + >![](../public_sys-resources/icon-note.gif) **说明:** + >当前通过release分支只能获取轻量和小型系统源码。 + + 通过repo下载。 + + ``` + repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify + repo sync -c + repo forall -c 'git lfs pull' + ``` + +- OpenHarmony其他版本源码获取方式请参考版本[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md)。 + +## 获取方式2:从HPM获取 + +### 适用场景 + +对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在[HPM](https://hpm.harmonyos.com)网站获取下载开源发行版,也可以在开源发行版的基础上定制(添加或删除组件)。然后通过包管理器命令行工具(hpm-cli)将需要的组件及相关的编译工具链全部下载、安装到本地。 + +### 前提条件 + +先要在本地安装Node.js和hpm命令行工具,安装步骤如下: + +1. 安装Node.js。 + + 官网下载并在本地安装Node.js. + + 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 + +2. 通过Node.js自带的npm安装hpm命令行工具。 + + 打开CMD,执行以下命令: + + ``` + npm install -g @ohos/hpm-cli + ``` + +3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 + + ``` + hpm -V 或 hpm --version + ``` + +4. 如果升级hpm的版本,请执行如下命令: + + ``` + npm update -g @ohos/hpm-cli + ``` + + +### 操作步骤 + +1. 查找发行版。 + 1. 打开包管理页面[HPM](https://hpm.harmonyOS.com),设定搜索的对象为“发行版“,如下图所示。 + 2. 在搜索框输入关键字搜索,如“摄像头”。 + 3. 结果中显示与关键字匹配的发行版,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。 + 4. 查找合适的发行版,点击查看发行版的详情介绍。 + + **图 1** 包管理 + + + ![](figure/zh-cn_image_0000001119915556.png) + + +2. 了解发行版详情。 + + 1. 仔细阅读发行版的说明信息,以了解使用场景、特性、组件构成、使用方法以及如何进行定制化,如下图所示。 + 2. 点击「直接下载」,将发行版下载到本地。 + 3. 点击「定制组件」,将对发行版包含的组件进行定制(添加/删除)。 + + **图 2** 发行版示例 + + + ![](figure/zh-cn_image_0000001119755646.png) + +3. 定制组件。 + 1. 进入发行版的定制页面,如下图所示。 + 2. 通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。 + 3. 在右边填写您的项目基本信息,包括名称、版本、描述等信息。 + 4. 点击“下载“,系统会根据您的选择,生成相应的OpenHarmony代码结构文件\(如my\_cust\_dist.zip\),保存至本地文件。 + + **图 3** 组件定制 + + + ![](figure/zh-cn_image_0000001166715379.png) + + +4. 下载安装组件。 + 1. 解压下载的压缩文件,用命令行工具CMD(Linux下的Shell终端) + 2. 在解压后的文件目录下执行hpm install指令 + 3. 下载的组件存在工程目录下的ohos\_bundles文件夹中(部分组件安装后会将源码复制到指定目录下)。 + + +## 获取方式3:从镜像站点获取 + +为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 本部分只提供OpenHarmony Master最新版本和LTS最新版本的源码获取方式, 其他版本源码获取方式以及具体版本信息请参考[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md) +>- 当前Master 1.0版本已经不再维护。 + +**表 1** 源码获取路径 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

LTS版本源码

+

版本信息

+

下载站点

+

SHA256校验码

+

全量代码(轻量和小型系统)

+

1.1.1

+

站点

+

SHA256 校验码

+

Hi3861解决方案(二进制)

+

1.1.1

+

站点

+

SHA256 校验码

+

Hi3518解决方案(二进制)

+

1.1.1

+

站点

+

SHA256 校验码

+

Hi3516解决方案(二进制)

+

1.1.1

+

站点

+

SHA256 校验码

+

RELEASE-NOTES

+

1.1.1

+

站点

+

-

+

Master版本源码

+

版本信息

+

下载站点

+

SHA256校验码

+

全量代码(标准系统)

+

2.0 Canary

+

站点1站点2

+

SHA256校验码

+

全量代码(轻量和小型系统)

+

1.0(不再维护)

+

站点

+

SHA256 校验码

+

Hi3861解决方案(二进制)

+

1.0(不再维护)

+

站点

+

SHA256 校验码

+

Hi3518解决方案(二进制)

+

1.0(不再维护)

+

站点

+

SHA256 校验码

+

Hi3516解决方案(二进制)

+

1.0(不再维护)

+

站点

+

SHA256 校验码

+

RELEASE-NOTES

+

1.0(不再维护)

+

站点

+

-

+

编译工具链

+

版本信息

+

下载站点

+

SHA256校验码

+

编译工具链获取清单

+

-

+

站点

+

-

+
+ +## 源码目录简介 + +下表是OpenHarmony源码的目录及简单说明: + +**表 2** 源码目录 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

目录名

+

描述

+

applications

+

应用程序样例,包括camera等

+

base

+

基础软件服务子系统集&硬件服务子系统集

+

build

+

组件化编译、构建和配置脚本

+

docs

+

说明文档

+

domains

+

增强软件服务子系统集

+

drivers

+

驱动子系统

+

foundation

+

系统基础能力子系统集

+

kernel

+

内核子系统

+

prebuilts

+

编译器及工具链子系统

+

test

+

测试子系统

+

third_party

+

开源第三方组件

+

utils

+

常用的工具集

+

vendor

+

厂商提供的软件

+

build.py

+

编译脚本文件

+
+ diff --git a/zh-cn/device-dev/get-code/sourcecode.md b/zh-cn/device-dev/get-code/sourcecode.md new file mode 100644 index 0000000000000000000000000000000000000000..c5803f640fa69090e16fb33f1bd504282c61b207 --- /dev/null +++ b/zh-cn/device-dev/get-code/sourcecode.md @@ -0,0 +1,5 @@ +# 获取源码 + +- **[源码获取](sourcecode-acquire.md)** + + diff --git "a/zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" "b/zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" deleted file mode 100755 index 3b2c0526b4ee8ef6ef2e967f4b5d8a011011906c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/get-code/\346\272\220\347\240\201\350\216\267\345\217\226.md" +++ /dev/null @@ -1,426 +0,0 @@ -# 源码获取 - -- [OpenHarmony介绍](#section6370143622110) -- [源码获取概述](#section12763342204) -- [获取方式1:从代码仓库获取](#section537312010229) - - [适用场景](#section10881513459) - - [前提条件](#section102871547153314) - - [操作步骤](#section429012478331) - -- [获取方式2:从HPM获取](#section463013147412) - - [适用场景](#section26661067443) - - [前提条件](#section17544943123315) - - [操作步骤](#section954619433333) - -- [获取方式3:从镜像站点获取](#section1186691118430) -- [源码目录简介](#section1072115612811) - -## OpenHarmony介绍 - -OpenHarmony是由开放原子开源基金会(OpenAtom Foundation)孵化及运营的开源项目,目标是面向全场景、全连接、全智能时代,搭建一个智能终端设备操作系统的框架和平台,促进万物互联产业的繁荣发展。 - -开源代码仓库地址:[https://openharmony.gitee.com](https://openharmony.gitee.com) - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前的OpenHarmony源代码仅支持在Linux环境下编译。 - -## 源码获取概述 - -本文档将介绍如何获取OpenHarmony源码并说明OpenHarmony的源码目录结构。OpenHarmony的代码以[组件](../bundles/概述.md)的形式开放,开发者可以通过如下其中一种方式获取: - -- **获取方式1**:从代码仓库获取。通过repo或git工具从代码仓库中下载,此方式可获取最新代码。 -- **获取方式2**:通过HPM包管理器获取。在[HPM](https://hpm.harmonyos.com)网站,查找满足需求的开源发行版,直接下载(或者定制后下载),再通过hpm-cli命令工具将所需的组件及工具链下载、安装到本地。 -- **获取方式3**:从镜像站点下载归档后的发行版压缩文件。如果要获取旧版本的源码,也可通过此方式获取,此方式下载速度较快。 - -## 获取方式1:从代码仓库获取 - -### 适用场景 - -- 基于OpenHarmony的稳定分支建立自己的基线,分发下游客户。 - -- 已经完成自身软件与OpenHarmony的对接,需要进行OpenHarmony官方认证。 - -- 芯片/模组/app通过OpenHarmony官方认证后,贡献代码到OpenHarmony社区。 - -- 修复OpenHarmony的问题。 - -- 学习OpenHarmony的源码。 - - -### 前提条件 - -1. 注册码云gitee账号。 -2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading)并配置用户信息。 - - ``` - git config --global user.name "yourname" - git config --global user.email "your-email-address" - git config --global credential.helper store - ``` - -4. 安装码云repo工具,可以执行如下命令。 - - ``` - curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 - chmod a+x /usr/local/bin/repo - pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests - ``` - - -### 操作步骤 - -**获取轻量/小型/标准系统(2.0 Canary)源码** - ->![](public_sys-resources/icon-note.gif) **说明:** ->主干代码为开发分支,开发者可通过主干代码获取最新特性。release分支代码相对比较稳定,开发者可基于release分支代码进行商用功能开发。 - -- **OpenHarmony主干代码获取** - - 方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 - - ``` - repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify - repo sync -c - repo forall -c 'git lfs pull' - ``` - - 方式二:通过repo + https 下载。 - - ``` - repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify - repo sync -c - repo forall -c 'git lfs pull' - ``` - - -- **OpenHarmony release 分支最新代码获取** - - >![](public_sys-resources/icon-note.gif) **说明:** - >当前通过release分支只能获取轻量和小型系统源码。 - - 通过repo下载。 - - ``` - repo init -u https://gitee.com/openharmony/manifest.git -b OpenHarmony_1.0.1_release --no-repo-verify - repo sync -c - repo forall -c 'git lfs pull' - ``` - -- **OpenHarmony** 其他版本源码获取方式请参考版本[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md)。 - -## 获取方式2:从HPM获取 - -### 适用场景 - -对于刚接触OpenHarmony的新用户,希望能够参考一些示例解决方案从而进行快速开发。可以在[HPM](https://hpm.harmonyos.com)网站获取下载开源发行版,也可以在开源发行版的基础上定制(添加或删除组件)。然后通过包管理器命令行工具(hpm-cli)将需要的组件及相关的编译工具链全部下载、安装到本地。 - -### 前提条件 - -先要在本地安装Node.js和hpm命令行工具,安装步骤如下: - -1. 安装Node.js。 - - 官网下载并在本地安装Node.js. - - 推荐安装 [Node.js](https://nodejs.org/) 12.x \(包含 npm 6.14.4\)或更高版本 \(推荐 12.13.0+\)。 - -2. 通过Node.js自带的npm安装hpm命令行工具。 - - 打开CMD,执行以下命令: - - ``` - npm install -g @ohos/hpm-cli - ``` - -3. 安装完成后执行如下命令,显示hpm版本,即安装成功。 - - ``` - hpm -V 或 hpm --version - ``` - -4. 如果升级hpm的版本,请执行如下命令: - - ``` - npm update -g @ohos/hpm-cli - ``` - - -### 操作步骤 - -1. 查找发行版。 - 1. 打开包管理页面[HPM](https://hpm.harmonyOS.com),设定搜索的对象为“发行版“,如下图所示。 - 2. 在搜索框输入关键字搜索,如“摄像头”。 - 3. 结果中显示与关键字匹配的发行版,可以进一步根据组件类别等过滤条件(如:适配的开发板,内核)精确筛选。 - 4. 查找合适的发行版,点击查看发行版的详情介绍。 - - **图 1** 包管理 - - - ![](figures/zh-cn_image_0000001119915556.png) - - -2. 了解发行版详情。 - - 1. 仔细阅读发行版的说明信息,以了解使用场景、特性、组件构成、使用方法以及如何进行定制化,如下图所示。 - 2. 点击「直接下载」,将发行版下载到本地。 - 3. 点击「定制组件」,将对发行版包含的组件进行定制(添加/删除)。 - - **图 2** 发行版示例 - - - ![](figures/zh-cn_image_0000001119755646.png) - -3. 定制组件。 - 1. 进入发行版的定制页面,如下图所示。 - 2. 通过关闭开关移除可选组件,或者通过“添加组件”增加新的组件。 - 3. 在右边填写您的项目基本信息,包括名称、版本、描述等信息。 - 4. 点击“下载“,系统会根据您的选择,生成相应的OpenHarmony代码结构文件\(如my\_cust\_dist.zip\),保存至本地文件。 - - **图 3** 组件定制 - - - ![](figures/zh-cn_image_0000001166715379.png) - - -4. 下载安装组件。 - 1. 解压下载的压缩文件,用命令行工具CMD(Linux下的Shell终端) - 2. 在解压后的文件目录下执行hpm install指令 - 3. 下载的组件存在工程目录下的ohos\_bundles文件夹中(部分组件安装后会将源码复制到指定目录下)。 - - -## 获取方式3:从镜像站点获取 - -为了获得更好的下载性能,您可以选择从以下站点的镜像库获取源码或者对应的解决方案。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 本部分只提供**OpenHarmony** Master最新版本和LTS最新版本的源码获取方式, 其他版本源码获取方式以及具体版本信息请参考[Release-Notes](https://gitee.com/openharmony/docs/blob/master/zh-cn/release-notes/OpenHarmony-Release-Notes.md) ->- 当前Master 1.0版本已经不再维护。 - -**表 1** 源码获取路径 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

LTS版本源码

-

版本信息

-

下载站点

-

SHA256校验码

-

全量代码(轻量和小型系统)

-

1.1.1

-

站点

-

SHA256 校验码

-

Hi3861解决方案(二进制)

-

1.1.1

-

站点

-

SHA256 校验码

-

Hi3518解决方案(二进制)

-

1.1.1

-

站点

-

SHA256 校验码

-

Hi3516解决方案(二进制)

-

1.1.1

-

站点

-

SHA256 校验码

-

RELEASE-NOTES

-

1.1.1

-

站点

-

-

-

Master版本源码

-

版本信息

-

下载站点

-

SHA256校验码

-

全量代码(标准系统)

-

2.0 Canary

-

站点1站点2

-

SHA256校验码

-

全量代码(轻量和小型系统)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

Hi3861解决方案(二进制)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

Hi3518解决方案(二进制)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

Hi3516解决方案(二进制)

-

1.0(不再维护)

-

站点

-

SHA256 校验码

-

RELEASE-NOTES

-

1.0(不再维护)

-

站点

-

-

-

编译工具链

-

版本信息

-

下载站点

-

SHA256校验码

-

编译工具链获取清单

-

-

-

站点

-

-

-
- -## 源码目录简介 - -下表是OpenHarmony源码的目录及简单说明: - -**表 2** 源码目录 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

目录名

-

描述

-

applications

-

应用程序样例,包括camera等

-

base

-

基础软件服务子系统集&硬件服务子系统集

-

build

-

组件化编译、构建和配置脚本

-

docs

-

说明文档

-

domains

-

增强软件服务子系统集

-

drivers

-

驱动子系统

-

foundation

-

系统基础能力子系统集

-

kernel

-

内核子系统

-

prebuilts

-

编译器及工具链子系统

-

test

-

测试子系统

-

third_party

-

开源第三方组件

-

utils

-

常用的工具集

-

vendor

-

厂商提供的软件

-

build.py

-

编译脚本文件

-
- diff --git "a/zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" "b/zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" deleted file mode 100755 index eeb55c7156473c57f088d2bce54464b13fd8ca92..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/get-code/\350\216\267\345\217\226\345\267\245\345\205\267.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 获取工具 - -- **[Docker编译环境](Docker编译环境.md)** - -- **[IDE](IDE.md)** - - diff --git a/zh-cn/device-dev/glossary/Readme-CN.md b/zh-cn/device-dev/glossary/Readme-CN.md index 1e55e64c536877c21128a54e333b2802f36fa1da..e69d48c93789ee931046637f2f6262f867c7a4ef 100755 --- a/zh-cn/device-dev/glossary/Readme-CN.md +++ b/zh-cn/device-dev/glossary/Readme-CN.md @@ -1,4 +1,4 @@ -# glossary +# 术语 -- [术语](术语.md) +- [术语](glossary.md) diff --git "a/zh-cn/device-dev/glossary/\346\234\257\350\257\255.md" b/zh-cn/device-dev/glossary/glossary.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/glossary/\346\234\257\350\257\255.md" rename to zh-cn/device-dev/glossary/glossary.md diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/glossary/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/glossary/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-note.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/glossary/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/glossary/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/glossary/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/glossary/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/glossary/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/glossary/public_sys-resources/icon-warning.gif and /dev/null differ diff --git "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" "b/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" deleted file mode 100644 index 90604006df166670190abe945a505eb3e81408b2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\345\267\245\344\275\234\346\265\201\347\250\213\350\247\243\346\236\220.md" +++ /dev/null @@ -1,18 +0,0 @@ -# Input模型工作流程解析 - -为了让开发者更清晰的了解Input模型工作流程,本节将对input模型加载的关键流程代码进行说明。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本章节为Input模型工作流程说明,开发者无需进行开发。 - -- **[私有配置信息解析](私有配置信息解析.md)** - -- **[管理驱动层初始化及注册驱动至HDF框架](管理驱动层初始化及注册驱动至HDF框架.md)** - -- **[公共驱动层初始化及注册驱动至HDF框架](公共驱动层初始化及注册驱动至HDF框架.md)** - -- **[器件驱动层初始化及注册驱动至HDF框架](器件驱动层初始化及注册驱动至HDF框架.md)** - -- **[具体调用逻辑串联函数](具体调用逻辑串联函数.md)** - - diff --git "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" "b/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" deleted file mode 100644 index 2ad3264215219982f95f0ebd29fd39bc2b480e71..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/Input\346\250\241\345\236\213\347\256\200\344\273\213.md" +++ /dev/null @@ -1,12 +0,0 @@ -# Input模型简介 - -Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。其中: - -- 设备管理层:主要为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; -- 公共驱动层:负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; -- 器件驱动层:通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; - -此外,Input模型预先实现了数据通道以及设备配置信息解析等函数。 - -关于Input模型的详细介绍请参考《[Touchscreen开发概述](../driver/Touchscreen开发概述.md)》。 - diff --git "a/zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" "b/zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" deleted file mode 100755 index fc94423bf4b226c2284c93a126c88618ba864537..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/LED\345\244\226\350\256\276\346\216\247\345\210\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# LED外设控制 - -- **[概述](概述.md)** - -- **[开发](开发.md)** - -- **[验证](验证.md)** - - diff --git a/zh-cn/device-dev/guide/Readme-CN.md b/zh-cn/device-dev/guide/Readme-CN.md index 6afa218aca591d6e446fe35e60821022c6a5459b..b447b4990ae7dbcbc12aaacec172224f3968718f 100755 --- a/zh-cn/device-dev/guide/Readme-CN.md +++ b/zh-cn/device-dev/guide/Readme-CN.md @@ -1,74 +1,39 @@ -# 开发示例 +# 设备开发指南 + +- [WLAN连接类产品](device-wifi.md) + - [LED外设控制](device-wifi-led-outcontrol.md) + - [集成三方SDK](device-wifi-sdk.md) + +- [无屏摄像头类产品](device-iotcamera.md) + - [概述](device-iotcamera-control-overview.md) + - [示例开发](device-iotcamera-control-demo.md) + - [拍照开发指导](device-iotcamera-control-demo-photodevguide.md) + - [录像开发指导](device-iotcamera-control-demo-videodevguide.md) + + - [应用实例](device-iotcamera-control-example.md) + +- [带屏摄像头类产品](device-camera.md) + - [屏幕和摄像头控制](device-camera-control.md) + - [概述](device-camera-control-overview.md) + - [示例开发](device-camera-control-demo.md) + - [拍照开发指导](device-camera-control-demo-photoguide.md) + - [录像开发指导](device-camera-control-demo-videoguide.md) + - [预览开发指导](device-camera-control-demo-previewguide.md) + + - [应用实例](device-camera-control-example.md) + + - [视觉应用开发](device-camera-visual.md) + - [概述](device-camera-visual-overview.md) + - [开发准备](device-camera-visual-prepare.md) + - [添加页面](device-camera-visual-addpage.md) + - [开发首页](device-camera-visual-first-page.md) + - [开发详情页](device-camera-visual-details.md) + - [调试打包](device-camera-visual-debug.md) + - [真机运行](device-camera-visual-run.md) + - [常见问题](device-camera-visual-faqs.md) + +- [时钟应用开发指导](device-clock-guide.md) +- [平台驱动开发示例](device-drive-demo.md) +- [外设驱动开发示例](device-outerdrive-demo.md) -- [WLAN连接类产品](WLAN连接类产品.md) - - [LED外设控制](LED外设控制.md) - - [概述](概述.md) - - [开发](开发.md) - - [验证](验证.md) - - - [集成三方SDK](集成三方SDK.md) - -- [无屏摄像头类产品](无屏摄像头类产品.md) - - [摄像头控制](摄像头控制.md) - - [概述](概述-0.md) - - [示例开发](示例开发.md) - - [拍照开发指导](拍照开发指导.md) - - [录像开发指导](录像开发指导.md) - - - [应用实例](应用实例.md) - -- [带屏摄像头类产品](带屏摄像头类产品.md) - - [屏幕和摄像头控制](屏幕和摄像头控制.md) - - [概述](概述-1.md) - - [示例开发](示例开发-2.md) - - [拍照开发指导](拍照开发指导-3.md) - - [录像开发指导](录像开发指导-4.md) - - [预览开发指导](预览开发指导.md) - - - [应用实例](应用实例-5.md) - - - [视觉应用开发](视觉应用开发.md) - - [概述](概述-6.md) - - [开发准备](开发准备.md) - - [添加页面](添加页面.md) - - [开发首页](开发首页.md) - - [开发详情页](开发详情页.md) - - [调试打包](调试打包.md) - - [真机运行](真机运行.md) - - [常见问题](常见问题.md) - -- [时钟应用开发示例](时钟应用开发示例.md) - - [概述](概述-7.md) - - [开发准备](开发准备-8.md) - - [开发步骤](开发步骤.md) - - [签名打包](签名打包.md) - - [真机运行](真机运行-9.md) - -- [平台驱动开发示例](平台驱动开发示例.md) - - [概述](概述-10.md) - - [环境准备](环境准备.md) - - [开发](开发-11.md) - - [编译及烧录](编译及烧录.md) - -- [外设驱动开发示例](外设驱动开发示例.md) - - [概述](概述-12.md) - - [硬件资源介绍](硬件资源介绍.md) - - [Input模型简介](Input模型简介.md) - - - [环境搭建](环境搭建.md) - - [TouchScreen器件驱动开发](TouchScreen器件驱动开发.md) - - [配置设备描述信息](配置设备描述信息.md) - - [配置Touchscreen器件信息](配置Touchscreen器件信息.md) - - [适配器件私有驱动](适配器件私有驱动.md) - - - [编译及烧录](编译及烧录-13.md) - - [调试验证](调试验证.md) - - [开机日志分析](开机日志分析.md) - - - [Input模型工作流程解析](Input模型工作流程解析.md) - - [私有配置信息解析](私有配置信息解析.md) - - [管理驱动层初始化及注册驱动至HDF框架](管理驱动层初始化及注册驱动至HDF框架.md) - - [公共驱动层初始化及注册驱动至HDF框架](公共驱动层初始化及注册驱动至HDF框架.md) - - [器件驱动层初始化及注册驱动至HDF框架](器件驱动层初始化及注册驱动至HDF框架.md) - - [具体调用逻辑串联函数](具体调用逻辑串联函数.md) diff --git "a/zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" deleted file mode 100644 index ef2d3835fa3e16bf4f94ec4d40017dba3cafd5b0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/TouchScreen\345\231\250\344\273\266\351\251\261\345\212\250\345\274\200\345\217\221.md" +++ /dev/null @@ -1,17 +0,0 @@ -# TouchScreen器件驱动开发 - -基于Input模型适配一款触摸屏IC需要完成的工作有: - -1.配置设备描述信息。驱动注册到HDF框架所需要的设备驱动描述信息,如驱动是否加载以及加载次序等; - -2.配置器件私有信息、平台硬件信息。器件私有信息包括上下电时序等,平台硬件信息包括器件连接主板的GPIO端口信息等。 - -3.适配器件私有驱动。 Input模型对Input设备开发流程进行了抽象,开发者只需要适配器件驱动层,无需改动管理驱动层以及公共驱动层。 - -- **[配置设备描述信息](配置设备描述信息.md)** - -- **[配置Touchscreen器件信息](配置Touchscreen器件信息.md)** - -- **[适配器件私有驱动](适配器件私有驱动.md)** - - diff --git "a/zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" "b/zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" deleted file mode 100755 index 08afdfcafc40033c66ba69f0f0580ab2e73d13ae..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/WLAN\350\277\236\346\216\245\347\261\273\344\272\247\345\223\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# WLAN连接类产品 - -- **[LED外设控制](LED外设控制.md)** - -- **[集成三方SDK](集成三方SDK.md)** - - diff --git a/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md b/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md new file mode 100644 index 0000000000000000000000000000000000000000..0cae9c359bf6c5b036a4f947635d7c2ca289b65a --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-demo-photoguide.md @@ -0,0 +1,396 @@ +# 拍照开发指导 + +- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) +- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) +- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) +- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) + +## 使用场景 + +使用Camera产生图片帧(拍照)。 + +## 接口说明 + +**表 1** API列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

类名

+

接口名

+

描述

+

CameraKit

+

int32_t GetCameraIds(std::list<string> cameraList)

+

获取cameraId列表

+

CameraKit

+

CameraAbility& GetCameraAbility(string cameraId)

+

获取指定camera的能力

+

CameraKit

+

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

+

注册camera设备状态回调

+

CameraKit

+

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

+

去注册camera设备状态回调

+

CameraKit

+

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

+

创建camera实例

+

Camera

+

string GetCameraId()

+

获取cameraID

+

Camera

+

CameraConfig& GetCameraConfig()

+

获取camera配置信息

+

Camera

+

FrameConfig& GetFrameConfig(int32_t type)

+

获取捕获帧类型

+

Camera

+

void Configure(CameraConfig& config)

+

配置camera

+

Camera

+

void Release()

+

释放camera

+

Camera

+

int TriggerLoopingCapture(FrameConfig& frameConfig)

+

开始循环帧捕获

+

Camera

+

void StopLoopingCapture()

+

停止循环帧捕获

+

Camera

+

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

+

抓图

+

CameraConfig

+

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

+

设置帧状态回调

+

CameraConfig

+

static CameraConfig* CreateCameraConfig()

+

创建camera配置信息实例

+

CameraAbility

+

std::list<Size> GetSupportedSizes(int format)

+

根据类型获取支持输出图像尺寸大小

+

CameraAbility

+

std::list<T> GetParameterRange(uint32_t key)

+

获取支持的参数范围

+

CameraDevice

+

CameraDeviceCallback()

+

camera设备回调类构造函数

+

CameraDevice

+

void OnCameraStatus​(std::string cameraId, int32_t status)

+

camera设备状态变化时的回调

+

CameraStateCallback

+

CameraStateCallback​()

+

camera状态回调类构造函数

+

CameraStateCallback

+

void OnConfigured​(Camera& camera)

+

camera配置成功回调

+

CameraStateCallback

+

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

+

camera配置失败回调

+

CameraStateCallback

+

void OnCreated​(Camera& camera)

+

camera创建成功回调

+

CameraStateCallback

+

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

+

camera创建失败回调

+

CameraStateCallback

+

void OnReleased​(Camera& camera)

+

camera释放回调

+

FrameStateCallback

+

FrameStateCallback​()

+

帧状态回调类构造函数

+

FrameStateCallback

+

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

+

拍照帧完成回调

+

FrameStateCallback

+

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

+

拍照帧异常回调

+

FrameConfig

+

int32_t GetFrameConfigType()

+

获取帧配置类型

+

FrameConfig

+

std::list<OHOS::Surface> GetSurfaces()

+

获取帧配置的surface

+

FrameConfig

+

void AddSurface(OHOS::AGP::UISurface& surface);

+

添加surface

+

FrameConfig

+

void RemoveSurface(OHOS::AGP::UISurface& surface);

+

删除surface

+
+ +## 约束与限制 + +无。 + +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + camKit->CreateCamera(camId, CamStateMng, eventHdlr); + ``` + +6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` + + diff --git "a/zh-cn/device-dev/guide/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/guide/device-camera-control-demo-previewguide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/guide/device-camera-control-demo-previewguide.md diff --git "a/zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274-4.md" b/zh-cn/device-dev/guide/device-camera-control-demo-videoguide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274-4.md" rename to zh-cn/device-dev/guide/device-camera-control-demo-videoguide.md diff --git a/zh-cn/device-dev/guide/device-camera-control-demo.md b/zh-cn/device-dev/guide/device-camera-control-demo.md new file mode 100644 index 0000000000000000000000000000000000000000..3d42880861d0a17d7ab59f6bead3d0b312d65f3e --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-demo.md @@ -0,0 +1,9 @@ +# 示例开发 + +- **[拍照开发指导](device-camera-control-demo-photoguide.md)** + +- **[录像开发指导](device-camera-control-demo-videoguide.md)** + +- **[预览开发指导](device-camera-control-demo-previewguide.md)** + + diff --git a/zh-cn/device-dev/guide/device-camera-control-example.md b/zh-cn/device-dev/guide/device-camera-control-example.md new file mode 100644 index 0000000000000000000000000000000000000000..a092908acd9e92234b09634c4cdef1cf1a3d3c94 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-example.md @@ -0,0 +1,63 @@ +# 应用实例 + +本示例将运行源码中的camera示例代码,通过本示例可以实现对开发板拍照、录像及预览功能的控制。 + +- 本示例源码路径为“applications/sample/camera/media/camera\_sample.cpp”。 +- 在运行本示例前需先完成编译烧录、运行镜像等步骤,相关操作请参考[Hi3516快速入门](../quick-start/quickstart-lite-introduction-hi3516.md#section26131214194212)。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >开发板启动后默认会加载launcher应用,应用的图形界面默认显示在媒体图层上方,会影响camera\_sample的演示结果,因此需要在编译或是打包时去掉launcher应用。 + >**修改方法:**将“build/lite/components/applications.json”中camera\_sample\_app组件的targets中"//applications/sample/camera/launcher:launcher\_hap"整行注释或删除。 + +- 本示例编译结果路径为“out/hi3516dv300/ipcamera\_hi3516dv300\_liteos/dev\_tools/bin”,为让文件能在单板中执行,可将示例文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 + + 修改源码路径“applications/sample/camera/media/BUILD.gn”中第一处的output\_dir。 + + - 修改前:output\_dir = "$root\_out\_dir/dev\_ools" + - 修改后:output\_dir = "$root\_out\_dir/" + + 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 + +- 接下来可通过以下步骤运行示例: + +1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 + + **图 1** 启动示例 + ![](figure/启动示例.png "启动示例") + + 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 + +2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* + + **图 2** 输入拍照指令后串口打印日志 + ![](figure/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") + + 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 + + **图 3** 查看文件图 + ![](figure/查看文件图.png "查看文件图") + +3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 + + **图 4** 输入录像指令后串口打印日志 + ![](figure/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") + +4. 按3进行预览,预览图像直接送至显示屏,按s键停止。 + + **图 5** 输入预览指令后串口打印日志 + ![](figure/输入预览指令后串口打印日志.png "输入预览指令后串口打印日志") + + 预览效果如下 + + **图 6** 预览效果 + ![](figure/预览效果.jpg "预览效果") + +5. 按q键退出 + + **图 7** 输出退出指令后串口打印日志 + ![](figure/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") + + diff --git a/zh-cn/device-dev/guide/device-camera-control-overview.md b/zh-cn/device-dev/guide/device-camera-control-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..0bf698b5356079826b7ad124648f76965a4b5770 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control-overview.md @@ -0,0 +1,10 @@ +# 概述 + +本文档将介绍如何基于IoT Camera开发板(Hi3516DV300),利用其摄像头和屏幕,完成拍照、录像和视频预览功能。 + +通过本文档,开发者能够对OpenHarmony的摄像控制有更深入的了解,可参照本例尝试完成“智能猫眼”、“智能后视镜”、“智能带屏音箱”等设备的开发。 + +若开发者想先查看示例效果,请进入[应用实例](device-camera-control-example.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 + +相机应用开发的基本概念请参考:[相机开发概述](../subsystems/subsys-multimedia-camera-overview.md)。 + diff --git a/zh-cn/device-dev/guide/device-camera-control.md b/zh-cn/device-dev/guide/device-camera-control.md new file mode 100644 index 0000000000000000000000000000000000000000..a3e406a2e3c71d213ec842dc8d0722c366570022 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-control.md @@ -0,0 +1,9 @@ +# 屏幕和摄像头控制 + +- **[概述](device-camera-control-overview.md)** + +- **[示例开发](device-camera-control-demo.md)** + +- **[应用实例](device-camera-control-example.md)** + + diff --git a/zh-cn/device-dev/guide/device-camera-visual-addpage.md b/zh-cn/device-dev/guide/device-camera-visual-addpage.md new file mode 100644 index 0000000000000000000000000000000000000000..3929ffbf6aee8d1ecf8ff07da1e3ceeadfa7b2db --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-addpage.md @@ -0,0 +1,34 @@ +# 添加页面 + +- [创建首页面](#section16935511143715) +- [创建详情页](#section122131729173819) + +## 创建首页面 + +空气质量监测App包含两个界面(Page),工程创建完成后会生成一个名为index的Page,可以作为首页。工程目录如下图所示: + +**图 1** 工程目录 +![](figure/工程目录.png "工程目录") + +## 创建详情页 + +新增一个Page,作为详情页,具体步骤如下: + +1. pages目录右键 ,弹出的菜单中选择New、JS Page。 + + **图 2** 添加页面 + ![](figure/添加页面.png "添加页面") + +2. 输入Page名称。 + + **图 3** 输入页面名称 + ![](figure/输入页面名称.png "输入页面名称") + +3. 确认创建结果。 + + 详情页创建完成后应用工程目录如下图所示,每个Page包括三个文件:布局文件hml、样式文件css、业务逻辑代码js。 + + **图 4** 完整工程目录 + ![](figure/完整工程目录.png "完整工程目录") + + diff --git a/zh-cn/device-dev/guide/device-camera-visual-debug.md b/zh-cn/device-dev/guide/device-camera-visual-debug.md new file mode 100644 index 0000000000000000000000000000000000000000..30505bcb3ebf9e4daf0bb1d6adb2b544f19209be --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-debug.md @@ -0,0 +1,4 @@ +# 调试打包 + +代码编写完成后,可以进行调试和打包;应用调试及打包方法可以参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)的[应用调测](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404)和[编译构建](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)章节。IPCamera应用暂时不支持签名模式,所以需要将应用发布为未签名的应用安装包。 + diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\350\257\246\346\203\205\351\241\265.md" b/zh-cn/device-dev/guide/device-camera-visual-details.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\274\200\345\217\221\350\257\246\346\203\205\351\241\265.md" rename to zh-cn/device-dev/guide/device-camera-visual-details.md diff --git "a/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/guide/device-camera-visual-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/guide/device-camera-visual-faqs.md diff --git a/zh-cn/device-dev/guide/device-camera-visual-first-page.md b/zh-cn/device-dev/guide/device-camera-visual-first-page.md new file mode 100644 index 0000000000000000000000000000000000000000..354097ab25c36055562f5c6469393e8f73fba01d --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-first-page.md @@ -0,0 +1,581 @@ +# 开发首页 + +应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。 + +从第一章节中的[显示效果图](device-camera-visual-overview.md#fig18250512195914)分析可知,首页由三部分组成: + +- 标题栏:位于页面正上方,位置固定,包括应用退出按钮和页面标题。 +- 信息栏:主要展示城市的空气信息指标等内容;该页面根据用户需求可设置多屏,且能循环滑动。 +- 页面位置指示器:主要功能是标识当前页面,位置固定在页面底部的中间。 + +综上,我们可搭建一个纵向三行排列的弹性页面布局来实现首页的功能。 + +1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: + + ``` +
+
+ ``` + + class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: + + ``` + .container { + flex-direction: column; + height: 480px; + width: 960px; + } + ``` + + 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向三行排列的弹性页面布局。 + +2. 实现标题栏:标题栏包括一个退出按钮和一个标题,两个控件是横向排列;首先添加一个div,并设置flex-direction的属性为row,表示子组件是水平方向从左往右排列;然后依次添加一个image和text组件,代码如下: + + ``` +
+
+ + + 空气质量 + +
+
+ ``` + + 设置组件的高度、边距、颜色等属性。 + + ``` + .header { + width: 960px; + height: 72px; + } + .back { + width: 36px; + height: 36px; + margin-left: 39px; + margin-top: 23px; + } + .title { + width: 296px; + height: 40px; + margin-top: 20px; + margin-left: 21px; + color: #e6e6e6; + } + ``` + + onclick="exitApp" 设置了div组件的click事件,当在标题栏上触发点击事件时,就会执行函数exitApp,该函数位于index.js文件中,代码如下: + + ``` + exitApp() { + console.log('start exit'); + app.terminate(); + console.log('end exit'); + } + ``` + + app.terminate\(\)函数实现了程序退出功能;在使用该函数前,需要引入app模块,在js文件的最上方写如下代码: + + ``` + import app from '@system.app' + ``` + + 代码编写完成后,在模拟器中运行项目,显示效果如下图所示: + + **图 1** 标题栏效果 + ![](figure/标题栏效果.png "标题栏效果") + +3. 实现城市空气质量信息的多屏左右滑动,需要使用“swiper”组件。 + + 在根节点中添加一个子节点swiper,代码片段如下: + + ``` +
+
+ + + 空气质量 + +
+ + +
+ ``` + + - class="swiper"设置了组件的高度和宽度,代码如下: + + ``` + .swiper { + height: 385px; + width: 960px; + } + ``` + + + - index="\{\{swiperPage\}\}" duration="500" onchange="swiperChange" 这些代码用来设置组件的属性和事件。其中,duration="500" 表示设置swiper的页面滑动的动画时长为500ms。 + - index="\{\{swiperPage\}\}"设置了swiper子组件索引值,\{\{swiperPage\}\}这种写法表示index的值是和js代码中的swiperPage变量动态绑定的,index的值会随着swiperPage变动而改变。 + - onchange="swiperChange" 设置了swiper组件的change事件和函数swiperChange绑定,对应的js代码如下: + + ``` + //引入router模块,用户页面跳转 + import router from'@system.router' + import app from '@system.app' + + export default { + //定义参数 + data: { + //默认是第一页 + swiperPage: 0 + }, + onInit () { + }, + exitApp(){ + console.log('start exit'); + app.terminate(); + console.log('end exit'); + }, + //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中 + swiperChange (e) { + this.swiperPage = e.index; + } + } + ``` + + +4. 设置一个城市的空气质量信息为一屏,在一屏内,要展示多种信息,分别使用不同的控件进行展示。 + + 在swiper中添加两个子组件stack(绝对布局),每个stack组件内分别添加text、image、progress等组件来显示对应的信息 ,页面结构如下: + + ``` + + + + ------空气质量 + ------城市名称 + -----进度条 + -------云朵图片 + --------AQI数值 + AQI------AQI +
--------空气指标详细信息 +
+
--------更新时间和网站等信息 +
+
+ + + + + + + + +
+
+
+ ``` + + 代码编写完成后,模拟器运行效果如下: + + **图 2** 标题栏和信息栏效果 + ![](figure/标题栏和信息栏效果.png "标题栏和信息栏效果") + +5. 添加页面位置指示器:由于当前swiper不支持设置indicator,需要开发者自己来实现该效果。在根节点中添加一个子组件div,并设置相应样式;然后在该div中添加两个子组件div,设置两个div的border-radius,并在swiper滑动事件中动态改变对应div的背景色来实现该效果。 + + ``` +
+
+
+
+ ``` + + **图 3** 页面位置指示器效果图 + ![](figure/页面位置指示器效果图.png "页面位置指示器效果图") + +6. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: + + - **index.hml文件** + + ``` +
+
+ + + 空气质量 + +
+ + + {{airData[0].airQuality}} + + {{airData[0].location}} + + + + {{airData[0].detailData}} + + + AQI + +
+
+ + CO + + + 100 + +
+
+ + NO2 + + + 90 + +
+
+ + PM10 + + + 120 + +
+
+ + PM2.5 + + + 40 + +
+
+ + SO2 + + + 150 + +
+ +
+ +
+ + {{airData[1].airQuality}} + + {{airData[1].location}} + + + + {{airData[1].detailData}} + + + AQI + +
+
+ + CO + + + 10 + +
+
+ + NO2 + + + 50 + +
+
+ + PM10 + + + 60 + +
+
+ + PM2.5 + + + 40 + +
+
+ + SO2 + + + 150 + +
+ +
+ +
+
+
+
+
+
+
+ ``` + + - **index.css文件** + + css文件中定义了许多class,每个class用于定义组件的位置、大小、字体、颜色、背景色等信息。同时,每一个子组件都叠加在父组件中,父组件的样式会影响子组件的呈现。 + + ``` + .aqi-value { + text-align: center; + font-size: 65px; + color: #f0ffff; + width: 156px; + height: 92px; + top: 134px; + left: 210px; + } + .aqi { + text-align: center; + color: #a2c4a2; + width: 156px; + height: 45px; + top: 90px; + left: 210px; + } + .airquality { + top: 222px; + text-align: center; + width: 156px; + height: 45px; + left: 210px; + } + .image { + top: 285px; + left: 274px; + width: 32px; + height: 32px; + } + .location-text { + text-align: center; + color: #ffffff; + width: 200px; + height: 52px; + font-size: 40px; + left: 380px; + top: 16px; + } + .container { + flex-direction: column; + height: 480px; + width: 960px; + } + .circle-progress { + center-x: 128px; + center-y: 128px; + radius: 128px; + startAngle: 198; + totalAngle: 320; + strokeWidth: 24px; + width: 256px; + height: 256px; + left: 160px; + top: 58px; + } + .detail { + width: 256px; + height: 265px; + left: 544px; + top: 58px; + flex-direction: column; + } + .text-wrapper { + width: 256px; + height: 35px; + margin-top: 6px; + } + .gas-name { + width: 128px; + height: 35px; + text-align: left; + } + .gas-value { + width: 128px; + height: 35px; + text-align: right; + } + .btn { + width: 180px; + height: 50px; + margin-top: 6px; + margin-left: 38px; + background-color: #1a1a1a; + color: #1085CE; + } + .footer { + top: 326px; + width: 960px; + height: 28px; + } + .header { + width: 960px; + height: 72px; + } + .back { + width: 36px; + height: 36px; + margin-left: 39px; + margin-top: 23px; + } + .title { + width: 296px; + height: 40px; + margin-top: 20px; + margin-left: 21px; + color: #e6e6e6; + } + .swiper { + height: 385px; + width: 960px; + } + .images { + width: 60px; + height: 15px; + margin-left: 450px; + } + .update-time { + width: 480px; + height: 28px; + font-size: 20px; + color: #A9A9A9; + text-align: right; + } + .info-source { + width: 450px; + height: 28px; + font-size: 20px; + color: #A9A9A9; + text-align: left; + margin-left: 24px; + } + .circle-div { + width: 12px; + height: 12px; + border-radius: 6px; + } + ``` + + - **index.js:** + + js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:根据数值动态改变文字、进度条颜色、页面跳转。 + + ``` + //导入router和app模块 + import router from '@system.router' + import app from '@system.app' + + export default { + data: { + //页面绑定数据 + textColor1: '#00ff00', + textColor2: '#00ff00', + bgColor1: '#669966', + bgColor2: '#669966', + swiperPage: 0, + percent1: 40, + percent2: 90, + iconUncheckedColor: '#262626', + iconcheckedColor: '#ffffff', + iconcheckedBR: '6px', + src1: 'common/cloud_green.png', + src2: 'common/cloud_green.png', + airData: [{ + location: '东莞', + airQuality: '良', + detailData: 40 + }, { + location: '深圳', + airQuality: '差', + detailData: 90 + }] + }, + onInit () { + //根据数值的不同,设置不同的字体、背景颜色和图片 + if(this.airData[0].detailData > 100){ + this.src1 = 'common/cloud_red.png'; + this.textColor1 = '#ff0000'; + this.bgColor1 = '#9d7462'; + } else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){ + this.src1 = 'common/cloud_yellow.png'; + this.textColor1 = '#ecf19a'; + this.bgColor1 = '#9d9d62'; + } + if(this.airData[1].detailData > 100){ + this.src2 = 'common/cloud_red.png'; + this.textColor2 = '#ff0000'; + this.bgColor2 = '#9d7462'; + } else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){ + this.src2 = 'common/cloud_yellow.png'; + this.textColor2 = '#ecf19a'; + this.bgColor2 = '#9d9d62'; + } + if(this.selectedCityIndex){ + this.swiperPage = this.selectedCityIndex; + if(this.swiperPage == 0){ + this.iconcheckedColor = '#ffffff'; + this.iconUncheckedColor = '#262626'; + }else{ + this.iconcheckedColor = '#262626'; + this.iconUncheckedColor = '#ffffff'; + } + } + }, + //跳转到详情页面 + openDetail () { + router.replace({ + uri: 'pages/detail/detail', + params: {selectedCityIndex:this.swiperPage} + }); + }, + //退出应用 + exitApp(){ + console.log('start exit'); + app.terminate(); + console.log('end exit'); + }, + //页面滑动事件,滑动时改变最新的标识 + swiperChange (e) { + this.swiperPage = e.index; + if(e.index == 0){ + this.iconcheckedColor = '#ffffff'; + this.iconUncheckedColor = '#262626'; + }else{ + this.iconcheckedColor = '#262626'; + this.iconUncheckedColor = '#ffffff'; + } + } + } + ``` + + diff --git a/zh-cn/device-dev/guide/device-camera-visual-overview.md b/zh-cn/device-dev/guide/device-camera-visual-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..a7e9895e2dceb1911879973ef697791cc59e649d --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-overview.md @@ -0,0 +1,15 @@ +# 概述 + +- [效果展示](#section3997224182313) + +本文将介绍如何快速搭建基于OpenHarmony系统的行车记录仪(Hi3516DV300开发板)应用开发环境,并基于一个简易的APP示例逐步展示应用的创建、开发、调试和安装等流程。接下来本文以空气质量监测(AirQuality)App为例进行说明。 + +## 效果展示 + +空气质量监测App是一款展示城市空气质量信息的应用,有两个页面组成:首页和详情页,在DevEco Studio模拟器中的显示效果如下图所示: + +**图 1** 空气质量监测 App显示效果图 + + +![](figure/Video_2020-07-25_173141.gif) + diff --git a/zh-cn/device-dev/guide/device-camera-visual-prepare.md b/zh-cn/device-dev/guide/device-camera-visual-prepare.md new file mode 100644 index 0000000000000000000000000000000000000000..55ed7451c0ecdf7d2ab9fd9f896374287a1c5efb --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-prepare.md @@ -0,0 +1,27 @@ +# 开发准备 + +- [准备开发环境](#section1912530122716) +- [创建项目](#section1456035192720) + +## 准备开发环境 + +首先需要下载和配置DevEco Studio,具体操作请参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415)。 + +## 创建项目 + +1. 通过如下两种方式,打开工程创建向导界面。 + - 如果当前未打开任何工程,可以在DevEco Studio的欢迎页,选择**Create HarmonyOS Project**开始创建一个新工程。 + - 如果已经打开了工程,可以在菜单栏选择**File \> New \> New Project**来创建一个新工程。 + +2. 选择“Smart Vision”下的“Empty Feature Ability”模板。 + + ![](figure/zh-cn_image_0000001082434703.png) + +3. 点击**Next**,进入到工程配置阶段,需要根据向导配置工程的基本信息。 + - **Project Name**:工程的名称,可以自定义。 + - **Package Name**:软件包名称,默认情况下,应用ID也会使用该名称,应用发布时,应用ID需要唯一。 + - **Save Location**:工程文件本地存储路径,存储路径中不能包含中文字符和空格。 + - **Compatible API Version**:兼容的SDK版本。 + +4. 点击**Finish**,工具会自动生成示例代码和相关资源,等待工程创建完成。 + diff --git a/zh-cn/device-dev/guide/device-camera-visual-run.md b/zh-cn/device-dev/guide/device-camera-visual-run.md new file mode 100644 index 0000000000000000000000000000000000000000..3e7c3f1d165781cccae6694ca9327357317a6e40 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual-run.md @@ -0,0 +1,29 @@ +# 真机运行 + +应用编译打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[Hi3516快速入门](../quick-start/quickstart-lite-introduction-hi3516.md#section26131214194212)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载三方应用。 + +1. 将IDE编译的未签名应用安装包和安装工具(镜像文件生成目录中的dev\_tools)放在sdcard中,将sdcard插入开发板卡槽。 +2. 应用安装默认要校验签名,需要执行以下命令,关闭签名校验。 + + ``` + ./sdcard/dev_tools/bin/bm set -s disable + ``` + +3. 执行以下命令,安装应用。 + + ``` + ./sdcard/dev_tools/bin/bm install -p /sdcard/airquality.hap + ``` + + 其中dev\_tools目录中是安装工具,airquality.hap为应用安装包,此处替换为实际工程的安装包名称。 + +4. 应用安装完成后,可点击桌面应用图标启动应用,进行操作。 + + **图 1** 桌面 + ![](figure/桌面.png "桌面") + +5. 卸载应用(可选)。 + + 长按桌面应用图标,在弹出的菜单中点击“卸载”按钮即可卸载应用。 + + diff --git a/zh-cn/device-dev/guide/device-camera-visual.md b/zh-cn/device-dev/guide/device-camera-visual.md new file mode 100644 index 0000000000000000000000000000000000000000..ca4e46538b7894fdc3ce840b2b67f185d6e47d29 --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera-visual.md @@ -0,0 +1,19 @@ +# 视觉应用开发 + +- **[概述](device-camera-visual-overview.md)** + +- **[开发准备](device-camera-visual-prepare.md)** + +- **[添加页面](device-camera-visual-addpage.md)** + +- **[开发首页](device-camera-visual-first-page.md)** + +- **[开发详情页](device-camera-visual-details.md)** + +- **[调试打包](device-camera-visual-debug.md)** + +- **[真机运行](device-camera-visual-run.md)** + +- **[常见问题](device-camera-visual-faqs.md)** + + diff --git a/zh-cn/device-dev/guide/device-camera.md b/zh-cn/device-dev/guide/device-camera.md new file mode 100644 index 0000000000000000000000000000000000000000..7239a00d3a42e683c3c015e5e22a3a2dc5a12cec --- /dev/null +++ b/zh-cn/device-dev/guide/device-camera.md @@ -0,0 +1,7 @@ +# 带屏摄像头类产品 + +- **[屏幕和摄像头控制](device-camera-control.md)** + +- **[视觉应用开发](device-camera-visual.md)** + + diff --git a/zh-cn/device-dev/guide/device-clock-guide.md b/zh-cn/device-dev/guide/device-clock-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..a615280a6e27bcf8c37efb75c72ac494e638ad11 --- /dev/null +++ b/zh-cn/device-dev/guide/device-clock-guide.md @@ -0,0 +1,332 @@ +# 时钟应用开发指导 + +- [概述](#section11522349121115) +- [开发准备](#section6592121861218) +- [开发步骤](#section19901741111312) +- [签名打包](#section10601181101516) +- [真机运行](#section092721731511) +- [常见问题](#section1122413460153) + - [hdc\_std连接不到设备](#section1922725151614) + - [hdc\_std运行不了](#section15657547131615) + + +## 概述 + +本文将介绍如何快速搭建基于OpenHarmony标准系统(Hi3516DV300开发板)的应用开发环境,并基于一个时钟APP示例逐步展示应用的创建、开发、调试和安装等流程。示例代码可以通过[本链接](https://gitee.com/openharmony/app_samples/tree/master/common/Clock)获取。 + +时钟App是一款显示实时时间的应用,显示效果如下图所示: + +**图 1** 时钟应用显示效果图 + + +![](figure/Clock.png) + +## 开发准备 + +首先需要下载和配置DevEco Studio,具体操作请参考[DevEco Studio 使用指南](../../application-dev/quick-start/DevEco-Studio(OpenHarmony)使用指南.md)。 + +## 开发步骤 + +应用的功能是通过表盘和数字显示实时时间。 + +从[显示效果图](device-clock-guide.md#fig7763172132019)分析可知,页面由两个部分组成: + +- 表盘栏:主要展示一个动态的钟表,且钟表指针能准确转动。 +- 数字时间栏:主要以数字形式显示当前时间。 + +综上,我们可搭建一个纵向两行排列的弹性页面布局来实现界面的功能。具体开发步骤如下: + +1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: + + ``` +
+
+ ``` + + class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: + + ``` + .container { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + } + ``` + + 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向两行排列的弹性页面布局。 + +2. 实现时钟转动,需要使用“stack”组件。“stack”组件的功能是堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。 + + 在根组件下添加一个stack容器,代码片段如下: + + ``` +
+ + + + + + +
+ ``` + + style="transform : rotate\(\{\{ second \* 6 \}\}deg\) 这类代码用来设置组件的旋转事件。其中transform是设置动画平移/旋转/缩放的属性,rotate是旋转动画属性,支持设置x轴和y轴两个维度的选中参数。 + + 在css文件中设置"stack"组件样式的高度、宽度、位置等属性,代码如下: + + ``` + .stack { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 50%; + } + ``` + + 在css文件中设置"clock-bg"组件样式的高度、宽度等属性,代码如下: + + ``` + .clock-bg { + width: 80%; + height: 80%; + object-fit: scale-down; + } + ``` + + 在css文件中设置"clock-hand"组件为时针、分针和秒针的高度、宽度等属性,代码如下: + + ``` + .clock-hand { + width: 25%; + height: 65%; + object-fit: contain; + } + ``` + + index.js中会有一个定时器实时刷新时分秒变量,从而触发时间界面自动更新。对应的js代码如下: + + ``` + export default { + timer: undefined, + //定义参数 + data: { + hour: 0, //定义小时 + minute: 0, //定义分钟 + second: 0 //定义秒 + }, + onInit () { + this.updateTime(); + this.timer = setInterval(this.updateTime, 1000)//设置1s的定时器 + }, + updateTime: function () { + var nowTime = new Date() + this.hour = nowTime.getHours() + this.minute = nowTime.getMinutes() + this.second = nowTime.getSeconds() + if (this.hour < 10) { + this.hour = '0' + this.hour + } + if (this.minute < 10) { + this.minute = '0' + this.minute + } + if (this.second < 10) { + this.second = '0' + this.second + } + }, + } + ``` + +3. 显示数字时间,在钟表下面以数字形式显示当前时间。在根布局内末尾加上text组件,页面结构如下: + + ``` + {{ hour }}:{{ minute }}:{{ second }} + ``` + + class="digit-clock"设置了组件的高度和宽度以及字体大小,其代码如下: + + ``` + .digit-clock { + font-size: 58px; + width: 100%; + margin-top: 0px; + text-align: center; + } + ``` + +4. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: + - **index.hml文件** + + ``` +
+ + + + + + + {{ hour }}:{{ minute }}:{{ second }} +
+ ``` + + + - **index.css文件** + + ``` + .container { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 100%; + } + + .stack { + flex-direction: column; + justify-content: center; + align-items: center; + width: 100%; + height: 50%; + } + + .digit-clock { + font-size: 58px; + width: 100%; + margin-top: 0px; + text-align: center; + } + + .clock-bg { + width: 80%; + height: 80%; + object-fit: scale-down; + } + + .clock-hand { + width: 25%; + height: 65%; + object-fit: contain; + } + ``` + + + - **index.js:** + + js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:定时获取系统时间。 + + ``` + export default { + timer: undefined, + data: { + hour: 0, + minute: 0, + second: 0 + }, + onInit() { + this.updateTime() + this.timer = setInterval(this.updateTime, 1000) + }, + updateTime: function () { + var nowTime = new Date() + this.hour = nowTime.getHours() + this.minute = nowTime.getMinutes() + this.second = nowTime.getSeconds() + if (this.hour < 10) { + this.hour = '0' + this.hour + } + if (this.minute < 10) { + this.minute = '0' + this.minute + } + if (this.second < 10) { + this.second = '0' + this.second + } + }, + onDestroy() { + clearInterval(this.timer); + } + } + ``` + + + +## 签名打包 + +代码编写完成后,在真机设备上运行应用,需要先对应用进行签名,然后再进行打包,具体操作请参考[签名打包指导](../../application-dev/quick-start/配置OpenHarmony应用签名信息.md)。 + +## 真机运行 + +应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/quickstart-standard.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。 + +1. 从开发者工具代码仓路径中获取hdc客户端。 + + ``` + developtools/hdc_standard/prebuilt/windows/hdc_std.exe + ``` + + 修改名称为hdc.exe,并将工具路径加入系统环境path变量中。 + +2. 启动cmd命令窗口,执行以下命令,推送hap应用包到设备目录下并安装。 + + ``` + hdc smode + hdc target mount + hdc file send clock.hap /data/clock.hap + hdc shell chmod 666 /data/clock.hap + hdc shell bm install -p /data/clock.hap + ``` + +3. 启动应用。执行以下命令,其中ohos.samples.clock为应用包名,MainAbility为应用启动的Ability。 + + ``` + hdc shell aa start -d 123 -a ohos.samples.clock.MainAbility -b ohos.samples.clock + ``` + +4. 卸载应用(可选)。执行以下命令,其中ohos.samples.clock为应用包名。 + + ``` + hdc shell bm uninstall -n ohos.samples.clock + ``` + + +## 常见问题 + +### hdc\_std连接不到设备 + +- **现象描述** + + 执行 "hdc\_std list targets"命令后结果为:\[Empty\] + +- **可能原因和解决方法** + 1. 设备没有被识别: + + 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 + + 2. hdc\_std工作异常: + + 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 + + 3. hdc\_std与设备不匹配: + + 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 + + + +### hdc\_std运行不了 + +- **现象描述** + + 点击hdc\_std.exe文件无法运行。 + +- **可能原因和解决方法** + + hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 + + diff --git a/zh-cn/device-dev/guide/device-drive-demo.md b/zh-cn/device-dev/guide/device-drive-demo.md new file mode 100644 index 0000000000000000000000000000000000000000..bb103f846c199d497d95cf1c570a17ccdac281f6 --- /dev/null +++ b/zh-cn/device-dev/guide/device-drive-demo.md @@ -0,0 +1,453 @@ +# 平台驱动开发示例 + +- [概述](#section194201316174215) +- [环境准备](#section6926133918422) +- [开发](#section65801539470) + - [文件说明](#section0708184454414) + - [实例化驱动入口](#section85325864412) + - [设置相关参数](#section8155172019453) + - [添加控制器](#section1335374114452) + +- [编译及烧录](#section164824754712) + +## 概述 + +本文档将以I2C驱动为例,介绍如何基于HDF驱动框架完成平台驱动开发。 + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>本例仅作为平台驱动开发示例参考,开发者不可直接用于商用集成。 + +HDF驱动框架为常用外围设备提供了标准的驱动框架,驱动开发者只需将驱动适配至HDF驱动框架,即可通过HDF驱动框架提供的接口操作外围设备。 + +本文以I2C为例。其时序流程如[图1](#fig148041484161)所示。 + +**图 1** I2C时序流程图 + + +![](figure/zh-cn_image_0000001169991055.png) + +- User Business:用户业务驱动。 +- i2cManagerEntry:I2C管理器入口,注册I2cManager到HDF驱动框架。 +- I2cManager:I2C管理器,管理I2C控制器。 +- I2cCntlr:I2C控制器。 +- i2cDriverEntry:I2C控制器入口,注册I2cCntlr到HDF驱动框架。 + +## 环境准备 + +环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/quickstart-standard.md)。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 + +## 开发 + +### 文件说明 + +本例中涉及的文件及路径如下表: + +**表 1** 文件说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

说明

+

文件路径

+

操作

+

示例文件

+

/drivers/adapter/khdf/linux/platform/i2c/i2c_sample.c

+

新增文件

+

设备服务文件

+

/drivers/adapter/khdf/linux/hcs/device_info/device_info.hcs

+

+

追加内容

+

+

配置参数文件

+

/drivers/adapter/khdf/linux/hcs/platform/i2c_config.hcs

+

编译文件

+

/drivers/adapter/khdf/linux/platform/i2c/Makefile

+

依赖头文件

+

/drivers/framework/include/core/hdf_device_desc.h

+

作为头文件引用

+

+

核心层头文件

+

/drivers/framework/support/platform/include/i2c_core.h

+

HCS配置入口文件

+

/drivers/adapter/khdf/linux/hcs/hdf.hcs

+

HCS配置文件总入口

+
+ +>![](../public_sys-resources/icon-caution.gif) **注意:** +>本例程涉及的文件路径均作为演示,驱动开发者应根据实际情况确定具体的源文件存放位置。 + +### 实例化驱动入口 + +实例化一个HdfDriverEntry 对象作为驱动入口。驱动入口必须为HdfDriverEntry(在hdf\_device\_desc.h中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 + +I2C驱动中没有实现Bind方法,因为I2C控制器由manager管理,而在manager中已经实现了Bind方法,因此I2C驱动中无需再绑定服务。 + +实例化驱动入口的示例代码如下: + +``` +/* 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 */ +struct HdfDriverEntry g_sampleI2cDriverEntry = { + .moduleVersion = 1, + .Init = SampleI2cInit, + .Release = SampleI2cRelease, + .moduleName = "demo_i2c_driver", +}; +/* 调用HDF_INIT将驱动入口注册到HDF框架中 */ +HDF_INIT(g_sampleI2cDriverEntry); +``` + +### 设置相关参数 + +通过配置device\_info.hcs,并从HCS获取并解析设备的配置参数以确保驱动能够正确加载。 + +1. 添加设备服务节点(必选)。 + + 编辑device\_info.hcs,在device\_i2c :: device下添加驱动设备服务节点,示例如下: + + ``` + root { + device_info { + match_attr = "hdf_manager"; + device_i2c :: device { // i2c设备节点 + device2 :: deviceNode { // i2c驱动的DeviceNode节点 + policy = 0; // policy字段是驱动服务发布的策略 + priority = 55; // 驱动启动优先级 + permission = 0644; // 驱动创建设备节点权限 + moduleName = "demo_i2c_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 + serviceName = "DEMO_I2C_DRIVER"; // 驱动对外发布服务的名称,必须唯一 + deviceMatchAttr = "demo_i2c_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的 + // match_attr值相等 + } + } + } + } + + ``` + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高,驱动的priority值相同则不保证加载顺序。 + +2. 添加配置参数(可选)。 + + 有时驱动可能会需要私有配置信息,以确保寄存器的配置可以满足不同产品的需求。如需要私有配置信息,则可以添加一个驱动的配置文件,用来存放一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](../driver/drive-hdf-development.md))传递给驱动。驱动开发者可新建配置文件,并在板级驱动hdf.hcs中引用新建的配置文件,本例中直接在原有的配置文件i2c\_config.hcs内添加配置参数。 + + 本例中编辑i2c\_config.hcs,添加配置参数: + + ``` + root { + platform { + i2c_config_demo { + match_attr = "demo_i2c_config"; // 该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 + + template i2c_controller { // 参数模板 + bus = 0; + reg_pbase = 0x120b0000; + reg_size = 0xd1; + } + + controller_demo_0 :: i2c_controller { // 两个I2C示例控制器 + bus = 8; + } + controller_demo_1 :: i2c_controller { + bus = 9; + } + } + } + } + ``` + + match\_attr字段必须与device\_info.hcs中的deviceMatch\_Attr保持一致,在此文件中配置驱动需要的参数,通过match\_attr可匹配至对应的驱动,该驱动即可在Bind或Init中调用DeviceResourceGetIfaceInstance\(\)函数获取这些配置参数。 + + 若配置文件为新文件,则需要在板级配置入口文件hdf.hcs中引用该配置文件,例如: + + ``` + #include "device_info/device_info.hcs" + #include "i2c/i2c_config.hcs" + ``` + + 由于本例中在原有的i2c\_config.hcs内添加配置参数,没有新建配置文件,因此无需再将i2c\_config.hcs添加至板级配置入口文件中。 + +3. 驱动从HCS获取配置参数。 + + 在本例中,驱动需要通过HCS获取寄存器物理基地址、寄存器大小、总线号等参数,从而对控制器进行正确配置。 + + ``` + /* 从HCS获取配置参数 */ + static int32_t SampleI2cReadDrs(struct SampleI2cCntlr *sampleCntlr, const struct DeviceResourceNode *node) + { + int32_t ret; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { // 确保GetUint32方法可用 + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return HDF_FAILURE; + } + + ret = drsOps->GetUint32(node, "reg_pbase", &sampleCntlr->regBasePhy, 0); // 从HCS读取物理基地址reg_pbase + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regBase fail!", __func__); + return ret; + } + + ret = drsOps->GetUint16(node, "reg_size", &sampleCntlr->regSize, 0); // 从HCS读取寄存器大小reg_size + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read regsize fail!", __func__); + return ret; + } + + ret = drsOps->GetUint16(node, "bus", (uint16_t *)&sampleCntlr->bus, 0); // 从HCS读取总线号bus + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read bus fail!", __func__); + return ret; + } + + return HDF_SUCCESS; + } + ``` + + +### 添加控制器 + +初始化控制器硬件,并调用核心层接口完成向核心层添加、删除设备,以及钩子函数的实现等。 + +1. 定义结构体,实现钩子函数并赋值至函数指针。 + + I2cMethod结构体在i2c\_core.h中定义,其中通过函数指针的方式定义了I2C需要实现的方法,transfer方法为用于传输的钩子函数,在驱动中需要做具体实现并对函数指针赋值。 + + 示例代码如下: + + ``` + /* 自定义设备结构体,继承父类I2cCntlr */ + struct SampleI2cCntlr { + struct I2cCntlr cntlr; + OsalSpinlock spin; + volatile unsigned char *regBase; + uint16_t regSize; + int16_t bus; + uint32_t regBasePhy; + }; + + /* 消息结构体,继承父类I2cMsg */ + struct SampleTransferData { + struct I2cMsg *msgs; + int16_t index; + int16_t count; + }; + /* 钩子函数实现 */ + static int32_t SampleI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) + { + int32_t ret = HDF_SUCCESS; + struct SampleI2cCntlr *sampleCntlr = NULL; + struct SampleTransferData td; + + if (cntlr == NULL || cntlr->priv == NULL) { + HDF_LOGE("SampleI2cTransfer: cntlr lor sampleCntlr is null!"); + return HDF_ERR_INVALID_OBJECT; + } + sampleCntlr = (struct SampleI2cCntlr *)cntlr; + + if (msgs == NULL || count <= 0) { + HDF_LOGE("SampleI2cTransfer: err parms! count:%d", count); + return HDF_ERR_INVALID_PARAM; + } + td.msgs = msgs; + td.count = count; + td.index = 0; + + HDF_LOGE("Successfully transmitted!"); // 表示此处传输成功 + + td.index = count; // 经过处理,最后实际发送msg个数等于count,返回已发送个数,此句代替已省略的处理过程 + return (td.index > 0) ? td.index : ret; + } + /* 钩子函数赋值 */ + static struct I2cMethod g_method = { + .transfer = SampleI2cTransfer, + }; + ``` + +2. 编写驱动初始化函数。 + + 本例中使用SampleI2cInit作为驱动初始化函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Init,以供HDF驱动框架调用从而达到初始化驱动的目的。该函数中需要对从HCS获取的配置参数进行解析,并按照这些参数创建控制器。示例如下: + + ``` + /* 解析参数,申请内存并创建控制器 */ + static int32_t SampleI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) + { + int32_t ret; + struct SampleI2cCntlr *sampleCntlr = NULL; + (void)device; + + sampleCntlr = (struct SampleI2cCntlr *)OsalMemCalloc(sizeof(*sampleCntlr)); + if (sampleCntlr == NULL) { + HDF_LOGE("%s: malloc sampleCntlr fail!", __func__); + return HDF_ERR_MALLOC_FAIL; + } + + ret = SampleI2cReadDrs(sampleCntlr, node); // 从HCS获取配置参数 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret); + goto __ERR__; + } + + sampleCntlr->regBase = OsalIoRemap(sampleCntlr->regBasePhy, sampleCntlr->regSize); + if (sampleCntlr->regBase == NULL) { + HDF_LOGE("%s: ioremap regBase fail!", __func__); + ret = HDF_ERR_IO; + goto __ERR__; + } + + HDF_LOGE("The controller has been initialized!"); // 表示此处省略的控制器初始化操作已经成功 + + sampleCntlr->cntlr.priv = (void *)node; + sampleCntlr->cntlr.busId = sampleCntlr->bus; + sampleCntlr->cntlr.ops = &g_method; + (void)OsalSpinInit(&sampleCntlr->spin); // 初始化自旋锁 + ret = I2cCntlrAdd(&sampleCntlr->cntlr); // 向核心层添加控制器 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret); + goto __ERR__; + } + + return HDF_SUCCESS; + __ERR__: // 错误处理 + if (sampleCntlr != NULL) { + if (sampleCntlr->regBase != NULL) { + OsalIoUnmap((void *)sampleCntlr->regBase); // 取消地址映射 + sampleCntlr->regBase = NULL; + } + OsalMemFree(sampleCntlr); // 释放内存 + sampleCntlr = NULL; + } + return ret; + } + /* 驱动入口初始化函数 */ + static int32_t SampleI2cInit(struct HdfDeviceObject *device) + { + int32_t ret; + const struct DeviceResourceNode *childNode = NULL; + + HDF_LOGE("%s: Enter", __func__); + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + + ret = HDF_SUCCESS; + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + ret = SampleI2cParseAndInit(device, childNode); // 调用解析参数和创建控制器的函数 + if (ret != HDF_SUCCESS) { + break; + } + } + return ret; + } + ``` + +3. 编写驱动释放函数。 + + 本例中使用SampleI2cRelease作为驱动释放函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,将调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。示例如下: + + ``` + /* 删除控制器函数 */ + static void SampleI2cRemoveByNode(const struct DeviceResourceNode *node) + { + int32_t ret; + int16_t bus; + struct I2cCntlr *cntlr = NULL; + struct SampleI2cCntlr *sampleCntlr = NULL; + struct DeviceResourceIface *drsOps = NULL; + + drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (drsOps == NULL || drsOps->GetUint32 == NULL) { + HDF_LOGE("%s: invalid drs ops fail!", __func__); + return; + } + + ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0); // 从HCS获取I2C总线号 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: read bus fail!", __func__); + return; + } + + cntlr = I2cCntlrGet(bus); + if (cntlr != NULL && cntlr->priv == node) { // 根据I2C总线号删除控制器 + I2cCntlrPut(cntlr); + I2cCntlrRemove(cntlr); + sampleCntlr = (struct SampleI2cCntlr *)cntlr; + OsalIoUnmap((void *)sampleCntlr->regBase); + OsalMemFree(sampleCntlr); + } + return; + } + /* 释放资源 */ + static void SampleI2cRelease(struct HdfDeviceObject *device) + { + const struct DeviceResourceNode *childNode = NULL; + + HDF_LOGI("%s: enter", __func__); + + if (device == NULL || device->property == NULL) { + HDF_LOGE("%s: device or property is NULL", __func__); + return; + } + + DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { + SampleI2cRemoveByNode(childNode); // 调用删除控制器函数 + } + } + ``` + + +## 编译及烧录 + +1. 编辑Makefile,添加源文件: + + ``` + include drivers/hdf/khdf/platform/platform.mk + + obj-y += $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_core.o \ + $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_if.o \ + ./i2c_adapter.o \ + ./i2c_sample.o + ``` + + "./i2c\_sample.o"为本示例中在Makefile中追加的内容。 + +2. 编译及烧录。 + + 具体操作请参考[标准系统快速入门编译及烧录章节](../quick-start/quickstart-standard.md)。 + + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md b/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md new file mode 100644 index 0000000000000000000000000000000000000000..31edc27814baddb754614c87ca0225979ef408ff --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-demo-photodevguide.md @@ -0,0 +1,396 @@ +# 拍照开发指导 + +- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) +- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) +- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) +- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) + +## 使用场景 + +使用Camera产生图片帧(拍照)。 + +## 接口说明 + +**表 1** API列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

类名

+

接口名

+

描述

+

CameraKit

+

int32_t GetCameraIds(std::list<string> cameraList)

+

获取cameraId列表

+

CameraKit

+

CameraAbility& GetCameraAbility(string cameraId)

+

获取指定camera的能力

+

CameraKit

+

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

+

注册camera设备状态回调

+

CameraKit

+

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

+

去注册camera设备状态回调

+

CameraKit

+

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

+

创建camera实例

+

Camera

+

string GetCameraId()

+

获取cameraID

+

Camera

+

CameraConfig& GetCameraConfig()

+

获取camera配置信息

+

Camera

+

FrameConfig& GetFrameConfig(int32_t type)

+

获取捕获帧类型

+

Camera

+

void Configure(CameraConfig& config)

+

配置camera

+

Camera

+

void Release()

+

释放camera

+

Camera

+

int TriggerLoopingCapture(FrameConfig& frameConfig)

+

开始循环帧捕获

+

Camera

+

void StopLoopingCapture()

+

停止循环帧捕获

+

Camera

+

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

+

抓图

+

CameraConfig

+

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

+

设置帧状态回调

+

CameraConfig

+

static CameraConfig* CreateCameraConfig()

+

创建camera配置信息实例

+

CameraAbility

+

std::list<Size> GetSupportedSizes(int format)

+

根据类型获取支持输出图像尺寸大小

+

CameraAbility

+

std::list<T> GetParameterRange(uint32_t key)

+

获取支持的参数范围

+

CameraDevice

+

CameraDeviceCallback()

+

camera设备回调类构造函数

+

CameraDevice

+

void OnCameraStatus​(std::string cameraId, int32_t status)

+

camera设备状态变化时的回调

+

CameraStateCallback

+

CameraStateCallback​()

+

camera状态回调类构造函数

+

CameraStateCallback

+

void OnConfigured​(Camera& camera)

+

camera配置成功回调

+

CameraStateCallback

+

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

+

camera配置失败回调

+

CameraStateCallback

+

void OnCreated​(Camera& camera)

+

camera创建成功回调

+

CameraStateCallback

+

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

+

camera创建失败回调

+

CameraStateCallback

+

void OnReleased​(Camera& camera)

+

camera释放回调

+

FrameStateCallback

+

FrameStateCallback​()

+

帧状态回调类构造函数

+

FrameStateCallback

+

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

+

拍照帧完成回调

+

FrameStateCallback

+

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

+

拍照帧异常回调

+

FrameConfig

+

int32_t GetFrameConfigType()

+

获取帧配置类型

+

FrameConfig

+

std::list<OHOS::Surface> GetSurfaces()

+

获取帧配置的surface

+

FrameConfig

+

void AddSurface(OHOS::AGP::UISurface& surface);

+

添加surface

+

FrameConfig

+

void RemoveSurface(OHOS::AGP::UISurface& surface);

+

删除surface

+
+ +## 约束与限制 + +无。 + +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + camKit->CreateCamera(camId, CamStateMng, eventHdlr); + ``` + +6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` + + diff --git "a/zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/guide/device-iotcamera-control-demo-videodevguide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/guide/device-iotcamera-control-demo-videodevguide.md diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-demo.md b/zh-cn/device-dev/guide/device-iotcamera-control-demo.md new file mode 100644 index 0000000000000000000000000000000000000000..26be96c626e2e70310352f98858114ba071b1bae --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-demo.md @@ -0,0 +1,7 @@ +# 示例开发 + +- **[拍照开发指导](device-iotcamera-control-demo-photodevguide.md)** + +- **[录像开发指导](device-iotcamera-control-demo-videodevguide.md)** + + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-example.md b/zh-cn/device-dev/guide/device-iotcamera-control-example.md new file mode 100644 index 0000000000000000000000000000000000000000..8f7e480ded6a00d4f830b0bde6413d9412cf7e2d --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-example.md @@ -0,0 +1,45 @@ +# 应用实例 + +- 开发板介绍、编译烧录、运行镜像等操作请参考[Hi3518快速入门](../quick-start/quickstart-lite-introduction-hi3518.md#section14815247616),编译结果包含示例,结果文件为out/ipcamera\_hi3518ev300/dev\_tools/bin/camera\_sample,可将文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 + + 修改applications/sample/camera/media/BUILD.gn中的output\_dir。 + + - 修改前:output\_dir = "$root\_out\_dir/dev\_tools" + - 修改后:output\_dir = "$root\_out\_dir/" + + 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 + +- 相机示例代码为applications/sample/camera/media/camera\_sample.cpp。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后时自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 + + +1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 + + **图 1** 启动示例 + ![](figure/启动示例.png "启动示例") + + 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 + +2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* + + **图 2** 输入拍照指令后串口打印日志 + ![](figure/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") + + 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 + + **图 3** 查看文件图 + ![](figure/查看文件图.png "查看文件图") + +3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 + + **图 4** 输入录像指令后串口打印日志 + ![](figure/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") + +4. 按q键退出 + + **图 5** 输出退出指令后串口打印日志 + ![](figure/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") + + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control-overview.md b/zh-cn/device-dev/guide/device-iotcamera-control-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..03fef3f55e4efd17bb96166a158e592c0f1316f5 --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control-overview.md @@ -0,0 +1,10 @@ +# 概述 + +本文档将介绍如何基于IoT Camera开发板,利用开发套件中自带的摄像头,完成拍照、录像功能。 + +开发者可通过执行示例应用,对开发板的外设控制有了更深入了解后,可使用开发板完成摄像头等设备。 + +若开发者想先查看示例效果,请进入[应用实例](device-iotcamera-control-example.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 + +相机开发基本概念可参考:[相机开发概述](../subsystems/subsys-multimedia-camera-overview.md)。 + diff --git a/zh-cn/device-dev/guide/device-iotcamera-control.md b/zh-cn/device-dev/guide/device-iotcamera-control.md new file mode 100644 index 0000000000000000000000000000000000000000..776d324bf5be97b63ce546443cc3cf5ebdd08a71 --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera-control.md @@ -0,0 +1,9 @@ +# 摄像头控制 + +- **[概述](device-iotcamera-control-overview.md)** + +- **[示例开发](device-iotcamera-control-demo.md)** + +- **[应用实例](device-iotcamera-control-example.md)** + + diff --git a/zh-cn/device-dev/guide/device-iotcamera.md b/zh-cn/device-dev/guide/device-iotcamera.md new file mode 100644 index 0000000000000000000000000000000000000000..4823d578306a683d5db28277ac38be5410051e8e --- /dev/null +++ b/zh-cn/device-dev/guide/device-iotcamera.md @@ -0,0 +1,5 @@ +# 无屏摄像头类产品 + +- **[摄像头控制](device-iotcamera-control.md)** + + diff --git a/zh-cn/device-dev/guide/device-outerdrive-demo.md b/zh-cn/device-dev/guide/device-outerdrive-demo.md new file mode 100644 index 0000000000000000000000000000000000000000..afeffb7863a892e6babfcf26f147a54b870a42f2 --- /dev/null +++ b/zh-cn/device-dev/guide/device-outerdrive-demo.md @@ -0,0 +1,483 @@ +# 外设驱动开发示例 + +- [概述](#section86753818426) + - [硬件资源简介](#section123071189431) + - [Input模型简介](#section53684425430) + +- [环境搭建](#section661075474418) +- [TouchScreen器件驱动开发](#section15233162984520) + - [配置设备描述信息](#section16761205604515) + - [配置Touchscreen器件信息](#section156331030144617) + - [适配器件私有驱动](#section17127331595) + +- [编译及烧录](#section16465031164711) +- [调试验证](#section62577313482) +- [Input模型工作流程解析](#section1578569154917) + - [私有配置信息解析](#section1310113815495) + - [管理驱动层初始化及注册驱动至HDF框架](#section614512119500) + - [公共驱动层初始化及注册驱动至HDF框架](#section16194201755019) + - [器件驱动层初始化及注册驱动至HDF框架](#section1090743312505) + - [具体调用逻辑串联函数](#section81801147529) + + +## 概述 + +本文档将介绍如何基于Hi3516DV300开发板完成基于HDF\_Input模型的触摸屏器件驱动开发,从而使开发者快速入门,进行基于的外设驱动开发。 + +### 硬件资源简介 + +Hi3516DV300开发板套件所提供的触摸屏器件IC为GT911,该器件采用标准I2C与主机通信,通过6pin软排线与主板连接。6pin分布以及实物连接图如下图所示: + +![](figure/绘图1.png) + +### Input模型简介 + +Input驱动模型核心部分由设备管理层、公共驱动层、器件驱动层组成。其中: + +- 设备管理层:主要为各类输入设备驱动提供input设备的注册、注销接口,同时统一管理input设备列表; +- 公共驱动层:负责对板级硬件进行初始化、硬件中断处理、向manager注册input设备等; +- 器件驱动层:通过适配平台驱动预留的差异化接口,实现器件驱动开发量最小化; + +此外,Input模型预先实现了数据通道以及设备配置信息解析等函数。 + +关于Input模型的详细介绍请参考《[Touchscreen开发概述](../driver/drive-peripherals-touch-des.md#section175431838101617)》。 + +## 环境搭建 + +环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/quickstart-standard.md)。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 + +## TouchScreen器件驱动开发 + +基于Input模型适配一款触摸屏IC需要完成的具体工作见下。 + +### 配置设备描述信息 + +驱动注册到HDF框架所需要的设备驱动描述信息,如驱动是否加载以及加载次序等。 + +配置文件路径:./drivers/adapter/khdf/linux/hcs/device\_info/device\_info.hcs + +device\_info.hcs中的信息主要提供给HDF框架使用,包含了Input模型各层驱动注册到HDF框架所必需的信息,开发者无特殊场景需求无需改动。各驱动层私有配置信息通过“deviceMatchAttr”字段与input\_config.hcs中的“match\_attr”相关内容进行匹配。 + +配置文件中与input模块相关的内容如下所示,相关字段的详细含义可以参考《[驱动配置](../driver/drive-hdf-development.md)》: + +``` +input :: host { + hostName = "input_host"; + priority = 100; + device_input_manager :: device { // Input管理层设备描述信息 + device0 :: deviceNode { + policy = 2; // 向内核用户态均发布服务 + priority = 100; // input管理层驱动优先级默认为100 + preload = 0; // 加载该驱动 + permission = 0660; // 驱动创建设备节点权限 + moduleName = "HDF_INPUT_MANAGER"; // 与驱动入口的moduleName匹配 + serviceName = "hdf_input_host"; // HDF框架生成的节点名 + deviceMatchAttr = ""; // manager目前不需要私有配置,因此为空 + } + } + + device_hdf_touch :: device { // Input公共驱动层设备描述信息 + device0 :: deviceNode { + policy = 2; // 向内核用户态均发布服务 + priority = 120; // input公共驱动优先级默认为120 + preload = 0; // 加载该驱动 + permission = 0660; // 驱动创建设备节点权限 + moduleName = "HDF_TOUCH"; // 与驱动入口的moduleName匹配 + serviceName = "hdf_input_event1"; // HDF框架生成的节点名 + deviceMatchAttr = "touch_device1"; // 与私有配置信息中的“match_attr”字段保持一致 + } + } + + device_touch_chip :: device { // Input器件驱动层信息 + device0 :: deviceNode { + policy = 0; // 向内核用户态均不发布服务 + priority = 130; // input器件驱动优先级默认为130 + preload = 0; // 加载该驱动 + permission = 0660; // 驱动创建设备节点权限 + moduleName = "HDF_TOUCH_GT911"; // 与驱动入口的moduleName匹配 + serviceName = "hdf_touch_gt911_service";// HDF框架生成的节点名 + deviceMatchAttr = "zsj_gt911_5p5"; //与私有配置信息中的“match_attr”字段保持一致 + } + } + } +``` + +该配置文件中需要重点关注的字段有: + +“priority”决定驱动加载顺序; + +“preload”决定驱动是否加载; + +“moduleName ”需要与驱动注册入口处的“moduleName ”字段保持一致; + +“serviceName ”HDF框架依据该字段创建节点名; + +“deviceMatchAttr ”需要与私有配置信息中的“match\_attr”字段保持一致。 + +通过配置设备描述信息,使得HDF框架通过moduleName与注册至驱动入口的代码相匹配,保证了驱动的正常加载,通过priority字段保证了各驱动的加载顺序。 + +### 配置Touchscreen器件信息 + +器件私有信息包括上下电时序等,平台硬件信息包括器件连接主板的GPIO端口信息等。 + +配置文件路径:./drivers/adapter/khdf/linux/hcs/input/input\_config.hcs + +input\_config.hcs中的信息由驱动代码进行读取解析,主要由公共驱动层的私有配置信息及器件驱动层的私有配置信息组成。文件中的配置包含板级硬件信息及器件私有配置信息,实际业务开发时,可根据具体需求增删及修改对应内容。 + +``` +root { + input_config { + touchConfig { + touch0 { // 第一款触摸屏 + boardConfig { // 板级硬件信息 + match_attr = "touch_device1"; // 与设备描述配置信息中公共驱动层私有配置信息的“match_attr”字段保持一致 + inputAttr { + /* 0:touch 1:key 2:keyboard 3:mouse 4:button 5:crown 6:encoder */ + inputType = 0; // input类型为touch + solutionX = 480; // 分辨率X信息 + solutionY = 960; // 分辨率Y信息 + devName = "main_touch"; // 设备名称 + } + busConfig { + /* 0:i2c 1:spi */ + busType = 0; // GT911采用I2C通信 + busNum = 6; // 与主机芯片第6路I2C通信 + clkGpio = 86; // 主机芯片SCL管脚 + dataGpio = 87; // 主机芯片SDA管脚 + i2cClkIomux = [0x114f0048, 0x403]; // SCL管脚配置信息 + i2cDataIomux = [0x114f004c, 0x403]; // SDA管脚配置信息 + } + pinConfig { + rstGpio = 3; // 复位管脚连接主机芯片的3号管脚 + intGpio = 4; // 中断管脚连接主机芯片的4号管脚 + rstRegCfg = [0x112f0094, 0x400]; // 复位管脚配置信息 + intRegCfg = [0x112f0098, 0x400]; // 中断管脚配置信息 + } + powerConfig { + /* 0:unused 1:ldo 2:gpio 3:pmic */ + vccType = 2; // GPIO供电 + vccNum = 20; // gpio20 + vccValue = 1800; // 电压幅值为1800mV + vciType = 1; // LDO供电 + vciNum = 12; // ldo12 + vciValue = 3300; // 电压幅值为3300mV + } + + featureConfig { + capacitanceTest = 0; // 容值测试 + gestureMode = 0; // 手势模式 + gloverMode = 0; // 手套模式 + coverMode = 0; // 皮套模式 + chargerMode = 0; // 充电模式 + knuckleMode = 0; // 指关节模式 + } + } + chipConfig { // 器件私有信息配置 + template touchChip { // 模板 + match_attr = ""; + chipName = "gt911"; // 触摸屏IC型号 + vendorName = "zsj"; // 供应商 + chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 + busType = 0; // 0代表I2C,1代表SPI + deviceAddr = 0x5D; // 器件IC通信地址 + irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 + maxSpeed = 400; // 最大通信速率为400Hz + chipVersion = 0; // 触摸屏IC版本号 + powerSequence { + /* 上电时序的配置含义说明: + [类型, 状态, 方向 , 延时] + 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 + 0代表下电或拉低,1代表上电或拉高,2代表无操作 + 0代表输入方向,1代表输出方向,2代表无操作 + 代表延时多少毫秒, 例如20代表延时20ms + */ + powerOnSeq = [4, 0, 1, 0, // 中断管脚配置为输出,且进行拉低 + 3, 0, 1, 10, // 复位管脚配置为输出,且进行拉低,延时10ms + 3, 1, 2, 60, // 复位管脚无操作,且进行拉高,延时60ms + 4, 2, 0, 0]; // 中断管脚配置为输入 + suspendSeq = [3, 0, 2, 10]; // 复位管脚无操作,且进行拉低,延时10ms + resumeSeq = [3, 1, 2, 10]; // 复位管脚无操作,且进行拉高,延时10ms + powerOffSeq = [3, 0, 2, 10, // 复位管脚无操作,且进行拉低,延时10ms + 1, 0, 2, 20]; // 电源正极管脚无操作,且进行拉低,延时20ms + } + } + + chip0 :: touchChip { + match_attr = "zsj_gt911_5p5"; // 与设备描述配置信息中器件私有配置信息的“match_attr”字段保持一致 + chipInfo = "ZIDN45100"; // 产品名+模组编号+芯片编号的组合信息 用于给用户态区分当前器件 + chipVersion = 0; // IC型号的版本 + } + } + } + } + } +} +``` + +示例中“touchConfig”包含了“touch0”,"touch0"包含了“boardConfig”与“chipConfig”;“boardConfig”字段包含了Hi3516DV300板级硬件信息,“chipConfig”包含了触摸屏器件的私有信息,如果需要替换触摸屏器件,重新配置“chipConfig”对应的字段信息即可。同时产品可以配置多款触摸屏,示例中用“touch0”代表了套件中默认的触摸屏的硬件接口以及器件的配置信息,如产品需要配置副屏,可在与“touch0”并列的位置配置“touch1”的信息。 + +### 适配器件私有驱动 + +Input模型对Input设备开发流程进行了抽象,开发者只需要适配器件驱动层,无需改动管理驱动层以及公共驱动层。 + +Input模型由三层驱动组成,开发者适配一款全新触摸屏驱动只需要适配器件驱动层即可,重点实现差异化接口,本小节以代码示例的形式展示开发者需要重点完成的工作。 + +1. 触摸屏器件差异化接口适配 + + 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c + + ``` + static struct TouchChipOps g_gt911ChipOps = { // 器件IC接口 + .Init = ChipInit, // 初始化 + .Detect = ChipDetect, // 器件检测 + .Resume = ChipResume, // 唤醒 + .Suspend = ChipSuspend, // 休眠 + .DataHandle = ChipDataHandle, // 器件数据读取 + .UpdateFirmware = UpdateFirmware, // 固件升级 + }; + + /* 不同触摸屏厂家使用的IC不一样,对应的寄存器操作也不一样,因此器件驱动层代码重点适配差异化接口部分,如下示例代码展示了GT911的数据解析*/ + + static int32_t ChipDataHandle(ChipDevice *device) + { + ... + /* GT911获取坐标之前需先读取状态寄存器 */ + reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; + ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); + if (ret < 0 || touchStatus == GT_EVENT_INVALID) { + return HDF_FAILURE; + } + ... + /* 根据状态寄存器的值读取数据寄存器数据 */ + reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; + reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; + pointNum = touchStatus & GT_FINGER_NUM_MASK; + if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) { + HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum); + (void)ChipCleanBuffer(i2cClient); + OsalMutexUnlock(&device->driver->mutex); + return HDF_FAILURE; + } + frame->realPointNum = pointNum; + frame->definedEvent = TOUCH_DOWN; + (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); + /* 对获取的数据进行解析 */ + ParsePointData(device, frame, buf, pointNum); + ... + } + static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) + { + ... + /* 每个坐标值由两个字节组成,对获取的单字节数据进行拼接得到最终的坐标值 */ + for (i = 0; i < pointNum; i++) { + frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID]; + frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | + ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); + /* 对解析出来的坐标值进行打印 */ + HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, frame->fingers[i].y); + } + } + ``` + +2. 器件层驱动初始化及注册驱动至HDF框架 + + 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c + + ``` + static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device) + { + ... + /* 器件配置结构体内存申请、配置信息解析及挂载 */ + chipCfg = ChipConfigInstance(device); + ... + /* 器件实例化 */ + chipDev = ChipDeviceInstance(); + ... + /* 器件信息挂载及器件私有操作挂载 */ + chipDev->chipCfg = chipCfg; + chipDev->ops = &g_gt911ChipOps; + ... + /* 注册器件驱动至平台驱动 */ + RegisterChipDevice(chipDev); + ... + } + struct HdfDriverEntry g_touchGoodixChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_GT911", // 该moduleName与device_info.hcs文件中器件驱动层的moduleName信息相匹配 + .Init = HdfGoodixChipInit, // 器件驱动初始化函数 + }; + HDF_INIT(g_touchGoodixChipEntry); // 注册器件驱动至HDF框架 + ``` + + 器件私有驱动层主要实现了各器件厂商差异较大的部分,如器件休眠唤醒、数据解析以及固件升级等。 + + 至此,基于HDF框架及Input模型的触摸屏驱动适配完成。 + + +## 编译及烧录 + +1. 编辑Makefile文件,添加本示例中的内容: + + 文件路径:./drivers/adapter/khdf/linux/model/input/Makefile + + 添加内容如下: + + ``` + obj-$(CONFIG_DRIVERS_HDF_TP_5P5_GT911) += \ + $(INPUT_ROOT_DIR)/touchscreen/touch_gt911.o + ``` + + 其中touch\_gt911.o为本示例中追加的内容。 + +2. 具体编译及烧录操作请参考[标准系统快速入门编译及烧录章节](../nottoctopics/zh-cn_topic_0000001135402541.md#section375234715135)。 + +## 调试验证 + +如下所示为开机启动日志部分截取 + +``` +[I/HDF_INPUT_DRV] HdfInputManagerInit: enter // 管理驱动层初始化 +[I/HDF_INPUT_DRV] HdfInputManagerInit: exit succ // 初始化成功 +[I/osal_cdev] add cdev hdf_input_host success +[I/HDF_LOG_TAG] HdfTouchDriverProbe: enter // 公共驱动层初始化 +[I/HDF_LOG_TAG] HdfTouchDriverProbe: main_touch exit succ // 初始化成功 +[I/osal_cdev] add cdev hdf_input_event1 success +[I/HDF_INPUT_DRV] HdfGoodixChipInit: enter // 器件驱动层初始化 +[I/HDF_INPUT_DRV] ChipDetect: IC FW version is 0x1060 +[I/HDF_INPUT_DRV] Product_ID: 911_1060, x_sol = 960, y_sol = 480 +[I/HDF_LOG_TAG] ChipDriverInit: chipDetect succ, ret = 0 +[I/HDF_LOG_TAG] InputDeviceInstance: inputDev->devName = main_touch +[I/HDF_INPUT_DRV] HdfGoodixChipInit: exit succ, chipName = gt911 // 初始化成功 +``` + +## Input模型工作流程解析 + +为了让开发者更清晰的了解Input模型工作流程,本节将对input模型加载的关键流程代码进行说明。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本章节为Input模型工作流程说明,开发者无需进行开发。 + +### 私有配置信息解析 + +示例代码路径:./drivers/framework/model/input/driver/input\_config\_parser.c + +根据OSAL提供的配置解析函数,可以将hcs文件中各字段含义进行解析,具体请参考input\_config\_parser.c中各函数的实现。如果提供的模板不能满足需求,在hcs文件中添加相应信息后,需要根据添加的字段开发相应的解析函数。 + +``` +static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode, BoardAttrCfg *attr) +{ + int32_t ret; + ret = parser->GetUint8(attrNode, "inputType", &attr->devType, 0); // 获取inputType字段信息,保存在BoardAttrCfg结构体中 + CHECK_PARSER_RET(ret, "GetUint8"); + ... + return HDF_SUCCESS; +} +``` + +### 管理驱动层初始化及注册驱动至HDF框架 + +示例代码路径:./drivers/framework/model/input/driver/hdf\_input\_device\_manager.c + +``` +static int32_t HdfInputManagerInit(struct HdfDeviceObject *device) +{ + /* 分配内存给manager,manager中将存放所有input设备 */ + g_inputManager = InputManagerInstance(); + ... +} +struct HdfDriverEntry g_hdfInputEntry = { + .moduleVersion = 1, + .moduleName = "HDF_INPUT_MANAGER", + .Bind = HdfInputManagerBind, + .Init = HdfInputManagerInit, + .Release = HdfInputManagerRelease, +}; + +HDF_INIT(g_hdfInputEntry); //驱动注册入口 +``` + +### 公共驱动层初始化及注册驱动至HDF框架 + +示例代码路径:./drivers/framework/model/input/driver/hdf\_touch.c + +``` +static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device) +{ + ... + /* 板级信息结构体内存申请及hcs配置信息解析 */ + boardCfg = BoardConfigInstance(device); + ... + /* 公共驱动结构体内存申请 */ + touchDriver = TouchDriverInstance(); + ... + /* 依据解析出的板级信息进行公共资源初始化,如IIC初始化 */ + ret = TouchDriverInit(touchDriver, boardCfg); + if (ret == HDF_SUCCESS) { + ... + /* 添加驱动至公共驱动层驱动管理链表,当设备与驱动进行绑定时使用该链表进行查询 */ + AddTouchDriver(touchDriver); + ... + } + ... +} +struct HdfDriverEntry g_hdfTouchEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH", + .Bind = HdfTouchDriverBind, + .Init = HdfTouchDriverProbe, + .Release = HdfTouchDriverRelease, +}; + +HDF_INIT(g_hdfTouchEntry); //驱动注册入口 +``` + +### 器件驱动层初始化及注册驱动至HDF框架 + +具体请参考[适配器件私有驱动](#section17127331595)器件层驱动初始化及注册驱动至HDF框架部分。 + +### 具体调用逻辑串联函数 + +Input模型管理层驱动init函数初始化了设备管理链表,公共驱动层初始化函数完成了相关结构体的内存申请。器件驱动相关信息通过RegisterChipDevice函数对公共驱动层相关结构体进行信息填充,同时完成了相关硬件信息的初始化(如中断注册等),绑定设备与驱动组成inputDev通过RegisterInputDevice函数向驱动管理层进行注册,在RegisterInputDevice函数中主要实现了将inputDev向设备管理链表的添加等功能。如下所示为两个函数的实现部分: + +``` +//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_touch.c +int32_t RegisterChipDevice(ChipDevice *chipDev) +{ + ... + /* 绑定设备与驱动,从而通过InputDeviceInstance函数创建inputDev */ + DeviceBindDriver(chipDev); + ... + /* 主要包含器件中断注册及中断处理函数,中断处理函数中有数据上报用户态的数据通道 */ + ChipDriverInit(chipDev); + ... + /* 申请内存实例化InputDev */ + inputDev = InputDeviceInstance(chipDev); + ... + /* 将InputDev设备注册至input驱动管理层 */ + RegisterInputDevice(inputDev); + ... +} + +//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_input_device_manager.c +int32_t RegisterInputDevice(InputDevice *inputDev) +{ + ... + /* 申请ID,该ID对于不同input设备唯一 */ + ret = AllocDeviceID(inputDev); + ... + /* 该函数包含了对hid类设备的特殊处理,对于触摸屏驱动,该函数无实质操作; */ + CreateDeviceNode(inputDev); + /* 内核态数据传送至用户态需使用IOService能力,需要申请buffer */ + AllocPackageBuffer(inputDev); + /* 将input设备添加进设备全局管理链表 */ + AddInputDevice(inputDev); + ... +} +``` + diff --git a/zh-cn/device-dev/guide/device-wifi-led-outcontrol.md b/zh-cn/device-dev/guide/device-wifi-led-outcontrol.md new file mode 100644 index 0000000000000000000000000000000000000000..2d4970fa19c09b4fc4140751446e32bbed4e7ee3 --- /dev/null +++ b/zh-cn/device-dev/guide/device-wifi-led-outcontrol.md @@ -0,0 +1,110 @@ +# LED外设控制 + +- [概述](#section14639174516337) +- [开发](#section13857170163412) +- [验证](#section1949121910344) + +## 概述 + +OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力,包含I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。本文介绍如何通过调用OpenHarmony的NDK接口,实现对GPIO控制,达到LED闪烁的效果。其他的IOT外设控制,开发者可根据API指导文档完成,此处不逐一介绍。 + +## 开发 + +1. 请先完成[《Hi3861快速入门》](../quick-start/quickstart-lite-introduction-hi3861.md#section19352114194115)。 + + LED控制参考示例存放于applications/sample/wifi-iot/app/iothardware/led\_example.c文件中。 + +2. 实现IOT外设控制,首先需要通过查阅原理图明确接线关系。经过查阅,hispark pegasus的LED与芯片的9号管脚相连。 + + ``` + #define LED_TEST_GPIO 9 + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >开发板原理图,请开发者联系Hi3861购买渠道客服获取。 + +3. 使用GPIO前,需要完成GPIO管脚初始化,明确管脚用途,并创建任务,使LED周期性亮灭,达到闪烁的效果。 + + ``` + static void LedExampleEntry(void) + { + osThreadAttr_t attr; + + /* 管脚初始化 */ + IoTGpioInit(LED_TEST_GPIO); + /* 配置9号管脚为输出方向 */ + IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); + + attr.name = "LedTask"; + attr.attr_bits = 0U; + attr.cb_mem = NULL; + attr.cb_size = 0U; + attr.stack_mem = NULL; + attr.stack_size = LED_TASK_STACK_SIZE; + attr.priority = LED_TASK_PRIO; + + /* 启动任务 */ + if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) { + printf("[LedExample] Failed to create LedTask!\n"); + } + } + ``` + +4. 在循环任务中通过周期性亮灭形式实现LED闪烁。 + + ``` + static void *LedTask(const char *arg) + { + (void)arg; + while (1) { + switch (g_ledState) { + case LED_ON: + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + break; + case LED_OFF: + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + break; + case LED_SPARK: + IoTGpioSetOutputVal(LED_TEST_GPIO, 0); + usleep(LED_INTERVAL_TIME_US); + IoTGpioSetOutputVal(LED_TEST_GPIO, 1); + usleep(LED_INTERVAL_TIME_US); + break; + default: + usleep(LED_INTERVAL_TIME_US); + break; + } + } + return NULL; + } + ``` + +5. 在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) + + ``` + SYS_RUN(LedExampleEntry); + ``` + +6. 修改applications/sample/wifi-iot/app/BUILD.gn文件,使led\_example.c参与编译。 + + ``` + import("//build/lite/config/component/lite_component.gni") + lite_component("app") { + features = [ + "iothardware:led_example" + ] + } + ``` + + +## 验证 + +编译过程请参考《[Hi3861快速入门-源码编译](../quick-start/quickstart-lite-steps-board3861-connection.md#section191121332125319)》,烧录过程请参考《[Hi3861快速入门-镜像烧录](../quick-start/quickstart-lite-steps-board3861-connection.md#section19458165166)》。 + +完成以上两步后,按下RST键复位模组,可发现LED在周期性闪烁,与预期相符,验证完毕。 + +**图 1** LED闪烁图 +![](figure/LED闪烁图.gif "LED闪烁图") + diff --git a/zh-cn/device-dev/guide/device-wifi-sdk.md b/zh-cn/device-dev/guide/device-wifi-sdk.md new file mode 100644 index 0000000000000000000000000000000000000000..8106f68cd6202a165547b6db59ae734fe01e6e6b --- /dev/null +++ b/zh-cn/device-dev/guide/device-wifi-sdk.md @@ -0,0 +1,325 @@ +# 集成三方SDK + +- [规划目录结构](#section1736472718351) +- [构建业务libs](#section442815485351) +- [编写适配代码](#section3984721113613) +- [代码编写](#section830417531286) +- [脚本编写](#section13500201173710) +- [编写业务代码](#section8754114803918) +- [运行](#section7737749184012) +- [结束](#section153301392411) + +OpenHarmony致力于打造一套更加开放完善的IoT生态系统,为此OpenHarmony规划了一组目录,用于将各厂商的SDK集成到OpenHarmony中。本文档基于Hi3861开发板,向平台开发者介绍将SDK集成到OpenHarmony的方法。 + +## 规划目录结构 + +三方SDK通常由静态库和适配代码构成。SDK的业务逻辑通过硬件模组工具链编译得到静态库libs,每款模组都有其对应的libs。SDK的南向API与OpenHarmony 的API存在使用差异,该差异可通过adapter适配代码屏蔽,不同模组可共用一套adapter。 + +基于以上特征,在OpenHarmony目录结构中,可以对三方SDK目录做如下划分。 + +- 适配代码adapter,放置到domains/iot/link/ 目录下,与模组解耦。 +- 业务库libs,放置到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/ 目录下,与模组绑定。 + +平台开发者在适配前,务必先依次完成以下步骤,下面以demolink SDK举例,进行介绍。 + +1. 创建厂商目录,domains/iot/link/demolink/、device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/ ,用于厂商隔离。 +2. 创建domains/iot/link/demolink/BUILD.gn ,用于构建适配代码。 +3. 创建device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录,用于存放业务库libs。 + +``` +. +├── domains +│ └── iot +│ └── link +│ ├── demolink +│ │ └── BUILD.gn +│ ├── libbuild +│ │ └── BUILD.gn +│ └── BUILD.gn +└── device + └── hisilicon + └── hispark_pegasus + └── sdk_liteos + └── 3rd_sdk + └── demolink + └── libs +``` + +## 构建业务libs + +平台SDK业务一般以静态库的形式提供,平台厂商在获取到OpenHarmony代码后,需要根据对应的硬件模组vendor,编译业务libs,并将编译结果放置在device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下。下面介绍业务libs的构建方法。 + +OpenHarmony已规划用于编译业务libs的目录domains/iot/link/libbuild/ ,该目录中包含domains/iot/link/libbuild/BUILD.gn和domains/iot/link/BUILD.gn文件,目录结构如下。 + +``` +. +└── domains + └── iot + └── link + ├── demolink + │ └── BUILD.gn + ├── libbuild + │ └── BUILD.gn + └── BUILD.gn +``` + +平台开发者在构建libs前,务必先完成如下步骤。 + +1. 在domains/iot/link/libbuild/ 目录下放置业务源码文件,包括.c和.h文件。 + + ``` + . + └── domains + └── iot + └── link + ├── demolink + │ ├── demosdk_adapter.c + │ ├── demosdk_adapter.h + │ └── BUILD.gn + ├── libbuild + │ ├── demosdk.c + │ ├── demosdk.h + │ └── BUILD.gn + └── BUILD.gn + ``` + +2. 适配domains/iot/link/libbuild/BUILD.gn,在编译完成后还原该文件。 + + 在BUILD.gn中,sources为需要参与构建的源文件,include\_dirs为依赖的头文件路径,构建的目标结果是生成静态库libdemosdk.a。 + + ``` + static_library("demosdk") { + sources = [ + "demosdk.c" + ] + include_dirs = [ + "//domains/iot/link/libbuild", + "//domains/iot/link/demolink" + ] + } + ``` + +3. 适配domains/iot/link/BUILD.gn,在编译完成后还原该文件。 + + 此BUILD.gn文件用于指定构建条目,需要在features中填入所有需参与编译的静态库条目,使domains/iot/link/libbuild/BUILD.gn参与到构建中来。 + + ``` + import("//build/lite/config/subsystem/lite_subsystem.gni") + import("//build/lite/config/component/lite_component.gni") + lite_subsystem("iot") { + subsystem_components = [ + ":link" + ] + } + lite_component("link") { + features = [ + "libbuild:demosdk" + ] + } + ``` + + +完成以上3点后,需在代码根目录下执行命令“hb build -T //domains/iot/link:iot”,等待执行完成,检查out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/目录下是否生成了目标库文件。 + +![](figure/zh-cn_image_0000001078563230.png) + +将库文件拷贝到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下,并将domains/iot/link/libbuild/ 目录中的.c和.h文件清除。 + +## 编写适配代码 + +## 代码编写 + +平台SDK中使用的API通常与OpenHarmony API存在差异,无法直接使用,需要一层适配代码adapter进行中间转换。本节以domains/iot/link/demolink/demosdk\_adapter.c中的任务创建接口DemoSdkCreateTask举例,向开发者演示如何在OpenHarmony上编写适配代码。 + +1. 查看待适配接口DemoSdkCreateTask的描述、参数、返回值。 + + ``` + struct TaskPara { + char *name; + void *(*func)(char* arg); + void *arg; + unsigned char prio; + unsigned int size; + }; + + /* + * IoT OS 创建线程接口 + * 返回值: 返回0 成功, 其他 失败 + */ + int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para); + ``` + +2. 查看OpenHarmony API接口文档,选取一个功能类似的接口,并比对参数及用法上的差异。例如本文选取osThreadNew ,通过和DemoSdkCreateTask接口比对,可以发现两接口依赖的参数基本一致,只是参数所归属的结构体不同。 + + ``` + typedef struct { + const char *name; ///< name of the thread + uint32_t attr_bits; ///< attribute bits + void *cb_mem; ///< memory for control block + uint32_t cb_size; ///< size of provided memory for control block + void *stack_mem; ///< memory for stack + uint32_t stack_size; ///< size of stack + osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) + TZ_ModuleId_t tz_module; ///< TrustZone module identifier + uint32_t reserved; ///< reserved (must be 0) + } osThreadAttr_t; + + /// Create a thread and add it to Active Threads. + /// \param[in] func thread function. + /// \param[in] argument pointer that is passed to the thread function as start argument. + /// \param[in] attr thread attributes; NULL: default values. + /// \return thread ID for reference by other functions or NULL in case of error. + osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); + ``` + +3. 完成代码差异转换。 + + ``` + int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para) + { + osThreadAttr_t attr = {0}; + osThreadId_t threadId; + if (handle == 0 || para == 0) { + return DEMOSDK_ERR; + } + if (para->func == 0) { + return DEMOSDK_ERR; + } + if (para->name == 0) { + return DEMOSDK_ERR; + } + attr.name = para->name; + attr.priority = para->prio; + attr.stack_size = para->size; + threadId = osThreadNew((osThreadFunc_t)para->func, para->arg, &attr); + if (threadId == 0) { + printf("osThreadNew fail\n"); + return DEMOSDK_ERR; + } + *(unsigned int *)handle = (unsigned int)threadId; + return DEMOSDK_OK; + } + ``` + + +## 脚本编写 + +开发者在完成代码适配后,还需要在adapter同级目录下新建BUILD.gn文件。该文件可在整包构建时,将适配代码编译成静态库,并链接到bin包中去。在domains/iot/link/demolink/BUILD.gn中,sources中为需要参与构建的源文件,include\_dirs中为依赖的头文件路径,构建目标结果是生产静态库libdemolinkadapter.a。 + +``` +import("//build/lite/config/component/lite_component.gni") +static_library("demolinkadapter") { + sources = [ + "demosdk_adapter.c" + ] + include_dirs = [ + "//kernel/liteos-m/kal/cmsis", + "//domains/iot/link/demolink" + ] +} +``` + +修改domains/iot/link/BUILD.gn文件,使domain/iot/hilink/BUILD.gn参与到构建系统中。 + +``` +import("//build/lite/config/subsystem/lite_subsystem.gni") +import("//build/lite/config/component/lite_component.gni") +lite_subsystem("iot") { + subsystem_components = [ + ":link" + ] +} +lite_component("link") { + features = [ + "demolink:demolinkadapter" + ] +} +``` + +## 编写业务代码 + +业务libs库和适配代码准备就绪后,还需要编写业务入口函数,调起三方SDK的业务入口。 + +下面以demolink举例,介绍如何在applications/sample/wifi-iot/app/路径下编写代码,调起demosdk的入口函数。 + +1. 目录创建 + + 开发者编写业务时,务必先在applications/sample/wifi-iot/app/ 路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 + + 例如:在app下新增业务目录demolink,并在其中创建业务入口代码helloworld.c和编译构建文件BUILD.gn,如下。 + + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + │── demolink + │ │── helloworld.c + │ └── BUILD.gn + └── BUILD.gn + ``` + +2. 编写业务代码。 + + 在helloworld.c文件中编写业务入口函数DemoSdkMain,并调起demolink的业务DemoSdkEntry,最后通过SYS\_RUN\(\)调用入口函数完成业务启动。 + + ``` + #include "hos_init.h" + #include "demosdk.h" + + void DemoSdkMain(void) + { + DemoSdkEntry(); + } + + SYS_RUN(DemoSdkMain); + ``` + +3. 编写构建脚本 + + 新增applications/sample/wifi-iot/app/demolink/BUILD.gn文件,指定源码和头文件路径,编译输出静态库文件libexample\_demolink.a。 + + ``` + static_library("example_demolink") { + sources = [ + "helloworld.c" + ] + include_dirs = [ + "//utils/native/lite/include", + "//domains/iot/link/libbuild" + ] + } + ``` + + 修改applications/sample/wifi-iot/app/BUILD.gn,使demolink参与编译。 + + ``` + import("//build/lite/config/component/lite_component.gni") + lite_component("app") { + features = [ + "demolink:example_demolink" + ] + } + ``` + + +## 运行 + +在代码根目录下,执行命令“hb build”编译输出版本包。最后启动运行,运行结果如图所示,与demolink预期相符。 + +``` +ready to OS start +sdk ver:Hi3861V100R001C00SPC024 2020-08-05 16:30:00 +formatting spiffs... +FileSystem mount ok. +wifi init success! +it is demosdk entry. +it is demo biz: hello world. +it is demo biz: hello world. +``` + +## 结束 + +至此,三方SDK集成已介绍完毕。 + diff --git a/zh-cn/device-dev/guide/device-wifi.md b/zh-cn/device-dev/guide/device-wifi.md new file mode 100644 index 0000000000000000000000000000000000000000..3f85bc6f6c8626e1314093b28146dc989ee55167 --- /dev/null +++ b/zh-cn/device-dev/guide/device-wifi.md @@ -0,0 +1,7 @@ +# WLAN连接类产品 + +- **[LED外设控制](device-wifi-led-outcontrol.md)** + +- **[集成三方SDK](device-wifi-sdk.md)** + + diff --git a/zh-cn/device-dev/guide/device.md b/zh-cn/device-dev/guide/device.md new file mode 100644 index 0000000000000000000000000000000000000000..2c7d789c20247c494fcc5d99b4b34e391c05ef54 --- /dev/null +++ b/zh-cn/device-dev/guide/device.md @@ -0,0 +1,15 @@ +# 设备开发指南 + +- **[WLAN连接类产品](device-wifi.md)** + +- **[无屏摄像头类产品](device-iotcamera.md)** + +- **[带屏摄像头类产品](device-camera.md)** + +- **[时钟应用开发指导](device-clock-guide.md)** + +- **[平台驱动开发示例](device-drive-demo.md)** + +- **[外设驱动开发示例](device-outerdrive-demo.md)** + + diff --git a/zh-cn/device-dev/guide/figures/Clock.png b/zh-cn/device-dev/guide/figure/Clock.png similarity index 100% rename from zh-cn/device-dev/guide/figures/Clock.png rename to zh-cn/device-dev/guide/figure/Clock.png diff --git "a/zh-cn/device-dev/guide/figures/LED\351\227\252\347\203\201\345\233\276.gif" "b/zh-cn/device-dev/guide/figure/LED\351\227\252\347\203\201\345\233\276.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/LED\351\227\252\347\203\201\345\233\276.gif" rename to "zh-cn/device-dev/guide/figure/LED\351\227\252\347\203\201\345\233\276.gif" diff --git a/zh-cn/device-dev/guide/figures/Video_2020-07-25_173141.gif b/zh-cn/device-dev/guide/figure/Video_2020-07-25_173141.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figures/Video_2020-07-25_173141.gif rename to zh-cn/device-dev/guide/figure/Video_2020-07-25_173141.gif diff --git a/zh-cn/device-dev/guide/figures/zh-cn_image_0000001078563230.png b/zh-cn/device-dev/guide/figure/zh-cn_image_0000001078563230.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figures/zh-cn_image_0000001078563230.png rename to zh-cn/device-dev/guide/figure/zh-cn_image_0000001078563230.png diff --git a/zh-cn/device-dev/guide/figures/zh-cn_image_0000001082434703.png b/zh-cn/device-dev/guide/figure/zh-cn_image_0000001082434703.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/guide/figures/zh-cn_image_0000001082434703.png rename to zh-cn/device-dev/guide/figure/zh-cn_image_0000001082434703.png diff --git a/zh-cn/device-dev/guide/figures/zh-cn_image_0000001161922745.png b/zh-cn/device-dev/guide/figure/zh-cn_image_0000001169991055.png similarity index 100% rename from zh-cn/device-dev/guide/figures/zh-cn_image_0000001161922745.png rename to zh-cn/device-dev/guide/figure/zh-cn_image_0000001169991055.png diff --git "a/zh-cn/device-dev/guide/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" "b/zh-cn/device-dev/guide/figure/\345\220\257\345\212\250\347\244\272\344\276\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\345\220\257\345\212\250\347\244\272\344\276\213.png" rename to "zh-cn/device-dev/guide/figure/\345\220\257\345\212\250\347\244\272\344\276\213.png" diff --git "a/zh-cn/device-dev/guide/figures/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" "b/zh-cn/device-dev/guide/figure/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/guide/figure/\345\256\214\346\225\264\345\267\245\347\250\213\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/guide/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" "b/zh-cn/device-dev/guide/figure/\345\267\245\347\250\213\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\345\267\245\347\250\213\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/guide/figure/\345\267\245\347\250\213\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" "b/zh-cn/device-dev/guide/figure/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" rename to "zh-cn/device-dev/guide/figure/\346\237\245\347\234\213\346\226\207\344\273\266\345\233\276.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" "b/zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" rename to "zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\345\222\214\344\277\241\346\201\257\346\240\217\346\225\210\346\236\234.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" "b/zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" rename to "zh-cn/device-dev/guide/figure/\346\240\207\351\242\230\346\240\217\346\225\210\346\236\234.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" "b/zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\346\241\214\351\235\242.png" rename to "zh-cn/device-dev/guide/figure/\346\241\214\351\235\242.png" diff --git "a/zh-cn/device-dev/guide/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" "b/zh-cn/device-dev/guide/figure/\346\267\273\345\212\240\351\241\265\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\346\267\273\345\212\240\351\241\265\351\235\242.png" rename to "zh-cn/device-dev/guide/figure/\346\267\273\345\212\240\351\241\265\351\235\242.png" diff --git "a/zh-cn/device-dev/guide/figures/\347\273\230\345\233\2761.png" "b/zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" similarity index 100% rename from "zh-cn/device-dev/guide/figures/\347\273\230\345\233\2761.png" rename to "zh-cn/device-dev/guide/figure/\347\273\230\345\233\2761.png" diff --git "a/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\345\275\225\345\203\217\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\346\213\215\347\205\247\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" "b/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" rename to "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\241\265\351\235\242\345\220\215\347\247\260.png" diff --git "a/zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figure/\350\276\223\345\205\245\351\242\204\350\247\210\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figures/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" "b/zh-cn/device-dev/guide/figure/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" rename to "zh-cn/device-dev/guide/figure/\350\276\223\345\207\272\351\200\200\345\207\272\346\214\207\344\273\244\345\220\216\344\270\262\345\217\243\346\211\223\345\215\260\346\227\245\345\277\227.png" diff --git "a/zh-cn/device-dev/guide/figures/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/guide/figure/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/guide/figure/\351\241\265\351\235\242\344\275\215\347\275\256\346\214\207\347\244\272\345\231\250\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/guide/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" "b/zh-cn/device-dev/guide/figure/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/guide/figures/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" rename to "zh-cn/device-dev/guide/figure/\351\242\204\350\247\210\346\225\210\346\236\234.jpg" diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/guide/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/guide/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-note.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/guide/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/guide/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/guide/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/guide/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/guide/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/guide/public_sys-resources/icon-warning.gif and /dev/null differ diff --git "a/zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" "b/zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" deleted file mode 100644 index 31de19a1b135135ed4b6481331284bdb35200aee..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\205\254\345\205\261\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" +++ /dev/null @@ -1,35 +0,0 @@ -# 公共驱动层初始化及注册驱动至HDF框架 - -示例代码路径:./drivers/framework/model/input/driver/hdf\_touch.c - -``` -static int32_t HdfTouchDriverProbe(struct HdfDeviceObject *device) -{ - ... - /* 板级信息结构体内存申请及hcs配置信息解析 */ - boardCfg = BoardConfigInstance(device); - ... - /* 公共驱动结构体内存申请 */ - touchDriver = TouchDriverInstance(); - ... - /* 依据解析出的板级信息进行公共资源初始化,如IIC初始化 */ - ret = TouchDriverInit(touchDriver, boardCfg); - if (ret == HDF_SUCCESS) { - ... - /* 添加驱动至公共驱动层驱动管理链表,当设备与驱动进行绑定时使用该链表进行查询 */ - AddTouchDriver(touchDriver); - ... - } - ... -} -struct HdfDriverEntry g_hdfTouchEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH", - .Bind = HdfTouchDriverBind, - .Init = HdfTouchDriverProbe, - .Release = HdfTouchDriverRelease, -}; - -HDF_INIT(g_hdfTouchEntry); //驱动注册入口 -``` - diff --git "a/zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" "b/zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" deleted file mode 100644 index 9fc526d2109ecffd5cec6f672a85e5f8f6b173f0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\205\267\344\275\223\350\260\203\347\224\250\351\200\273\350\276\221\344\270\262\350\201\224\345\207\275\346\225\260.md" +++ /dev/null @@ -1,40 +0,0 @@ -# 具体调用逻辑串联函数 - -Input模型管理层驱动init函数初始化了设备管理链表,公共驱动层初始化函数完成了相关结构体的内存申请。器件驱动相关信息通过RegisterChipDevice函数对公共驱动层相关结构体进行信息填充,同时完成了相关硬件信息的初始化(如中断注册等),绑定设备与驱动组成inputDev通过RegisterInputDevice函数向驱动管理层进行注册,在RegisterInputDevice函数中主要实现了将inputDev向设备管理链表的添加等功能。如下所示为两个函数的实现部分: - -``` -//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_touch.c -int32_t RegisterChipDevice(ChipDevice *chipDev) -{ - ... - /* 绑定设备与驱动,从而通过InputDeviceInstance函数创建inputDev */ - DeviceBindDriver(chipDev); - ... - /* 主要包含器件中断注册及中断处理函数,中断处理函数中有数据上报用户态的数据通道 */ - ChipDriverInit(chipDev); - ... - /* 申请内存实例化InputDev */ - inputDev = InputDeviceInstance(chipDev); - ... - /* 将InputDev设备注册至input驱动管理层 */ - RegisterInputDevice(inputDev); - ... -} - -//函数具体实现代码位置 :./drivers/framework/model/input/driver/hdf_input_device_manager.c -int32_t RegisterInputDevice(InputDevice *inputDev) -{ - ... - /* 申请ID,该ID对于不同input设备唯一 */ - ret = AllocDeviceID(inputDev); - ... - /* 该函数包含了对hid类设备的特殊处理,对于触摸屏驱动,该函数无实质操作; */ - CreateDeviceNode(inputDev); - /* 内核态数据传送至用户态需使用IOService能力,需要申请buffer */ - AllocPackageBuffer(inputDev); - /* 将input设备添加进设备全局管理链表 */ - AddInputDevice(inputDev); - ... -} -``` - diff --git "a/zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" "b/zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" deleted file mode 100644 index 4cfddfa469ff7d5812667549270c01baf14befe0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\231\250\344\273\266\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 器件驱动层初始化及注册驱动至HDF框架 - -具体请参考[3.3章节](适配器件私有驱动.md)器件层驱动初始化及注册驱动至HDF框架部分。 - diff --git "a/zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100644 index 8b083827126708b7db7f7d283ed2f34fa392a9ae..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\244\226\350\256\276\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 外设驱动开发示例 - -- **[概述](概述-12.md)** - -- **[环境搭建](环境搭建.md)** - -- **[TouchScreen器件驱动开发](TouchScreen器件驱动开发.md)** - -- **[编译及烧录](编译及烧录-13.md)** - -- **[调试验证](调试验证.md)** - -- **[Input模型工作流程解析](Input模型工作流程解析.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" "b/zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" deleted file mode 100755 index 7fed33d8a7778766da71be14c1704a1ebb08b0b6..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\261\217\345\271\225\345\222\214\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 屏幕和摄像头控制 - -- **[概述](概述-1.md)** - -- **[示例开发](示例开发-2.md)** - -- **[应用实例](应用实例-5.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" "b/zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" deleted file mode 100755 index 0dacd47e009d1b132a2d52dda4d6c6aaa59e10cb..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\270\246\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 带屏摄像头类产品 - -- **[屏幕和摄像头控制](屏幕和摄像头控制.md)** - -- **[视觉应用开发](视觉应用开发.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" "b/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" deleted file mode 100644 index 24be5472457cc6266e3a7f55040bdc377de2639d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\270\270\350\247\201\351\227\256\351\242\230-10.md" +++ /dev/null @@ -1,39 +0,0 @@ -# 常见问题 - -- [hdc\_std连接不到设备](#section1221016541119) -- [hdc\_std运行不了](#section219185710311) - -## hdc\_std连接不到设备 - -- **现象描述** - - 执行 "hdc\_std list targets"命令后结果为:\[Empty\] - -- **可能原因和解决方法** - 1. 设备没有被识别: - - 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 - - 2. hdc\_std工作异常: - - 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 - - 如果一直获取不到设备信息,请在任务管理器中查询是否有adb进程,该进程可能会对hdc产生干扰,可以将其杀掉后重复执行上面的步骤。 - - 3. hdc\_std与设备不匹配: - - 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 - - - -## hdc\_std运行不了 - -- **现象描述** - - 点击hdc\_std.exe文件无法运行。 - -- **可能原因和解决方法** - - hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 - - diff --git "a/zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100644 index 5dc1dd07b55fff2f60df94e5d132d3f02dc1db71..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\271\263\345\217\260\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 平台驱动开发示例 - -- **[概述](概述-10.md)** - -- **[环境准备](环境准备.md)** - -- **[开发](开发-11.md)** - -- **[编译及烧录](编译及烧录.md)** - - diff --git "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" "b/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" deleted file mode 100755 index a5da7138f9cbb55e51201fe4f6da8df0c9de54d5..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213-5.md" +++ /dev/null @@ -1,63 +0,0 @@ -# 应用实例 - -本示例将运行源码中的camera示例代码,通过本示例可以实现对开发板拍照、录像及预览功能的控制。 - -- 本示例源码路径为“applications/sample/camera/media/camera\_sample.cpp”。 -- 在运行本示例前需先完成编译烧录、运行镜像等步骤,相关操作请参考[Hi3516快速入门](../quick-start/Hi3516开发板介绍.md) - - >![](public_sys-resources/icon-note.gif) **说明:** - >开发板启动后默认会加载launcher应用,应用的图形界面默认显示在媒体图层上方,会影响camera\_sample的演示结果,因此需要在编译或是打包时去掉launcher应用。 - >**修改方法:**将“build/lite/components/applications.json”中camera\_sample\_app组件的targets中"//applications/sample/camera/launcher:launcher\_hap"整行注释或删除。 - -- 本示例编译结果路径为“out/hi3516dv300/ipcamera\_hi3516dv300\_liteos/dev\_tools/bin”,为让文件能在单板中执行,可将示例文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 - - 修改源码路径“applications/sample/camera/media/BUILD.gn”中第一处的output\_dir。 - - - 修改前:output\_dir = "$root\_out\_dir/dev\_ools" - - 修改后:output\_dir = "$root\_out\_dir/" - - 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 - -- 接下来可通过以下步骤运行示例: - -1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 - - **图 1** 启动示例 - ![](figures/启动示例.png "启动示例") - - 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 - -2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* - - **图 2** 输入拍照指令后串口打印日志 - ![](figures/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") - - 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 - - **图 3** 查看文件图 - ![](figures/查看文件图.png "查看文件图") - -3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 - - **图 4** 输入录像指令后串口打印日志 - ![](figures/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") - -4. 按3进行预览,预览图像直接送至显示屏,按s键停止。 - - **图 5** 输入预览指令后串口打印日志 - ![](figures/输入预览指令后串口打印日志.png "输入预览指令后串口打印日志") - - 预览效果如下 - - **图 6** 预览效果 - ![](figures/预览效果.jpg "预览效果") - -5. 按q键退出 - - **图 7** 输出退出指令后串口打印日志 - ![](figures/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") - - diff --git "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" "b/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" deleted file mode 100755 index 21cb165165fec20314a38415096eb0959a94869d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\272\224\347\224\250\345\256\236\344\276\213.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 应用实例 - -- 开发板介绍、编译烧录、运行镜像等操作请参考[Hi3518快速入门](../quick-start/Hi3518开发板介绍.md),编译结果包含示例,结果文件为out/ipcamera\_hi3518ev300/dev\_tools/bin/camera\_sample,可将文件通过读卡器复制至TF卡中,或者修改camera\_sample的编译脚本将结果文件复制至rootfs.img中。 - - 修改applications/sample/camera/media/BUILD.gn中的output\_dir。 - - - 修改前:output\_dir = "$root\_out\_dir/dev\_tools" - - 修改后:output\_dir = "$root\_out\_d_i_r/" - - 重新执行源码仓编译并烧写入单板后,可在单板bin目录下找到camera\_sample文件。 - -- 相机示例代码为applications/sample/camera/media/camera\_sample.cpp。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >实例运行拍照和录像功能需要插入TF卡\(最大容量支持128GB\),系统启动后时自动将TF卡挂载至/sdcard目录,如果在启动后插入则需要手动挂载。查看拍照和录像内容可将TF卡中内容复制到电脑中进行查看,预览功能无需TF卡。 - - -1. 通过cd命令进入可执行程序的末端路径,启动camera\_sample,执行命令如下图。 - - **图 1** 启动示例 - ![](figures/启动示例.png "启动示例") - - 运行后的控制命令如串口打印所示,按s键停止当前操作(包括录像和预览),按q键退出示例程序。 - -2. 按1进行拍照,拍照的文件格式为jpg,存储在/sdcard,文件名Capture\* - - **图 2** 输入拍照指令后串口打印日志 - ![](figures/输入拍照指令后串口打印日志.png "输入拍照指令后串口打印日志") - - 若想查看保存文件,可在退出程序后进入文件系统查看,退出后重新进入请回到步骤1。 - - **图 3** 查看文件图 - ![](figures/查看文件图.png "查看文件图") - -3. 按2进行录像,录像的文件格式为mp4,存储在/sdcard,文件名Record\*,按s键停止 - - **图 4** 输入录像指令后串口打印日志 - ![](figures/输入录像指令后串口打印日志.png "输入录像指令后串口打印日志") - -4. 按q键退出 - - **图 5** 输出退出指令后串口打印日志 - ![](figures/输出退出指令后串口打印日志.png "输出退出指令后串口打印日志") - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" deleted file mode 100644 index a7dedada78968ebaaf7e6f721e9ec4d7cf41994c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221-11.md" +++ /dev/null @@ -1,396 +0,0 @@ -# 开发 - -- [实例化驱动入口](#section6586911816) -- [设置相关参数](#section114323217503) -- [添加控制器](#section115187812516) - -平台驱动开发包含以下几步: - -1. 实例化驱动入口: 实例化一个HdfDriverEntry 对象作为驱动入口。 -2. 设置相关参数:通过配置device\_info.hcs,并从HCS获取并解析设备的配置参数以确保驱动能够正确加载。 -3. 添加控制器:初始化控制器硬件,并调用核心层接口完成向核心层添加、删除设备,以及钩子函数的实现等。 - -本例中涉及的文件及路径如下表: - -**表 1** 文件说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

说明

-

文件路径

-

操作

-

示例文件

-

/drivers/adapter/khdf/linux/platform/i2c/i2c_sample.c

-

新增文件

-

设备服务文件

-

/drivers/adapter/khdf/linux/hcs/device_info/device_info.hcs

-

-

追加内容

-

-

配置参数文件

-

/drivers/adapter/khdf/linux/hcs/platform/i2c_config.hcs

-

编译文件

-

/drivers/adapter/khdf/linux/platform/i2c/Makefile

-

依赖头文件

-

/drivers/framework/include/core/hdf_device_desc.h

-

作为头文件引用

-

-

核心层头文件

-

/drivers/framework/support/platform/include/i2c_core.h

-

HCS配置入口文件

-

/drivers/adapter/khdf/linux/hcs/hdf.hcs

-

HCS配置文件总入口

-
- ->![](public_sys-resources/icon-caution.gif) **注意:** ->本例程涉及的文件路径均作为演示,驱动开发者应根据实际情况确定具体的源文件存放位置。 - -## 实例化驱动入口 - -驱动入口必须为HdfDriverEntry(在hdf\_device\_desc.h中定义)类型的全局变量,且moduleName要和device\_info.hcs中保持一致。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 - -I2C驱动中没有实现Bind方法,因为I2C控制器由manager管理,而在manager中已经实现了Bind方法,因此I2C驱动中无需再绑定服务。 - -实例化驱动入口的示例代码如下: - -``` -/* 定义驱动入口的对象,必须为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量 */ -struct HdfDriverEntry g_sampleI2cDriverEntry = { - .moduleVersion = 1, - .Init = SampleI2cInit, - .Release = SampleI2cRelease, - .moduleName = "demo_i2c_driver", -}; -/* 调用HDF_INIT将驱动入口注册到HDF框架中 */ -HDF_INIT(g_sampleI2cDriverEntry); -``` - -## 设置相关参数 - -1. 添加设备服务节点(必选)。 - - 编辑device\_info.hcs,在device\_i2c :: device下添加驱动设备服务节点,示例如下: - - ``` - root { - device_info { - match_attr = "hdf_manager"; - device_i2c :: device { // i2c设备节点 - device2 :: deviceNode { // i2c驱动的DeviceNode节点 - policy = 0; // policy字段是驱动服务发布的策略 - priority = 55; // 驱动启动优先级 - permission = 0644; // 驱动创建设备节点权限 - moduleName = "demo_i2c_driver"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 - serviceName = "DEMO_I2C_DRIVER"; // 驱动对外发布服务的名称,必须唯一 - deviceMatchAttr = "demo_i2c_config"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的 - // match_attr值相等 - } - } - } - } - - ``` - - >![](public_sys-resources/icon-notice.gif) **须知:** - >配置文件中的priority(取值范围为整数0到200)是用来表示host和驱动的优先级,不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高,驱动的priority值相同则不保证加载顺序。 - -2. 添加配置参数(可选)。 - - 有时驱动可能会需要私有配置信息,以确保寄存器的配置可以满足不同产品的需求。如需要私有配置信息,则可以添加一个驱动的配置文件,用来存放一些驱动的默认配置信息,HDF框架在加载驱动的时候,会将对应的配置信息获取并保存在HdfDeviceObject 中的property里面,通过Bind和Init(参考[驱动开发](../driver/驱动开发.md))传递给驱动。驱动开发者可新建配置文件,并在板级驱动hdf.hcs中引用新建的配置文件,本例中直接在原有的配置文件i2c\_config.hcs内添加配置参数。 - - 本例中编辑i2c\_config.hcs,添加配置参数: - - ``` - root { - platform { - i2c_config_demo { - match_attr = "demo_i2c_config"; // 该字段的值必须和device_info.hcs中的deviceMatchAttr值一致 - - template i2c_controller { // 参数模板 - bus = 0; - reg_pbase = 0x120b0000; - reg_size = 0xd1; - } - - controller_demo_0 :: i2c_controller { // 两个I2C示例控制器 - bus = 8; - } - controller_demo_1 :: i2c_controller { - bus = 9; - } - } - } - } - ``` - - match\_attr字段必须与device\_info.hcs中的deviceMatch\_Attr保持一致,在此文件中配置驱动需要的参数,通过match\_attr可匹配至对应的驱动,该驱动即可在Bind或Init中调用DeviceResourceGetIfaceInstance\(\)函数获取这些配置参数。 - - 若配置文件为新文件,则需要在板级配置入口文件hdf.hcs中引用该配置文件,例如: - - ``` - #include "device_info/device_info.hcs" - #include "i2c/i2c_config.hcs" - ``` - - 由于本例中在原有的i2c\_config.hcs内添加配置参数,没有新建配置文件,因此无需再将i2c\_config.hcs添加至板级配置入口文件中。 - -3. 驱动从HCS获取配置参数。 - - 在本例中,驱动需要通过HCS获取寄存器物理基地址、寄存器大小、总线号等参数,从而对控制器进行正确配置。 - - ``` - /* 从HCS获取配置参数 */ - static int32_t SampleI2cReadDrs(struct SampleI2cCntlr *sampleCntlr, const struct DeviceResourceNode *node) - { - int32_t ret; - struct DeviceResourceIface *drsOps = NULL; - - drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - if (drsOps == NULL || drsOps->GetUint32 == NULL) { // 确保GetUint32方法可用 - HDF_LOGE("%s: invalid drs ops fail!", __func__); - return HDF_FAILURE; - } - - ret = drsOps->GetUint32(node, "reg_pbase", &sampleCntlr->regBasePhy, 0); // 从HCS读取物理基地址reg_pbase - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read regBase fail!", __func__); - return ret; - } - - ret = drsOps->GetUint16(node, "reg_size", &sampleCntlr->regSize, 0); // 从HCS读取寄存器大小reg_size - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read regsize fail!", __func__); - return ret; - } - - ret = drsOps->GetUint16(node, "bus", (uint16_t *)&sampleCntlr->bus, 0); // 从HCS读取总线号bus - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read bus fail!", __func__); - return ret; - } - - return HDF_SUCCESS; - } - ``` - - -## 添加控制器 - -1. 定义结构体,实现钩子函数并赋值至函数指针。 - - I2cMethod结构体在i2c\_core.h中定义,其中通过函数指针的方式定义了I2C需要实现的方法,transfer方法为用于传输的钩子函数,在驱动中需要做具体实现并对函数指针赋值。 - - 示例代码如下: - - ``` - /* 自定义设备结构体,继承父类I2cCntlr */ - struct SampleI2cCntlr { - struct I2cCntlr cntlr; - OsalSpinlock spin; - volatile unsigned char *regBase; - uint16_t regSize; - int16_t bus; - uint32_t regBasePhy; - }; - - /* 消息结构体,继承父类I2cMsg */ - struct SampleTransferData { - struct I2cMsg *msgs; - int16_t index; - int16_t count; - }; - /* 钩子函数实现 */ - static int32_t SampleI2cTransfer(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count) - { - int32_t ret = HDF_SUCCESS; - struct SampleI2cCntlr *sampleCntlr = NULL; - struct SampleTransferData td; - - if (cntlr == NULL || cntlr->priv == NULL) { - HDF_LOGE("SampleI2cTransfer: cntlr lor sampleCntlr is null!"); - return HDF_ERR_INVALID_OBJECT; - } - sampleCntlr = (struct SampleI2cCntlr *)cntlr; - - if (msgs == NULL || count <= 0) { - HDF_LOGE("SampleI2cTransfer: err parms! count:%d", count); - return HDF_ERR_INVALID_PARAM; - } - td.msgs = msgs; - td.count = count; - td.index = 0; - - HDF_LOGE("Successfully transmitted!"); // 表示此处传输成功 - - td.index = count; // 经过处理,最后实际发送msg个数等于count,返回已发送个数,此句代替已省略的处理过程 - return (td.index > 0) ? td.index : ret; - } - /* 钩子函数赋值 */ - static struct I2cMethod g_method = { - .transfer = SampleI2cTransfer, - }; - ``` - -2. 编写驱动初始化函数。 - - 本例中使用SampleI2cInit作为驱动初始化函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Init,以供HDF驱动框架调用从而达到初始化驱动的目的。该函数中需要对从HCS获取的配置参数进行解析,并按照这些参数创建控制器。示例如下: - - ``` - /* 解析参数,申请内存并创建控制器 */ - static int32_t SampleI2cParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node) - { - int32_t ret; - struct SampleI2cCntlr *sampleCntlr = NULL; - (void)device; - - sampleCntlr = (struct SampleI2cCntlr *)OsalMemCalloc(sizeof(*sampleCntlr)); - if (sampleCntlr == NULL) { - HDF_LOGE("%s: malloc sampleCntlr fail!", __func__); - return HDF_ERR_MALLOC_FAIL; - } - - ret = SampleI2cReadDrs(sampleCntlr, node); // 从HCS获取配置参数 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read drs fail! ret:%d", __func__, ret); - goto __ERR__; - } - - sampleCntlr->regBase = OsalIoRemap(sampleCntlr->regBasePhy, sampleCntlr->regSize); - if (sampleCntlr->regBase == NULL) { - HDF_LOGE("%s: ioremap regBase fail!", __func__); - ret = HDF_ERR_IO; - goto __ERR__; - } - - HDF_LOGE("The controller has been initialized!"); // 表示此处省略的控制器初始化操作已经成功 - - sampleCntlr->cntlr.priv = (void *)node; - sampleCntlr->cntlr.busId = sampleCntlr->bus; - sampleCntlr->cntlr.ops = &g_method; - (void)OsalSpinInit(&sampleCntlr->spin); // 初始化自旋锁 - ret = I2cCntlrAdd(&sampleCntlr->cntlr); // 向核心层添加控制器 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: add i2c controller fail:%d!", __func__, ret); - goto __ERR__; - } - - return HDF_SUCCESS; - __ERR__: // 错误处理 - if (sampleCntlr != NULL) { - if (sampleCntlr->regBase != NULL) { - OsalIoUnmap((void *)sampleCntlr->regBase); // 取消地址映射 - sampleCntlr->regBase = NULL; - } - OsalMemFree(sampleCntlr); // 释放内存 - sampleCntlr = NULL; - } - return ret; - } - /* 驱动入口初始化函数 */ - static int32_t SampleI2cInit(struct HdfDeviceObject *device) - { - int32_t ret; - const struct DeviceResourceNode *childNode = NULL; - - HDF_LOGE("%s: Enter", __func__); - if (device == NULL || device->property == NULL) { - HDF_LOGE("%s: device or property is NULL", __func__); - return HDF_ERR_INVALID_OBJECT; - } - - ret = HDF_SUCCESS; - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - ret = SampleI2cParseAndInit(device, childNode); // 调用解析参数和创建控制器的函数 - if (ret != HDF_SUCCESS) { - break; - } - } - return ret; - } - ``` - -3. 编写驱动释放函数。 - - 本例中使用SampleI2cRelease作为驱动释放函数的函数名(函数名称可由驱动开发者确定),该函数需要在驱动入口结构体中赋值给Release,当HDF框架调用Init函数初始化驱动失败时,将调用Release释放驱动资源。该函数中需包含释放内存和删除控制器等操作。示例如下: - - ``` - /* 删除控制器函数 */ - static void SampleI2cRemoveByNode(const struct DeviceResourceNode *node) - { - int32_t ret; - int16_t bus; - struct I2cCntlr *cntlr = NULL; - struct SampleI2cCntlr *sampleCntlr = NULL; - struct DeviceResourceIface *drsOps = NULL; - - drsOps = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - if (drsOps == NULL || drsOps->GetUint32 == NULL) { - HDF_LOGE("%s: invalid drs ops fail!", __func__); - return; - } - - ret = drsOps->GetUint16(node, "bus", (uint16_t *)&bus, 0); // 从HCS获取I2C总线号 - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: read bus fail!", __func__); - return; - } - - cntlr = I2cCntlrGet(bus); - if (cntlr != NULL && cntlr->priv == node) { // 根据I2C总线号删除控制器 - I2cCntlrPut(cntlr); - I2cCntlrRemove(cntlr); - sampleCntlr = (struct SampleI2cCntlr *)cntlr; - OsalIoUnmap((void *)sampleCntlr->regBase); - OsalMemFree(sampleCntlr); - } - return; - } - /* 释放资源 */ - static void SampleI2cRelease(struct HdfDeviceObject *device) - { - const struct DeviceResourceNode *childNode = NULL; - - HDF_LOGI("%s: enter", __func__); - - if (device == NULL || device->property == NULL) { - HDF_LOGE("%s: device or property is NULL", __func__); - return; - } - - DEV_RES_NODE_FOR_EACH_CHILD_NODE(device->property, childNode) { - SampleI2cRemoveByNode(childNode); // 调用删除控制器函数 - } - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221.md" deleted file mode 100755 index 18b3247aefef1bb7d1c24a961900349325110ad6..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221.md" +++ /dev/null @@ -1,91 +0,0 @@ -# 开发 - -1. 请先完成[《Hi3861快速入门》](../quick-start/Hi3861开发板介绍.md)。 - - LED控制参考示例存放于applications/sample/wifi-iot/app/iothardware/led\_example.c文件中。 - -2. 实现IOT外设控制,首先需要通过查阅原理图明确接线关系。经过查阅,hispark pegasus的LED与芯片的9号管脚相连。 - - ``` - #define LED_TEST_GPIO 9 - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >开发板原理图,请开发者联系Hi3861购买渠道客服获取。 - -3. 使用GPIO前,需要完成GPIO管脚初始化,明确管脚用途,并创建任务,使LED周期性亮灭,达到闪烁的效果。 - - ``` - static void LedExampleEntry(void) - { - osThreadAttr_t attr; - - /* 管脚初始化 */ - IoTGpioInit(LED_TEST_GPIO); - /* 配置9号管脚为输出方向 */ - IoTGpioSetDir(LED_TEST_GPIO, IOT_GPIO_DIR_OUT); - - attr.name = "LedTask"; - attr.attr_bits = 0U; - attr.cb_mem = NULL; - attr.cb_size = 0U; - attr.stack_mem = NULL; - attr.stack_size = LED_TASK_STACK_SIZE; - attr.priority = LED_TASK_PRIO; - - /* 启动任务 */ - if (osThreadNew((osThreadFunc_t)LedTask, NULL, &attr) == NULL) { - printf("[LedExample] Falied to create LedTask!\n"); - } - } - ``` - -4. 在循环任务中通过周期性亮灭形式实现LED闪烁。 - - ``` - static void *LedTask(const char *arg) - { - (void)arg; - while (1) { - switch (g_ledState) { - case LED_ON: - IoTGpioSetOutputVal(LED_TEST_GPIO, 1); - usleep(LED_INTERVAL_TIME_US); - break; - case LED_OFF: - IoTGpioSetOutputVal(LED_TEST_GPIO, 0); - usleep(LED_INTERVAL_TIME_US); - break; - case LED_SPARK: - IoTGpioSetOutputVal(LED_TEST_GPIO, 0); - usleep(LED_INTERVAL_TIME_US); - IoTGpioSetOutputVal(LED_TEST_GPIO, 1); - usleep(LED_INTERVAL_TIME_US); - break; - default: - usleep(LED_INTERVAL_TIME_US); - break; - } - } - return NULL; - } - ``` - -5. 在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) - - ``` - SYS_RUN(LedExampleEntry); - ``` - -6. 修改applications/sample/wifi-iot/app/BUILD.gn文件,使led\_example.c参与编译。 - - ``` - import("//build/lite/config/component/lite_component.gni") - lite_component("app") { - features = [ - "iothardware:led_example" - ] - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" deleted file mode 100755 index 52eed11deb14636b5a5cf069cf7fc7dbc62196e1..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207-8.md" +++ /dev/null @@ -1,8 +0,0 @@ -# 开发准备 - -- [准备开发环境和创建工程](#section1912530122716) - -## 准备开发环境和创建工程 - -首先需要下载和配置DevEco Studio,具体操作请参考[DevEco Studio 使用指南](../../application-dev/quick-start/DevEco-Studio(OpenHarmony)使用指南.md)。 - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" deleted file mode 100755 index f24d68a539b1f575c5cec0da870f718138055562..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\345\207\206\345\244\207.md" +++ /dev/null @@ -1,27 +0,0 @@ -# 开发准备 - -- [准备开发环境](#section1912530122716) -- [创建项目](#section1456035192720) - -## 准备开发环境 - -首先需要下载和配置DevEco Studio,具体操作请参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/software_install-0000001053582415)。 - -## 创建项目 - -1. 通过如下两种方式,打开工程创建向导界面。 - - 如果当前未打开任何工程,可以在DevEco Studio的欢迎页,选择**Create HarmonyOS Project**开始创建一个新工程。 - - 如果已经打开了工程,可以在菜单栏选择**File \> New \> New Project**来创建一个新工程。 - -2. 选择“Smart Vision”下的“Empty Feature Ability”模板。 - - ![](figures/zh-cn_image_0000001082434703.png) - -3. 点击**Next**,进入到工程配置阶段,需要根据向导配置工程的基本信息。 - - **Project Name**:工程的名称,可以自定义。 - - **Package Name**:软件包名称,默认情况下,应用ID也会使用该名称,应用发布时,应用ID需要唯一。 - - **Save Location**:工程文件本地存储路径,存储路径中不能包含中文字符和空格。 - - **Compatible API Version**:兼容的SDK版本。 - -4. 点击**Finish**,工具会自动生成示例代码和相关资源,等待工程创建完成。 - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" deleted file mode 100644 index ae738663fd4e90e5df3427c9a46dcb6755054fba..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\346\255\245\351\252\244.md" +++ /dev/null @@ -1,230 +0,0 @@ -# 开发步骤 - -应用的功能是通过表盘和数字显示实时时间。 - -从第一章节中的[显示效果图](概述-7.md#fig7763172132019)分析可知,页面由两个部分组成: - -- 表盘栏:主要展示一个动态的钟表,且钟表指针能准确转动。 -- 数字时间栏:主要以数字形式显示当前时间。 - -综上,我们可搭建一个纵向两行排列的弹性页面布局来实现界面的功能。具体开发步骤如下: - -1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: - - ``` -
-
- ``` - - class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: - - ``` - .container { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - } - ``` - - 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向两行排列的弹性页面布局。 - -2. 实现时钟转动,需要使用“stack”组件。“stack”组件的功能是堆叠容器,子组件按照顺序依次入栈,后一个子组件覆盖前一个子组件。 - - 在根组件下添加一个stack容器,代码片段如下: - - ``` -
- - - - - - -
- ``` - - style="transform : rotate\(\{\{ second \* 6 \}\}deg\) 这类代码用来设置组件的旋转事件。其中transform是设置动画平移/旋转/缩放的属性,rotate是旋转动画属性,支持设置x轴和y轴两个维度的选中参数。 - - 在css文件中设置"stack"组件样式的高度、宽度、位置等属性,代码如下: - - ``` - .stack { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 50%; - } - ``` - - 在css文件中设置"clock-bg"组件样式的高度、宽度等属性,代码如下: - - ``` - .clock-bg { - width: 80%; - height: 80%; - object-fit: scale-down; - } - ``` - - 在css文件中设置"clock-hand"组件为时针、分针和秒针的高度、宽度等属性,代码如下: - - ``` - .clock-hand { - width: 25%; - height: 65%; - object-fit: contain; - } - ``` - - index.js中会有一个定时器实时刷新时分秒变量,从而触发时间界面自动更新。对应的js代码如下: - - ``` - export default { - timer: undefined, - //定义参数 - data: { - hour: 0, //定义小时 - minute: 0, //定义分钟 - second: 0 //定义秒 - }, - onInit () { - this.updateTime(); - this.timer = setInterval(this.updateTime, 1000)//设置1s的定时器 - }, - updateTime: function () { - var nowTime = new Date() - this.hour = nowTime.getHours() - this.minute = nowTime.getMinutes() - this.second = nowTime.getSeconds() - if (this.hour < 10) { - this.hour = '0' + this.hour - } - if (this.minute < 10) { - this.minute = '0' + this.minute - } - if (this.second < 10) { - this.second = '0' + this.second - } - }, - } - ``` - -3. 显示数字时间,在钟表下面以数字形式显示当前时间。在根布局内末尾加上text组件,页面结构如下: - - ``` - {{ hour }}:{{ minute }}:{{ second }} - ``` - - class="digit-clock"设置了组件的高度和宽度以及字体大小,其代码如下: - - ``` - .digit-clock { - font-size: 58px; - width: 100%; - margin-top: 0px; - text-align: center; - } - ``` - -4. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: - - - **index.hml文件** - - ``` -
- - - - - - - {{ hour }}:{{ minute }}:{{ second }} -
- ``` - - - **index.css文件** - - ``` - .container { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 100%; - } - - .stack { - flex-direction: column; - justify-content: center; - align-items: center; - width: 100%; - height: 50%; - } - - .digit-clock { - font-size: 58px; - width: 100%; - margin-top: 0px; - text-align: center; - } - - .clock-bg { - width: 80%; - height: 80%; - object-fit: scale-down; - } - - .clock-hand { - width: 25%; - height: 65%; - object-fit: contain; - } - ``` - - - **index.js:** - - js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:定时获取系统时间。 - - ``` - export default { - timer: undefined, - data: { - hour: 0, - minute: 0, - second: 0 - }, - onInit() { - this.updateTime() - this.timer = setInterval(this.updateTime, 1000) - }, - updateTime: function () { - var nowTime = new Date() - this.hour = nowTime.getHours() - this.minute = nowTime.getMinutes() - this.second = nowTime.getSeconds() - if (this.hour < 10) { - this.hour = '0' + this.hour - } - if (this.minute < 10) { - this.minute = '0' + this.minute - } - if (this.second < 10) { - this.second = '0' + this.second - } - }, - onDestroy() { - clearInterval(this.timer); - } - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" "b/zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" deleted file mode 100755 index c80d70f94f323a6a705bb2b1dd1c5823eb490b7d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\345\217\221\351\246\226\351\241\265.md" +++ /dev/null @@ -1,581 +0,0 @@ -# 开发首页 - -应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。 - -从第一章节中的[显示效果图](概述-6.md#fig18250512195914)分析可知,首页由三部分组成: - -- 标题栏:位于页面正上方,位置固定,包括应用退出按钮和页面标题。 -- 信息栏:主要展示城市的空气信息指标等内容;该页面根据用户需求可设置多屏,且能循环滑动。 -- 页面位置指示器:主要功能是标识当前页面,位置固定在页面底部的中间。 - -综上,我们可搭建一个纵向三行排列的弹性页面布局来实现首页的功能。 - -1. 在hml文件中添加一个根节点div,注意每个hml文件中有且只能有一个根节点,代码如下: - - ``` -
-
- ``` - - class="container"表示组件使用的样式,container是index.css文件中的一个样式类,代码如下: - - ``` - .container { - flex-direction: column; - height: 480px; - width: 960px; - } - ``` - - 在这个样式类中,我们分别设置了根组件div的高度和宽度(注意在应用的开发过程中,除部分组件(text)外必须显式指定组件的高度和宽度,否则可能无法显示)、并将flex-direction属性设置为column,该属性表示div的子组件是垂直方向从上到下排列;这样就可以实现本节开头所说的纵向三行排列的弹性页面布局。 - -2. 实现标题栏:标题栏包括一个退出按钮和一个标题,两个控件是横向排列;首先添加一个div,并设置flex-direction的属性为row,表示子组件是水平方向从左往右排列;然后依次添加一个image和text组件,代码如下: - - ``` -
-
- - - 空气质量 - -
-
- ``` - - 设置组件的高度、边距、颜色等属性。 - - ``` - .header { - width: 960px; - height: 72px; - } - .back { - width: 36px; - height: 36px; - margin-left: 39px; - margin-top: 23px; - } - .title { - width: 296px; - height: 40px; - margin-top: 20px; - margin-left: 21px; - color: #e6e6e6; - } - ``` - - onclick="exitApp" 设置了div组件的click事件,当在标题栏上触发点击事件时,就会执行函数exitApp,该函数位于index.js文件中,代码如下: - - ``` - exitApp() { - console.log('start exit'); - app.terminate(); - console.log('end exit'); - } - ``` - - app.terminate\(\)函数实现了程序退出功能;在使用该函数前,需要引入app模块,在js文件的最上方写如下代码: - - ``` - import app from '@system.app' - ``` - - 代码编写完成后,在模拟器中运行项目,显示效果如下图所示: - - **图 1** 标题栏效果 - ![](figures/标题栏效果.png "标题栏效果") - -3. 实现城市空气质量信息的多屏左右滑动,需要使用“swiper”组件。 - - 在根节点中添加一个子节点swiper,代码片段如下: - - ``` -
-
- - - 空气质量 - -
- - -
- ``` - - - class="swiper"设置了组件的高度和宽度,代码如下: - - ``` - .swiper { - height: 385px; - width: 960px; - } - ``` - - - - index="\{\{swiperPage\}\}" duration="500" onchange="swiperChange" 这些代码用来设置组件的属性和事件。其中,duration="500" 表示设置swiper的页面滑动的动画时长为500ms。 - - index="\{\{swiperPage\}\}"设置了swiper子组件索引值,\{\{swiperPage\}\}这种写法表示index的值是和js代码中的swiperPage变量动态绑定的,index的值会随着swiperPage变动而改变。 - - onchange="swiperChange" 设置了swiper组件的change事件和函数swiperChange绑定,对应的js代码如下: - - ``` - //引入router模块,用户页面跳转 - import router from'@system.router' - import app from '@system.app' - - export default { - //定义参数 - data: { - //默认是第一页 - swiperPage: 0 - }, - onInit () { - }, - exitApp(){ - console.log('start exit'); - app.terminate(); - console.log('end exit'); - }, - //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中 - swiperChange (e) { - this.swiperPage = e.index; - } - } - ``` - - -4. 设置一个城市的空气质量信息为一屏,在一屏内,要展示多种信息,分别使用不同的控件进行展示。 - - 在swiper中添加两个子组件stack(绝对布局),每个stack组件内分别添加text、image、progress等组件来显示对应的信息 ,页面结构如下: - - ``` - - - - ------空气质量 - ------城市名称 - -----进度条 - -------云朵图片 - --------AQI数值 - AQI------AQI -
--------空气指标详细信息 -
-
--------更新时间和网站等信息 -
-
- - - - - - - - -
-
-
- ``` - - 代码编写完成后,模拟器运行效果如下: - - **图 2** 标题栏和信息栏效果 - ![](figures/标题栏和信息栏效果.png "标题栏和信息栏效果") - -5. 添加页面位置指示器:由于当前swiper不支持设置indicator,需要开发者自己来实现该效果。在根节点中添加一个子组件div,并设置相应样式;然后在该div中添加两个子组件div,设置两个div的border-radius,并在swiper滑动事件中动态改变对应div的背景色来实现该效果。 - - ``` -
-
-
-
- ``` - - **图 3** 页面位置指示器效果图 - ![](figures/页面位置指示器效果图.png "页面位置指示器效果图") - -6. 所有组件设置样式、动画效果和数据动态绑定,完整代码如下所示: - - - **index.hml文件** - - ``` -
-
- - - 空气质量 - -
- - - {{airData[0].airQuality}} - - {{airData[0].location}} - - - - {{airData[0].detailData}} - - - AQI - -
-
- - CO - - - 100 - -
-
- - NO2 - - - 90 - -
-
- - PM10 - - - 120 - -
-
- - PM2.5 - - - 40 - -
-
- - SO2 - - - 150 - -
- -
- -
- - {{airData[1].airQuality}} - - {{airData[1].location}} - - - - {{airData[1].detailData}} - - - AQI - -
-
- - CO - - - 10 - -
-
- - NO2 - - - 50 - -
-
- - PM10 - - - 60 - -
-
- - PM2.5 - - - 40 - -
-
- - SO2 - - - 150 - -
- -
- -
-
-
-
-
-
-
- ``` - - - **index.css文件** - - css文件中定义了许多class,每个class用于定义组件的位置、大小、字体、颜色、背景色等信息。同时,每一个子组件都叠加在父组件中,父组件的样式会影响子组件的呈现。 - - ``` - .aqi-value { - text-align: center; - font-size: 65px; - color: #f0ffff; - width: 156px; - height: 92px; - top: 134px; - left: 210px; - } - .aqi { - text-align: center; - color: #a2c4a2; - width: 156px; - height: 45px; - top: 90px; - left: 210px; - } - .airquality { - top: 222px; - text-align: center; - width: 156px; - height: 45px; - left: 210px; - } - .image { - top: 285px; - left: 274px; - width: 32px; - height: 32px; - } - .location-text { - text-align: center; - color: #ffffff; - width: 200px; - height: 52px; - font-size: 40px; - left: 380px; - top: 16px; - } - .container { - flex-direction: column; - height: 480px; - width: 960px; - } - .circle-progress { - center-x: 128px; - center-y: 128px; - radius: 128px; - startAngle: 198; - totalAngle: 320; - strokeWidth: 24px; - width: 256px; - height: 256px; - left: 160px; - top: 58px; - } - .detail { - width: 256px; - height: 265px; - left: 544px; - top: 58px; - flex-direction: column; - } - .text-wrapper { - width: 256px; - height: 35px; - margin-top: 6px; - } - .gas-name { - width: 128px; - height: 35px; - text-align: left; - } - .gas-value { - width: 128px; - height: 35px; - text-align: right; - } - .btn { - width: 180px; - height: 50px; - margin-top: 6px; - margin-left: 38px; - background-color: #1a1a1a; - color: #1085CE; - } - .footer { - top: 326px; - width: 960px; - height: 28px; - } - .header { - width: 960px; - height: 72px; - } - .back { - width: 36px; - height: 36px; - margin-left: 39px; - margin-top: 23px; - } - .title { - width: 296px; - height: 40px; - margin-top: 20px; - margin-left: 21px; - color: #e6e6e6; - } - .swiper { - height: 385px; - width: 960px; - } - .images { - width: 60px; - height: 15px; - margin-left: 450px; - } - .update-time { - width: 480px; - height: 28px; - font-size: 20px; - color: #A9A9A9; - text-align: right; - } - .info-source { - width: 450px; - height: 28px; - font-size: 20px; - color: #A9A9A9; - text-align: left; - margin-left: 24px; - } - .circle-div { - width: 12px; - height: 12px; - border-radius: 6px; - } - ``` - - - **index.js:** - - js文件主要用于实现App应用的逻辑交互。在本页面js文件中,需要实现如下功能:根据数值动态改变文字、进度条颜色、页面跳转。 - - ``` - //导入router和app模块 - import router from '@system.router' - import app from '@system.app' - - export default { - data: { - //页面绑定数据 - textColor1: '#00ff00', - textColor2: '#00ff00', - bgColor1: '#669966', - bgColor2: '#669966', - swiperPage: 0, - percent1: 40, - percent2: 90, - iconUncheckedColor: '#262626', - iconcheckedColor: '#ffffff', - iconcheckedBR: '6px', - src1: 'common/cloud_green.png', - src2: 'common/cloud_green.png', - airData: [{ - location: '东莞', - airQuality: '良', - detailData: 40 - }, { - location: '深圳', - airQuality: '差', - detailData: 90 - }] - }, - onInit () { - //根据数值的不同,设置不同的字体、背景颜色和图片 - if(this.airData[0].detailData > 100){ - this.src1 = 'common/cloud_red.png'; - this.textColor1 = '#ff0000'; - this.bgColor1 = '#9d7462'; - } else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){ - this.src1 = 'common/cloud_yellow.png'; - this.textColor1 = '#ecf19a'; - this.bgColor1 = '#9d9d62'; - } - if(this.airData[1].detailData > 100){ - this.src2 = 'common/cloud_red.png'; - this.textColor2 = '#ff0000'; - this.bgColor2 = '#9d7462'; - } else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){ - this.src2 = 'common/cloud_yellow.png'; - this.textColor2 = '#ecf19a'; - this.bgColor2 = '#9d9d62'; - } - if(this.selectedCityIndex){ - this.swiperPage = this.selectedCityIndex; - if(this.swiperPage == 0){ - this.iconcheckedColor = '#ffffff'; - this.iconUncheckedColor = '#262626'; - }else{ - this.iconcheckedColor = '#262626'; - this.iconUncheckedColor = '#ffffff'; - } - } - }, - //跳转到详情页面 - openDetail () { - router.replace({ - uri: 'pages/detail/detail', - params: {selectedCityIndex:this.swiperPage} - }); - }, - //退出应用 - exitApp(){ - console.log('start exit'); - app.terminate(); - console.log('end exit'); - }, - //页面滑动事件,滑动时改变最新的标识 - swiperChange (e) { - this.swiperPage = e.index; - if(e.index == 0){ - this.iconcheckedColor = '#ffffff'; - this.iconUncheckedColor = '#262626'; - }else{ - this.iconcheckedColor = '#262626'; - this.iconUncheckedColor = '#ffffff'; - } - } - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" "b/zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" deleted file mode 100644 index 469d6a3566fe136c2bb59993abde4b12551e4c03..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\345\274\200\346\234\272\346\227\245\345\277\227\345\210\206\346\236\220.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 开机日志分析 - -如下所示为开机启动日志部分截取 - -``` -[I/HDF_INPUT_DRV] HdfInputManagerInit: enter // 管理驱动层初始化 -[I/HDF_INPUT_DRV] HdfInputManagerInit: exit succ // 初始化成功 -[I/osal_cdev] add cdev hdf_input_host success -[I/HDF_LOG_TAG] HdfTouchDriverProbe: enter // 公共驱动层初始化 -[I/HDF_LOG_TAG] HdfTouchDriverProbe: main_touch exit succ // 初始化成功 -[I/osal_cdev] add cdev hdf_input_event1 success -[I/HDF_INPUT_DRV] HdfGoodixChipInit: enter // 器件驱动层初始化 -[I/HDF_INPUT_DRV] ChipDetect: IC FW version is 0x1060 -[I/HDF_INPUT_DRV] Product_ID: 911_1060, x_sol = 960, y_sol = 480 -[I/HDF_LOG_TAG] ChipDriverInit: chipDetect succ, ret = 0 -[I/HDF_LOG_TAG] InputDeviceInstance: inputDev->devName = main_touch -[I/HDF_INPUT_DRV] HdfGoodixChipInit: exit succ, chipName = gt911 // 初始化成功 -``` - diff --git "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" "b/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" deleted file mode 100755 index 83e445c0ed119ba040d2544e9793831a2cd2b05b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274-3.md" +++ /dev/null @@ -1,395 +0,0 @@ -# 拍照开发指导 - -- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) -- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) -- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) -- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) - -## 使用场景 - -使用Camera产生图片帧(拍照)。 - -## 接口说明 - -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

类名

-

接口名

-

描述

-

CameraKit

-

int32_t GetCameraIds(std::list<string> cameraList)

-

获取cameraId列表

-

CameraKit

-

CameraAbility& GetCameraAbility(string cameraId)

-

获取指定camera的能力

-

CameraKit

-

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

-

注册camera设备状态回调

-

CameraKit

-

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

-

去注册camera设备状态回调

-

CameraKit

-

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

-

创建camera实例

-

Camera

-

string GetCameraId()

-

获取cameraID

-

Camera

-

CameraConfig& GetCameraConfig()

-

获取camera配置信息

-

Camera

-

FrameConfig& GetFrameConfig(int32_t type)

-

获取捕获帧类型

-

Camera

-

void Configure(CameraConfig& config)

-

配置camera

-

Camera

-

void Release()

-

释放camera

-

Camera

-

int TriggerLoopingCapture(FrameConfig& frameConfig)

-

开始循环帧捕获

-

Camera

-

void StopLoopingCapture()

-

停止循环帧捕获

-

Camera

-

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

-

抓图

-

CameraConfig

-

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

-

设置帧状态回调

-

CameraConfig

-

static CameraConfig* CreateCameraConfig()

-

创建camera配置信息实例

-

CameraAbility

-

std::list<Size> GetSupportedSizes(int format)

-

根据类型获取支持输出图像尺寸大小

-

CameraAbility

-

std::list<T> GetParameterRange(uint32_t key)

-

获取支持的参数范围

-

CameraDevice

-

CameraDeviceCallback()

-

camera设备回调类构造函数

-

CameraDevice

-

void OnCameraStatus​(std::string cameraId, int32_t status)

-

camera设备状态变化时的回调

-

CameraStateCallback

-

CameraStateCallback​()

-

camera状态回调类构造函数

-

CameraStateCallback

-

void OnConfigured​(Camera& camera)

-

camera配置成功回调

-

CameraStateCallback

-

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

-

camera配置失败回调

-

CameraStateCallback

-

void OnCreated​(Camera& camera)

-

camera创建成功回调

-

CameraStateCallback

-

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

-

camera创建失败回调

-

CameraStateCallback

-

void OnReleased​(Camera& camera)

-

camera释放回调

-

FrameStateCallback

-

FrameStateCallback​()

-

帧状态回调类构造函数

-

FrameStateCallback

-

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

-

拍照帧完成回调

-

FrameStateCallback

-

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

-

拍照帧异常回调

-

FrameConfig

-

int32_t GetFrameConfigType()

-

获取帧配置类型

-

FrameConfig

-

std::list<OHOS::Surface> GetSurfaces()

-

获取帧配置的surface

-

FrameConfig

-

void AddSurface(OHOS::AGP::UISurface& surface);

-

添加surface

-

FrameConfig

-

void RemoveSurface(OHOS::AGP::UISurface& surface);

-

删除surface

-
- -## 约束与限制 - -无。 - -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - camKit->CreateCamera(camId, CamStateMng, eventHdlr); - ``` - -6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index e59c365a5c6fe2e58a8333157758418d1508175c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,395 +0,0 @@ -# 拍照开发指导 - -- [使用场景](#zh-cn_topic_0000001052170554_section1963312376119) -- [接口说明](#zh-cn_topic_0000001052170554_section56549532016) -- [约束与限制](#zh-cn_topic_0000001052170554_section1165911177314) -- [开发步骤](#zh-cn_topic_0000001052170554_section138543918214) - -## 使用场景 - -使用Camera产生图片帧(拍照)。 - -## 接口说明 - -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

类名

-

接口名

-

描述

-

CameraKit

-

int32_t GetCameraIds(std::list<string> cameraList)

-

获取cameraId列表

-

CameraKit

-

CameraAbility& GetCameraAbility(string cameraId)

-

获取指定camera的能力

-

CameraKit

-

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

-

注册camera设备状态回调

-

CameraKit

-

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

-

去注册camera设备状态回调

-

CameraKit

-

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

-

创建camera实例

-

Camera

-

string GetCameraId()

-

获取cameraID

-

Camera

-

CameraConfig& GetCameraConfig()

-

获取camera配置信息

-

Camera

-

FrameConfig& GetFrameConfig(int32_t type)

-

获取捕获帧类型

-

Camera

-

void Configure(CameraConfig& config)

-

配置camera

-

Camera

-

void Release()

-

释放camera

-

Camera

-

int TriggerLoopingCapture(FrameConfig& frameConfig)

-

开始循环帧捕获

-

Camera

-

void StopLoopingCapture()

-

停止循环帧捕获

-

Camera

-

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

-

抓图

-

CameraConfig

-

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

-

设置帧状态回调

-

CameraConfig

-

static CameraConfig* CreateCameraConfig()

-

创建camera配置信息实例

-

CameraAbility

-

std::list<Size> GetSupportedSizes(int format)

-

根据类型获取支持输出图像尺寸大小

-

CameraAbility

-

std::list<T> GetParameterRange(uint32_t key)

-

获取支持的参数范围

-

CameraDevice

-

CameraDeviceCallback()

-

camera设备回调类构造函数

-

CameraDevice

-

void OnCameraStatus​(std::string cameraId, int32_t status)

-

camera设备状态变化时的回调

-

CameraStateCallback

-

CameraStateCallback​()

-

camera状态回调类构造函数

-

CameraStateCallback

-

void OnConfigured​(Camera& camera)

-

camera配置成功回调

-

CameraStateCallback

-

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

-

camera配置失败回调

-

CameraStateCallback

-

void OnCreated​(Camera& camera)

-

camera创建成功回调

-

CameraStateCallback

-

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

-

camera创建失败回调

-

CameraStateCallback

-

void OnReleased​(Camera& camera)

-

camera释放回调

-

FrameStateCallback

-

FrameStateCallback​()

-

帧状态回调类构造函数

-

FrameStateCallback

-

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

-

拍照帧完成回调

-

FrameStateCallback

-

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

-

拍照帧异常回调

-

FrameConfig

-

int32_t GetFrameConfigType()

-

获取帧配置类型

-

FrameConfig

-

std::list<OHOS::Surface> GetSurfaces()

-

获取帧配置的surface

-

FrameConfig

-

void AddSurface(OHOS::AGP::UISurface& surface);

-

添加surface

-

FrameConfig

-

void RemoveSurface(OHOS::AGP::UISurface& surface);

-

删除surface

-
- -## 约束与限制 - -无。 - -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - camKit->CreateCamera(camId, CamStateMng, eventHdlr); - ``` - -6. 根据[步骤1](#zh-cn_topic_0000001052170554_li378084192111)、[步骤2](#zh-cn_topic_0000001052170554_li8716104682913)、[步骤3](#zh-cn_topic_0000001052170554_li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - - diff --git "a/zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" "b/zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" deleted file mode 100755 index 65f7df79807efc4e7fb9d33879b707e1d6ec1ce3..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\221\204\345\203\217\345\244\264\346\216\247\345\210\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 摄像头控制 - -- **[概述](概述-0.md)** - -- **[示例开发](示例开发.md)** - -- **[应用实例](应用实例.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" "b/zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" deleted file mode 100755 index 7d723b1bfd0ea849891a1cc8faade79f4802c0d2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\227\240\345\261\217\346\221\204\345\203\217\345\244\264\347\261\273\344\272\247\345\223\201.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 无屏摄像头类产品 - -- **[摄像头控制](摄像头控制.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100644 index 3cbff6960f629645fc6f4cca541d7e0dcbee0722..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\227\266\351\222\237\345\272\224\347\224\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 时钟应用开发示例 - -- **[概述](概述-7.md)** - -- **[开发准备](开发准备-8.md)** - -- **[开发步骤](开发步骤.md)** - -- **[签名打包](签名打包.md)** - -- **[真机运行](真机运行-9.md)** - -- **[常见问题](常见问题-10.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" deleted file mode 100755 index e3d5da250e043ac86136b0d8ad5a220f946fefc2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,10 +0,0 @@ -# 概述 - -本文档将介绍如何基于IoT Camera开发板,利用开发套件中自带的摄像头,完成拍照、录像功能。 - -开发者可通过执行示例应用,对开发板的外设控制有了更深入了解后,可使用开发板完成摄像头等设备。 - -若开发者想先查看示例效果,请进入[应用实例](应用实例.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 - -相机开发基本概念可参考:[相机开发概述](../subsystems/相机开发概述.md)。 - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" deleted file mode 100755 index f265cdb276c1d92bf06280ad54ba3fb5f210f46d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-1.md" +++ /dev/null @@ -1,10 +0,0 @@ -# 概述 - -本文档将介绍如何基于IoT Camera开发板(Hi3516DV300),利用其摄像头和屏幕,完成拍照、录像和视频预览功能。 - -通过本文档,开发者能够对OpenHarmony的摄像控制有更深入的了解,可参照本例尝试完成“智能猫眼”、“智能后视镜”、“智能带屏音箱”等设备的开发。 - -若开发者想先查看示例效果,请进入[应用实例](应用实例-5.md)。如需自定义应用行为,可参考下节“示例开发”对示例代码进行修改。 - -相机应用开发的基本概念请参考:[相机开发概述](../subsystems/相机开发概述.md)。 - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" deleted file mode 100644 index 16734e3f17205895f57f82921da60c53d475f77a..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-10.md" +++ /dev/null @@ -1,26 +0,0 @@ -# 概述 - -- [场景介绍](#section191543223549) - -本文档将以I2C驱动为例,介绍如何基于HDF驱动框架完成平台驱动开发。 - ->![](public_sys-resources/icon-caution.gif) **注意:** ->本例仅作为平台驱动开发示例参考,开发者不可直接用于商用集成。 - -## 场景介绍 - -HDF驱动框架为常用外围设备提供了标准的驱动框架,驱动开发者只需将驱动适配至HDF驱动框架,即可通过HDF驱动框架提供的接口操作外围设备。 - -本文以I2C为例。其时序流程如[图1](#fig148041484161)所示。 - -**图 1** I2C时序流程图 - - -![](figures/zh-cn_image_0000001161922745.png) - -- User Business:用户业务驱动。 -- i2cManagerEntry:I2C管理器入口,注册I2cManager到HDF驱动框架。 -- I2cManager:I2C管理器,管理I2C控制器。 -- I2cCntlr:I2C控制器。 -- i2cDriverEntry:I2C控制器入口,注册I2cCntlr到HDF驱动框架。 - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" deleted file mode 100644 index 0606b801b5eb33741f1c9cb78d67edf52318712a..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-12.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 概述 - -本文档将介绍如何基于Hi3516DV300开发板完成基于HDF\_Input模型的触摸屏器件驱动开发,从而使开发者快速入门,进行基于的外设驱动开发。 - -- **[硬件资源介绍](硬件资源介绍.md)** - -- **[Input模型简介](Input模型简介.md)** - - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" deleted file mode 100755 index 7f8de10aa751682d4f464e131f414fd2f1c920ce..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-6.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 概述 - -- [效果展示](#section3997224182313) - -本文将介绍如何快速搭建基于OpenHarmony系统的行车记录仪(Hi3516DV300开发板)应用开发环境,并基于一个简易的APP示例逐步展示应用的创建、开发、调试和安装等流程。接下来本文以空气质量监测(AirQuality)App为例进行说明。 - -## 效果展示 - -空气质量监测App是一款展示城市空气质量信息的应用,有两个页面组成:首页和详情页,在DevEco Studio模拟器中的显示效果如下图所示: - -**图 1** 空气质量监测 App显示效果图 - - -![](figures/Video_2020-07-25_173141.gif) - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" deleted file mode 100755 index e032aa00bcccc4972464e760e165742db5ffdf61..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260-7.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 概述 - -- [效果展示](#section3997224182313) - -本文将介绍如何快速搭建基于OpenHarmony标准系统(Hi3516DV300开发板)的应用开发环境,并基于一个时钟APP示例逐步展示应用的创建、开发、调试和安装等流程。示例代码可以通过[本链接](https://gitee.com/openharmony/app_samples/tree/master/common/Clock)获取。 - -## 效果展示 - -时钟App是一款显示实时时间的应用,显示效果如下图所示: - -**图 1** 时钟应用显示效果图 - - -![](figures/Clock.png) - diff --git "a/zh-cn/device-dev/guide/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/guide/\346\246\202\350\277\260.md" deleted file mode 100755 index 875da92ed1dd39a87faab8a658718423a7ce9d1f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 概述 - -OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力,包含I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。本文介绍如何通过调用OpenHarmony的NDK接口,实现对GPIO控制,达到LED闪烁的效果。其他的IOT外设控制,开发者可根据API指导文档完成,此处不逐一介绍。 - diff --git "a/zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" "b/zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" deleted file mode 100755 index 8733bfb1e6d4795483ae7e763c0e6fed857fdc64..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\346\267\273\345\212\240\351\241\265\351\235\242.md" +++ /dev/null @@ -1,34 +0,0 @@ -# 添加页面 - -- [创建首页面](#section16935511143715) -- [创建详情页](#section122131729173819) - -## 创建首页面 - -空气质量监测App包含两个界面(Page),工程创建完成后会生成一个名为index的Page,可以作为首页。工程目录如下图所示: - -**图 1** 工程目录 -![](figures/工程目录.png "工程目录") - -## 创建详情页 - -新增一个Page,作为详情页,具体步骤如下: - -1. pages目录右键 ,弹出的菜单中选择New、JS Page。 - - **图 2** 添加页面 - ![](figures/添加页面.png "添加页面") - -2. 输入Page名称。 - - **图 3** 输入页面名称 - ![](figures/输入页面名称.png "输入页面名称") - -3. 确认创建结果。 - - 详情页创建完成后应用工程目录如下图所示,每个Page包括三个文件:布局文件hml、样式文件css、业务逻辑代码js。 - - **图 4** 完整工程目录 - ![](figures/完整工程目录.png "完整工程目录") - - diff --git "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100644 index c6ae1a18427ed3bdec92f853ac9d49905d4901a5..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 环境准备 - -环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/标准系统入门.md)。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 - diff --git "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" "b/zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" deleted file mode 100644 index 381ddaa88c0c7136b378691ceae0f1594d54aec7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\216\257\345\242\203\346\220\255\345\273\272.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 环境搭建 - -环境准备具体操作请参考[标准系统基础环境搭建](../quick-start/标准系统入门.md)。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本示例针对OpenHarmony轻量系统、小型系统、标准系统都适用,本文以标准系统为例。其他系统的开发者可参考对应系统的指导文档进行环境搭建。 - diff --git "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" "b/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" deleted file mode 100644 index 30bb3b0801d1ea859f8e3a64d956fbeb91f0e381..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214-9.md" +++ /dev/null @@ -1,35 +0,0 @@ -# 真机运行 - -应用签名打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),然后将OpenHarmony系统烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[标准系统Hi3516快速入门](../quick-start/标准系统入门.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载应用。 - -1. 从开发者工具代码仓路径中获取hdc客户端。 - - ``` - developtools/hdc_standard/prebuilt/windows/hdc_std.exe - ``` - - 修改名称为hdc.exe,并将工具路径加入系统环境path变量中。 - -2. 启动cmd命令窗口,执行以下命令,推送hap应用包到设备目录下并安装。 - - ``` - hdc smode - hdc target mount - hdc file send clock.hap /data/clock.hap - hdc shell chmod 666 /data/clock.hap - hdc shell bm install -p /data/clock.hap - ``` - -3. 启动应用。执行以下命令,其中ohos.samples.clock为应用包名,MainAbility为应用启动的Ability。 - - ``` - hdc shell aa start -d 123 -a ohos.samples.clock.MainAbility -b ohos.samples.clock - ``` - -4. 卸载应用(可选)。执行以下命令,其中ohos.samples.clock为应用包名。 - - ``` - hdc shell bm uninstall -n ohos.samples.clock - ``` - - diff --git "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" "b/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" deleted file mode 100755 index 973019fcce8af2d9c0fde13a096d5c4067df3e6d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\234\237\346\234\272\350\277\220\350\241\214.md" +++ /dev/null @@ -1,29 +0,0 @@ -# 真机运行 - -应用编译打包后即可安装到开发板。安装应用前需要先完成[DevEco Device Tool的安装配置](https://device.harmonyos.com/cn/docs/ide/user-guides/tool_install-0000001050164976),然后将OpenHarmony烧录到开发板并运行。编译烧录、运行镜像的基本操作请参考快速入门手册:[Hi3516快速入门](../quick-start/Hi3516开发板介绍.md)。完成镜像运行,系统正常启动后,执行如下步骤安装或卸载三方应用。 - -1. 将IDE编译的未签名应用安装包和安装工具(镜像文件生成目录中的dev\_tools)放在sdcard中,将sdcard插入开发板卡槽。 -2. 应用安装默认要校验签名,需要执行以下命令,关闭签名校验。 - - ``` - ./sdcard/dev_tools/bin/bm set -s disable - ``` - -3. 执行以下命令,安装应用。 - - ``` - ./sdcard/dev_tools/bin/bm install -p /sdcard/airquality.hap - ``` - - 其中dev\_tools目录中是安装工具,airquality.hap为应用安装包,此处替换为实际工程的安装包名称。 - -4. 应用安装完成后,可点击桌面应用图标启动应用,进行操作。 - - **图 1** 桌面 - ![](figures/桌面.png "桌面") - -5. 卸载应用(可选)。 - - 长按桌面应用图标,在弹出的菜单中点击“卸载”按钮即可卸载应用。 - - diff --git "a/zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" "b/zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" deleted file mode 100644 index 18b33bd5af0271b644fe30b8585e3f6be22a3b55..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\241\254\344\273\266\350\265\204\346\272\220\344\273\213\347\273\215.md" +++ /dev/null @@ -1,6 +0,0 @@ -# 硬件资源介绍 - -Hi3516DV300开发板套件所提供的触摸屏器件IC为GT911,该器件采用标准I2C与主机通信,通过6pin软排线与主板连接。6pin分布以及实物连接图如下图所示: - -![](figures/绘图1.png) - diff --git "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" "b/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" deleted file mode 100755 index eb01bec406aeb05019daeeb14148eaf702bfc598..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221-2.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 示例开发 - -- **[拍照开发指导](拍照开发指导-3.md)** - -- **[录像开发指导](录像开发指导-4.md)** - -- **[预览开发指导](预览开发指导.md)** - - diff --git "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" deleted file mode 100755 index e8128ecaaca0f0b5311d51b7e8f1cd8dc01c00a0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\244\272\344\276\213\345\274\200\345\217\221.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 示例开发 - -- **[拍照开发指导](拍照开发指导.md)** - -- **[录像开发指导](录像开发指导.md)** - - diff --git "a/zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" "b/zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" deleted file mode 100644 index a472a6dfdfba6d50c291b37dcc1718f56dabaaed..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\247\201\346\234\211\351\205\215\347\275\256\344\277\241\346\201\257\350\247\243\346\236\220.md" +++ /dev/null @@ -1,17 +0,0 @@ -# 私有配置信息解析 - -示例代码路径:./drivers/framework/model/input/driver/input\_config\_parser.c - -根据OSAL提供的配置解析函数,可以将hcs文件中各字段含义进行解析,具体请参考input\_config\_parser.c中各函数的实现。如果提供的模板不能满足需求,在hcs文件中添加相应信息后,需要根据添加的字段开发相应的解析函数。 - -``` -static int32_t ParseAttr(struct DeviceResourceIface *parser, const struct DeviceResourceNode *attrNode, BoardAttrCfg *attr) -{ - int32_t ret; - ret = parser->GetUint8(attrNode, "inputType", &attr->devType, 0); // 获取inputType字段信息,保存在BoardAttrCfg结构体中 - CHECK_PARSER_RET(ret, "GetUint8"); - ... - return HDF_SUCCESS; -} -``` - diff --git "a/zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" "b/zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" deleted file mode 100644 index a6fd6f965525ad87ae4b3be7b1987a97ddc0fa39..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\255\276\345\220\215\346\211\223\345\214\205.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 签名打包 - -代码编写完成后,在真机设备上运行应用,需要先对应用进行签名,然后再进行打包,具体操作请参考[签名打包指导](../../application-dev/quick-start/配置OpenHarmony应用签名信息.md)。 - diff --git "a/zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" "b/zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" deleted file mode 100644 index 73b05bf0b039741952505f3c30c5440a28c1e25b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\256\241\347\220\206\351\251\261\345\212\250\345\261\202\345\210\235\345\247\213\345\214\226\345\217\212\346\263\250\345\206\214\351\251\261\345\212\250\350\207\263HDF\346\241\206\346\236\266.md" +++ /dev/null @@ -1,22 +0,0 @@ -# 管理驱动层初始化及注册驱动至HDF框架 - -示例代码路径:./drivers/framework/model/input/driver/hdf\_input\_device\_manager.c - -``` -static int32_t HdfInputManagerInit(struct HdfDeviceObject *device) -{ - /* 分配内存给manager,manager中将存放所有input设备 */ - g_inputManager = InputManagerInstance(); - ... -} -struct HdfDriverEntry g_hdfInputEntry = { - .moduleVersion = 1, - .moduleName = "HDF_INPUT_MANAGER", - .Bind = HdfInputManagerBind, - .Init = HdfInputManagerInit, - .Release = HdfInputManagerRelease, -}; - -HDF_INIT(g_hdfInputEntry); //驱动注册入口 -``` - diff --git "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" "b/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" deleted file mode 100644 index 587404009f050d03eeb8b95d221ea1beb2f3e062..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225-13.md" +++ /dev/null @@ -1,17 +0,0 @@ -# 编译及烧录 - -1. 编辑Makefile文件,添加本示例中的内容: - - 文件路径:./drivers/adapter/khdf/linux/model/input/Makefile - - 添加内容如下: - - ``` - obj-$(CONFIG_DRIVERS_HDF_TP_5P5_GT911) += \ - $(INPUT_ROOT_DIR)/touchscreen/touch_gt911.o - ``` - - 其中touch\_gt911.o为本示例中追加的内容。 - -2. 具体编译及烧录操作请参考[标准系统快速入门编译及烧录章节](../quick-start/标准系统入门.md)。 - diff --git "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" "b/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" deleted file mode 100644 index 92d839390d5dcacac6fdc98cb576d3e6312a0c69..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\347\274\226\350\257\221\345\217\212\347\203\247\345\275\225.md" +++ /dev/null @@ -1,20 +0,0 @@ -# 编译及烧录 - -1. 编辑Makefile,添加源文件: - - ``` - include drivers/hdf/khdf/platform/platform.mk - - obj-y += $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_core.o \ - $(HDF_PLATFORM_FRAMEWORKS_ROOT)/src/i2c_if.o \ - ./i2c_adapter.o \ - ./i2c_sample.o - ``` - - "./i2c\_sample.o"为本示例中在Makefile中追加的内容。 - -2. 编译及烧录。 - - 具体操作请参考[标准系统快速入门编译及烧录章节](../quick-start/标准系统入门.md)。 - - diff --git "a/zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" "b/zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" deleted file mode 100755 index b4a8975ab2b1883c7e69e324500c9fc516bb9b7e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\350\247\206\350\247\211\345\272\224\347\224\250\345\274\200\345\217\221.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 视觉应用开发 - -- **[概述](概述-6.md)** - -- **[开发准备](开发准备.md)** - -- **[添加页面](添加页面.md)** - -- **[开发首页](开发首页.md)** - -- **[开发详情页](开发详情页.md)** - -- **[调试打包](调试打包.md)** - -- **[真机运行](真机运行.md)** - -- **[常见问题](常见问题.md)** - - diff --git "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" "b/zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" deleted file mode 100755 index 5015bd5755d4a5750aeeac6e699c6d8070dc9827..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\346\211\223\345\214\205.md" +++ /dev/null @@ -1,4 +0,0 @@ -# 调试打包 - -代码编写完成后,可以进行调试和打包;应用调试及打包方法可以参考[《DevEco Studio使用指南》](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/tools_overview-0000001053582387)的[应用调测](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/debug_overview-0000001053822404)和[编译构建](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)章节。IPCamera应用暂时不支持签名模式,所以需要将应用发布为未签名的应用安装包。 - diff --git "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" "b/zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" deleted file mode 100644 index f339b20a630cc498481d71394a3f46225e537dfa..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\350\260\203\350\257\225\351\252\214\350\257\201.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 调试验证 - -- **[开机日志分析](开机日志分析.md)** - - diff --git "a/zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" "b/zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" deleted file mode 100644 index b719de9bacbb19722563054b8aafa6584550bf1c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\351\200\202\351\205\215\345\231\250\344\273\266\347\247\201\346\234\211\351\251\261\345\212\250.md" +++ /dev/null @@ -1,99 +0,0 @@ -# 适配器件私有驱动 - -Input模型由三层驱动组成,开发者适配一款全新触摸屏驱动只需要适配器件驱动层即可,重点实现差异化接口,本小节以代码示例的形式展示开发者需要重点完成的工作。 - -1. 触摸屏器件差异化接口适配 - - 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c - - ``` - static struct TouchChipOps g_gt911ChipOps = { // 器件IC接口 - .Init = ChipInit, // 初始化 - .Detect = ChipDetect, // 器件检测 - .Resume = ChipResume, // 唤醒 - .Suspend = ChipSuspend, // 休眠 - .DataHandle = ChipDataHandle, // 器件数据读取 - .UpdateFirmware = UpdateFirmware, // 固件升级 - }; - - /* 不同触摸屏厂家使用的IC不一样,对应的寄存器操作也不一样,因此器件驱动层代码重点适配差异化接口部分,如下示例代码展示了GT911的数据解析*/ - - static int32_t ChipDataHandle(ChipDevice *device) - { - ... - /* GT911获取坐标之前需先读取状态寄存器 */ - reg[0] = (GT_BUF_STATE_ADDR >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_BUF_STATE_ADDR & ONE_BYTE_MASK; - ret = InputI2cRead(i2cClient, reg, GT_ADDR_LEN, &touchStatus, 1); - if (ret < 0 || touchStatus == GT_EVENT_INVALID) { - return HDF_FAILURE; - } - ... - /* 根据状态寄存器的值读取数据寄存器数据 */ - reg[0] = (GT_X_LOW_BYTE_BASE >> ONE_BYTE_OFFSET) & ONE_BYTE_MASK; - reg[1] = GT_X_LOW_BYTE_BASE & ONE_BYTE_MASK; - pointNum = touchStatus & GT_FINGER_NUM_MASK; - if (pointNum == 0 || pointNum > MAX_SUPPORT_POINT) { - HDF_LOGE("%s: pointNum is invalid, %u", __func__, pointNum); - (void)ChipCleanBuffer(i2cClient); - OsalMutexUnlock(&device->driver->mutex); - return HDF_FAILURE; - } - frame->realPointNum = pointNum; - frame->definedEvent = TOUCH_DOWN; - (void)InputI2cRead(i2cClient, reg, GT_ADDR_LEN, buf, GT_POINT_SIZE * pointNum); - /* 对获取的数据进行解析 */ - ParsePointData(device, frame, buf, pointNum); - ... - } - static void ParsePointData(ChipDevice *device, FrameData *frame, uint8_t *buf, uint8_t pointNum) - { - ... - /* 每个坐标值由两个字节组成,对获取的单字节数据进行拼接得到最终的坐标值 */ - for (i = 0; i < pointNum; i++) { - frame->fingers[i].trackId = buf[GT_POINT_SIZE * i + GT_TRACK_ID]; - frame->fingers[i].y = (buf[GT_POINT_SIZE * i + GT_X_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_X_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - frame->fingers[i].x = (buf[GT_POINT_SIZE * i + GT_Y_LOW] & ONE_BYTE_MASK) | - ((buf[GT_POINT_SIZE * i + GT_Y_HIGH] & ONE_BYTE_MASK) << ONE_BYTE_OFFSET); - /* 对解析出来的坐标值进行打印 */ - HDF_LOGD("%s: x = %d, y = %d", __func__, frame->fingers[i].x, frame->fingers[i].y); - } - } - ``` - -2. 器件层驱动初始化及注册驱动至HDF框架 - - 示例代码路径:./drivers/framework/model/input/driver/touchscreen/touch\_gt911.c - - ``` - static int32_t HdfGoodixChipInit(struct HdfDeviceObject *device) - { - ... - /* 器件配置结构体内存申请、配置信息解析及挂载 */ - chipCfg = ChipConfigInstance(device); - ... - /* 器件实例化 */ - chipDev = ChipDeviceInstance(); - ... - /* 器件信息挂载及器件私有操作挂载 */ - chipDev->chipCfg = chipCfg; - chipDev->ops = &g_gt911ChipOps; - ... - /* 注册器件驱动至平台驱动 */ - RegisterChipDevice(chipDev); - ... - } - struct HdfDriverEntry g_touchGoodixChipEntry = { - .moduleVersion = 1, - .moduleName = "HDF_TOUCH_GT911", // 该moduleName与device_info.hcs文件中器件驱动层的moduleName信息相匹配 - .Init = HdfGoodixChipInit, // 器件驱动初始化函数 - }; - HDF_INIT(g_touchGoodixChipEntry); // 注册器件驱动至HDF框架 - ``` - - 器件私有驱动层主要实现了各器件厂商差异较大的部分,如器件休眠唤醒、数据解析以及固件升级等。 - - 至此,基于HDF框架及Input模型的触摸屏驱动适配完成。 - - diff --git "a/zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" "b/zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" deleted file mode 100644 index a56381458292b83a64324abba06a4a7301d7a25f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\351\205\215\347\275\256Touchscreen\345\231\250\344\273\266\344\277\241\346\201\257.md" +++ /dev/null @@ -1,98 +0,0 @@ -# 配置Touchscreen器件信息 - -配置文件路径:./drivers/adapter/khdf/linux/hcs/input/input\_config.hcs - -input\_config.hcs中的信息由驱动代码进行读取解析,主要由公共驱动层的私有配置信息及器件驱动层的私有配置信息组成。文件中的配置包含板级硬件信息及器件私有配置信息,实际业务开发时,可根据具体需求增删及修改对应内容。 - -``` -root { - input_config { - touchConfig { - touch0 { // 第一款触摸屏 - boardConfig { // 板级硬件信息 - match_attr = "touch_device1"; // 与设备描述配置信息中公共驱动层私有配置信息的“match_attr”字段保持一致 - inputAttr { - /* 0:touch 1:key 2:keyboard 3:mouse 4:button 5:crown 6:encoder */ - inputType = 0; // input类型为touch - solutionX = 480; // 分辨率X信息 - solutionY = 960; // 分辨率Y信息 - devName = "main_touch"; // 设备名称 - } - busConfig { - /* 0:i2c 1:spi */ - busType = 0; // GT911采用I2C通信 - busNum = 6; // 与主机芯片第6路I2C通信 - clkGpio = 86; // 主机芯片SCL管脚 - dataGpio = 87; // 主机芯片SDA管脚 - i2cClkIomux = [0x114f0048, 0x403]; // SCL管脚配置信息 - i2cDataIomux = [0x114f004c, 0x403]; // SDA管脚配置信息 - } - pinConfig { - rstGpio = 3; // 复位管脚连接主机芯片的3号管脚 - intGpio = 4; // 中断管脚连接主机芯片的4号管脚 - rstRegCfg = [0x112f0094, 0x400]; // 复位管脚配置信息 - intRegCfg = [0x112f0098, 0x400]; // 中断管脚配置信息 - } - powerConfig { - /* 0:unused 1:ldo 2:gpio 3:pmic */ - vccType = 2; // GPIO供电 - vccNum = 20; // gpio20 - vccValue = 1800; // 电压幅值为1800mV - vciType = 1; // LDO供电 - vciNum = 12; // ldo12 - vciValue = 3300; // 电压幅值为3300mV - } - - featureConfig { - capacitanceTest = 0; // 容值测试 - gestureMode = 0; // 手势模式 - gloverMode = 0; // 手套模式 - coverMode = 0; // 皮套模式 - chargerMode = 0; // 充电模式 - knuckleMode = 0; // 指关节模式 - } - } - chipConfig { // 器件私有信息配置 - template touchChip { // 模板 - match_attr = ""; - chipName = "gt911"; // 触摸屏IC型号 - vendorName = "zsj"; // 供应商 - chipInfo = "AAAA11222"; // 1~4字符代表产品名,5~6字符代表IC型号,7~9字符代表模型型号 - busType = 0; // 0代表I2C,1代表SPI - deviceAddr = 0x5D; // 器件IC通信地址 - irqFlag = 2; // 1代表上升沿触发,2代表下降沿触发,4代表高电平触发,8代表低电平触发 - maxSpeed = 400; // 最大通信速率为400Hz - chipVersion = 0; // 触摸屏IC版本号 - powerSequence { - /* 上电时序的配置含义说明: - [类型, 状态, 方向 , 延时] - 0代表空,1代表vcc电源(1.8V),2代表VCI电源(3.3V),3代表复位管脚,4代表中断管脚 - 0代表下电或拉低,1代表上电或拉高,2代表无操作 - 0代表输入方向,1代表输出方向,2代表无操作 - 代表延时多少毫秒, 例如20代表延时20ms - */ - powerOnSeq = [4, 0, 1, 0, // 中断管脚配置为输出,且进行拉低 - 3, 0, 1, 10, // 复位管脚配置为输出,且进行拉低,延时10ms - 3, 1, 2, 60, // 复位管脚无操作,且进行拉高,延时60ms - 4, 2, 0, 0]; // 中断管脚配置为输入 - suspendSeq = [3, 0, 2, 10]; // 复位管脚无操作,且进行拉低,延时10ms - resumeSeq = [3, 1, 2, 10]; // 复位管脚无操作,且进行拉高,延时10ms - powerOffSeq = [3, 0, 2, 10, // 复位管脚无操作,且进行拉低,延时10ms - 1, 0, 2, 20]; // 电源正极管脚无操作,且进行拉低,延时20ms - } - } - - chip0 :: touchChip { - match_attr = "zsj_gt911_5p5"; // 与设备描述配置信息中器件私有配置信息的“match_attr”字段保持一致 - chipInfo = "ZIDN45100"; // 产品名+模组编号+芯片编号的组合信息 用于给用户态区分当前器件 - chipVersion = 0; // IC型号的版本 - } - } - } - } - } -} -``` - -示例中“touchConfig”包含了“touch0”,"touch0"包含了“boardConfig”与“chipConfig”;“boardConfig”字段包含了Hi3516DV300板级硬件信息,“chipConfig”包含了触摸屏器件的私有信息,如果需要替换触摸屏器件,重新配置“chipConfig”对应的字段信息即可。同时产品可以配置多款触摸屏,示例中用“touch0”代表了套件中默认的触摸屏的硬件接口以及器件的配置信息,如产品需要配置副屏,可在与“touch0”并列的位置配置“touch1”的信息。 - diff --git "a/zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" "b/zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" deleted file mode 100644 index 4183826a4fa9d0afa0ce01ff2ead4d3c1a0dac70..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\351\205\215\347\275\256\350\256\276\345\244\207\346\217\217\350\277\260\344\277\241\346\201\257.md" +++ /dev/null @@ -1,64 +0,0 @@ -# 配置设备描述信息 - -配置文件路径:./drivers/adapter/khdf/linux/hcs/device\_info/device\_info.hcs - -device\_info.hcs中的信息主要提供给HDF框架使用,包含了Input模型各层驱动注册到HDF框架所必需的信息,开发者无特殊场景需求无需改动。各驱动层私有配置信息通过“deviceMatchAttr”字段与input\_config.hcs中的“match\_attr”相关内容进行匹配。 - -配置文件中与input模块相关的内容如下所示,相关字段的详细含义可以参考《[驱动配置](../driver/驱动开发.md)》: - -``` -input :: host { - hostName = "input_host"; - priority = 100; - device_input_manager :: device { // Input管理层设备描述信息 - device0 :: deviceNode { - policy = 2; // 向内核用户态均发布服务 - priority = 100; // input管理层驱动优先级默认为100 - preload = 0; // 加载该驱动 - permission = 0660; // 驱动创建设备节点权限 - moduleName = "HDF_INPUT_MANAGER"; // 与驱动入口的moduleName匹配 - serviceName = "hdf_input_host"; // HDF框架生成的节点名 - deviceMatchAttr = ""; // manager目前不需要私有配置,因此为空 - } - } - - device_hdf_touch :: device { // Input公共驱动层设备描述信息 - device0 :: deviceNode { - policy = 2; // 向内核用户态均发布服务 - priority = 120; // input公共驱动优先级默认为120 - preload = 0; // 加载该驱动 - permission = 0660; // 驱动创建设备节点权限 - moduleName = "HDF_TOUCH"; // 与驱动入口的moduleName匹配 - serviceName = "hdf_input_event1"; // HDF框架生成的节点名 - deviceMatchAttr = "touch_device1"; // 与私有配置信息中的“match_attr”字段保持一致 - } - } - - device_touch_chip :: device { // Input器件驱动层信息 - device0 :: deviceNode { - policy = 0; // 向内核用户态均不发布服务 - priority = 130; // input器件驱动优先级默认为130 - preload = 0; // 加载该驱动 - permission = 0660; // 驱动创建设备节点权限 - moduleName = "HDF_TOUCH_GT911"; // 与驱动入口的moduleName匹配 - serviceName = "hdf_touch_gt911_service";// HDF框架生成的节点名 - deviceMatchAttr = "zsj_gt911_5p5"; //与私有配置信息中的“match_attr”字段保持一致 - } - } - } -``` - -该配置文件中需要重点关注的字段有: - -“priority”决定驱动加载顺序; - -“preload”决定驱动是否加载; - -“moduleName ”需要与驱动注册入口处的“moduleName ”字段保持一致; - -“serviceName ”HDF框架依据该字段创建节点名; - -“deviceMatchAttr ”需要与私有配置信息中的“match\_attr”字段保持一致。 - -通过配置设备描述信息,使得HDF框架通过moduleName与注册至驱动入口的代码相匹配,保证了驱动的正常加载,通过priority字段保证了各驱动的加载顺序。 - diff --git "a/zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" "b/zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" deleted file mode 100755 index 355c2b275b3e532be944d3b46dee2cc073060f73..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\351\233\206\346\210\220\344\270\211\346\226\271SDK.md" +++ /dev/null @@ -1,325 +0,0 @@ -# 集成三方SDK - -- [规划目录结构](#section1736472718351) -- [构建业务libs](#section442815485351) -- [编写适配代码](#section3984721113613) -- [代码编写](#section830417531286) -- [脚本编写](#section13500201173710) -- [编写业务代码](#section8754114803918) -- [运行](#section7737749184012) -- [结束](#section153301392411) - -OpenHarmony致力于打造一套更加开放完善的IoT生态系统,为此OpenHarmony规划了一组目录,用于将各厂商的SDK集成到OpenHarmony中。本文档基于Hi3861开发板,向平台开发者介绍将SDK集成到OpenHarmony的方法。 - -## 规划目录结构 - -三方SDK通常由静态库和适配代码构成。SDK的业务逻辑通过硬件模组工具链编译得到静态库libs,每款模组都有其对应的libs。SDK的南向API与OpenHarmony 的API存在使用差异,该差异可通过adapter适配代码屏蔽,不同模组可共用一套adapter。 - -基于以上特征,在OpenHarmony目录结构中,可以对三方SDK目录做如下划分。 - -- 适配代码adapter,放置到domains/iot/link/ 目录下,与模组解耦。 -- 业务库libs,放置到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/ 目录下,与模组绑定。 - -平台开发者在适配前,务必先依次完成以下步骤,下面以demolink SDK举例,进行介绍。 - -1. 创建厂商目录,domains/iot/link/demolink/、device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/ ,用于厂商隔离。 -2. 创建domains/iot/link/demolink/BUILD.gn ,用于构建适配代码。 -3. 创建device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录,用于存放业务库libs。 - -``` -. -├── domains -│ └── iot -│ └── link -│ ├── demolink -│ │ └── BUILD.gn -│ ├── libbuild -│ │ └── BUILD.gn -│ └── BUILD.gn -└── device - └── hisilicon - └── hispark_pegasus - └── sdk_liteos - └── 3rd_sdk - └── demolink - └── libs -``` - -## 构建业务libs - -平台SDK业务一般以静态库的形式提供,平台厂商在获取到OpenHarmony代码后,需要根据对应的硬件模组vendor,编译业务libs,并将编译结果放置在device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下。下面介绍业务libs的构建方法。 - -OpenHarmony已规划用于编译业务libs的目录domains/iot/link/libbuild/ ,该目录中包含domains/iot/link/libbuild/BUILD.gn和domains/iot/link/BUILD.gn文件,目录结构如下。 - -``` -. -└── domains - └── iot - └── link - ├── demolink - │ └── BUILD.gn - ├── libbuild - │ └── BUILD.gn - └── BUILD.gn -``` - -平台开发者在构建libs前,务必先完成如下步骤。 - -1. 在domains/iot/link/libbuild/ 目录下放置业务源码文件,包括.c和.h文件。 - - ``` - . - └── domains - └── iot - └── link - ├── demolink - │ ├── demosdk_adapter.c - │ ├── demosdk_adapter.h - │ └── BUILD.gn - ├── libbuild - │ ├── demosdk.c - │ ├── demosdk.h - │ └── BUILD.gn - └── BUILD.gn - ``` - -2. 适配domains/iot/link/libbuild/BUILD.gn,在编译完成后还原该文件。 - - 在BUILD.gn中,sources为需要参与构建的源文件,include\_dirs为依赖的头文件路径,构建的目标结果是生成静态库libdemosdk.a。 - - ``` - static_library("demosdk") { - sources = [ - "demosdk.c" - ] - include_dirs = [ - "//domains/iot/link/libbuild", - "//domains/iot/link/demolink" - ] - } - ``` - -3. 适配domains/iot/link/BUILD.gn,在编译完成后还原该文件。 - - 此BUILD.gn文件用于指定构建条目,需要在features中填入所有需参与编译的静态库条目,使domains/iot/link/libbuild/BUILD.gn参与到构建中来。 - - ``` - import("//build/lite/config/subsystem/lite_subsystem.gni") - import("//build/lite/config/component/lite_component.gni") - lite_subsystem("iot") { - subsystem_components = [ - ":link" - ] - } - lite_component("link") { - features = [ - "libbuild:demosdk" - ] - } - ``` - - -完成以上3点后,需在代码根目录下执行命令“hb build -T //domains/iot/link:iot”,等待执行完成,检查out/hispark\_pegasus/wifiiot\_hispark\_pegasus/libs/目录下是否生成了目标库文件。 - -![](figures/zh-cn_image_0000001078563230.png) - -将库文件拷贝到device/hisilicon/hispark\_pegasus/sdk\_liteos/3rd\_sdk/demolink/libs/ 目录下,并将domains/iot/link/libbuild/ 目录中的.c和.h文件清除。 - -## 编写适配代码 - -## 代码编写 - -平台SDK中使用的API通常与OpenHarmony API存在差异,无法直接使用,需要一层适配代码adapter进行中间转换。本节以domains/iot/link/demolink/demosdk\_adapter.c中的任务创建接口DemoSdkCreateTask举例,向开发者演示如何在OpenHarmony上编写适配代码。 - -1. 查看待适配接口DemoSdkCreateTask的描述、参数、返回值。 - - ``` - struct TaskPara { - char *name; - void *(*func)(char* arg); - void *arg; - unsigned char prio; - unsigned int size; - }; - - /* - * IoT OS 创建线程接口 - * 返回值: 返回0 成功, 其他 失败 - */ - int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para); - ``` - -2. 查看OpenHarmony API接口文档,选取一个功能类似的接口,并比对参数及用法上的差异。例如本文选取osThreadNew ,通过和DemoSdkCreateTask接口比对,可以发现两接口依赖的参数基本一致,只是参数所归属的结构体不同。 - - ``` - typedef struct { - const char *name; ///< name of the thread - uint32_t attr_bits; ///< attribute bits - void *cb_mem; ///< memory for control block - uint32_t cb_size; ///< size of provided memory for control block - void *stack_mem; ///< memory for stack - uint32_t stack_size; ///< size of stack - osPriority_t priority; ///< initial thread priority (default: osPriorityNormal) - TZ_ModuleId_t tz_module; ///< TrustZone module identifier - uint32_t reserved; ///< reserved (must be 0) - } osThreadAttr_t; - - /// Create a thread and add it to Active Threads. - /// \param[in] func thread function. - /// \param[in] argument pointer that is passed to the thread function as start argument. - /// \param[in] attr thread attributes; NULL: default values. - /// \return thread ID for reference by other functions or NULL in case of error. - osThreadId_t osThreadNew (osThreadFunc_t func, void *argument, const osThreadAttr_t *attr); - ``` - -3. 完成代码差异转换。 - - ``` - int DemoSdkCreateTask(unsigned int *handle, const struct TaskPara *para) - { - osThreadAttr_t attr = {0}; - osThreadId_t threadId; - if (handle == 0 || para == 0) { - return DEMOSDK_ERR; - } - if (para->func == 0) { - return DEMOSDK_ERR; - } - if (para->name == 0) { - return DEMOSDK_ERR; - } - attr.name = para->name; - attr.priority = para->prio; - attr.stack_size = para->size; - threadId = osThreadNew((osThreadFunc_t)para->func, para->arg, &attr); - if (threadId == 0) { - printf("osThreadNew fail\n"); - return DEMOSDK_ERR; - } - *(unsigned int *)handle = (unsigned int)threadId; - return DEMOSDK_OK; - } - ``` - - -## 脚本编写 - -开发者在完成代码适配后,还需要在adapter同级目录下新建BUILD.gn文件。该文件可在整包构建时,将适配代码编译成静态库,并链接到bin包中去。在domains/iot/link/demolink/BUILD.gn中,sources中为需要参与构建的源文件,include\_dirs中为依赖的头文件路径,构建目标结果是生产静态库libdemolinkadapter.a。 - -``` -import("//build/lite/config/component/lite_component.gni") -static_library("demolinkadapter") { - sources = [ - "demosdk_adapter.c" - ] - include_dirs = [ - "//kernel/liteos-m/kal/cmsis", - "//domains/iot/link/demolink" - ] -} -``` - -修改domains/iot/link/BUILD.gn文件,使domain/iot/hilink/BUILD.gn参与到构建系统中。 - -``` -import("//build/lite/config/subsystem/lite_subsystem.gni") -import("//build/lite/config/component/lite_component.gni") -lite_subsystem("iot") { - subsystem_components = [ - ":link" - ] -} -lite_component("link") { - features = [ - "demolink:demolinkadapter" - ] -} -``` - -## 编写业务代码 - -业务libs库和适配代码准备就绪后,还需要编写业务入口函数,调起三方SDK的业务入口。 - -下面以demolink举例,介绍如何在applications/sample/wifi-iot/app/路径下编写代码,调起demosdk的入口函数。 - -1. 目录创建 - - 开发者编写业务时,务必先在applications/sample/wifi-iot/app/ 路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 - - 例如:在app下新增业务目录demolink,并在其中创建业务入口代码helloworld.c和编译构建文件BUILD.gn,如下。 - - ``` - . - └── applications - └── sample - └── wifi-iot - └── app - │── demolink - │ │── helloworld.c - │ └── BUILD.gn - └── BUILD.gn - ``` - -2. 编写业务代码。 - - 在helloworld.c文件中编写业务入口函数DemoSdkMain,并调起demolink的业务DemoSdkEntry,最后通过SYS\_RUN\(\)调用入口函数完成业务启动。 - - ``` - #include "hos_init.h" - #include "demosdk.h" - - void DemoSdkMain(void) - { - DemoSdkEntry(); - } - - SYS_RUN(DemoSdkMain); - ``` - -3. 编写构建脚本 - - 新增applications/sample/wifi-iot/app/demolink/BUILD.gn文件,指定源码和头文件路径,编译输出静态库文件libexample\_demolink.a。 - - ``` - static_library("example_demolink") { - sources = [ - "helloworld.c" - ] - include_dirs = [ - "//utils/native/lite/include", - "//domains/iot/link/libbuild" - ] - } - ``` - - 修改applications/sample/wifi-iot/app/BUILD.gn,使demolink参与编译。 - - ``` - import("//build/lite/config/component/lite_component.gni") - lite_component("app") { - features = [ - "demolink:example_demolink" - ] - } - ``` - - -## 运行 - -在代码根目录下,执行命令“hb build”编译输出版本包。最后启动运行,运行结果如图所示,与demolink预期相符。 - -``` -ready to OS start -sdk ver:Hi3861V100R001C00SPC024 2020-08-05 16:30:00 -formatting spiffs... -FileSystem mount ok. -wifi init success! -it is demosdk entry. -it is demo biz: hello world. -it is demo biz: hello world. -``` - -## 结束 - -至此,三方SDK集成已介绍完毕。 - diff --git "a/zh-cn/device-dev/guide/\351\252\214\350\257\201.md" "b/zh-cn/device-dev/guide/\351\252\214\350\257\201.md" deleted file mode 100755 index e9be36acdfb301de6902f16081f4e792cdebe00d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/guide/\351\252\214\350\257\201.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 验证 - -编译过程请参考《[Hi3861快速入门-源码编译](../quick-start/运行Hello-World.md)》,烧录过程请参考《[Hi3861快速入门-镜像烧录](../quick-start/WLAN联网.md)》。 - -完成以上两步后,按下RST键复位模组,可发现LED在周期性闪烁,与预期相符,验证完毕。 - -**图 1** LED闪烁图 -![](figures/LED闪烁图.gif "LED闪烁图") - diff --git "a/zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" "b/zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" deleted file mode 100644 index ce1082a69f28edf6313a5883728bf45c2b6b3389..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel-contribution/OpenHarmony\345\206\205\346\240\270\346\226\207\346\241\243\345\205\261\345\273\272ToDo-List.md" +++ /dev/null @@ -1,245 +0,0 @@ -# OpenHarmony文档共建计划--内核文档共建 - - - -| 2021-06-28-2021-07-30 | 2021-07-05 | 2021-07-05-2021-07-30 | 2021-08-01-2021-08-31 | -| --------------------------------- | -------------------------------- | -------------------------- | --------------------- | -| **任务招募** | **线上会议** | **文档共建** | **结项发布** | -| ToDo List、文档模板、共建手册大纲 | 文档共建介绍、写作规范、常见操作 | 小组周进展跟踪、导师辅导制 | 发布共建后内核文档 | - -- [如何参与](#section_register) -- [文档共建范围](#section_outline_summary) -- [文档大纲及认领明细](section_outline_detail) - -## 共建活动ToDoList - -OpenHarmony文档共建活动是由OpenHarmony社区举办,旨在进一步丰富和完善现有文档,提升文档体验**,**更好地服务于广大开发者。本次文档共建活动有共建移植文档、内核文档、Qemu仿真文档。详情请参考共建手册大纲:《基于Qemu运行OpenHarmony》、 《小型系统三方芯片移植指南》、《OpenHarmony内核开发指南》。 - -即日起开发者可自主选择并认领感兴趣的任务,获得社区资深**技术导师**和**文档导师**的指导。根据项目的难易程度和完成情况,参与者还将获得"**OpenHarmony 文档共建贡献者** " 荣誉及周边纪念品。 - -1. **活动时间:** 2021-06-28~2021-07-30 - -2. **招募对象:** - - - 技术写作者 - - - 文档验证/审核者 - - - 小组组织人员 - -3. **招募要求:** -- 熟悉嵌入式、物联网等OS开发相关知识 - -- 有扎实的C语言编程经验 - -- 有较强的文字写作能力、逻辑思维能力 - -4. **参与方式:** - - - Gitee社区内认领任务反馈 - - 开发者加入内核文档共建招募活动微信群 -5. 共建激励规则 - -**卓越贡献奖** - -- **奖励对象:**审核通过&内容被采纳的contributor。 - -- **奖励礼品:**OpenHarmonyT恤、帽子等周边纪念品。 - - - -## 如何参与 -- 方式1 [Issue回帖](https://gitee.com/openharmony/docs/issues/I3Y9MU?from=project-issue) -- 方式2 微信交流群报名 -- 方式3 邮件反馈 @neeen @rtos_yuan ,邮件主题:OpenHarmony轻内核文档共建报名 -3种方式均可报名,建议同时提供邮箱,方便后续发送线上会议交流通知。 - - -## 文档共建范围 - -### 1、基于Qemu运行OpenHarmony---招募内容写作 - -- 背景 - - - 对于想体验OpenHarmony的开发者,手头不一定有现成的开发板,基于Qemu可以降低入门体验门槛。 - - - 已经支持Qemu,但是没有对应的文档, 快速入门只有3861、3516、3518等板子。 - -- 文档计划 - - LiteOS-A、LiteOS-M Qemu使用教程第一时间上社区,社区化运作文档,降低社区开发者体验OpenHarmony开发的门槛。 - -- **访问[《基于Qemu运行OpenHarmony 文档大纲》](#section_qemu_outline_detail)。** - -### 2、小型系统三方芯片移植指南---招募内容体验&验证 - -社区支持的开发板有限,三方芯片、开发板移植需要更丰富的开发板场景案例。 -- 文档计划 - - - 鼓励开发者完善移植文档,支持社区开发者移植支持更多的开发板、支持手头的开发板能运行起来。 - - 鼓励移植经验文档回馈社区。 - -- **访问[《小型系统三方芯片移植指南 文档大纲》](#porting_tutorial_outline_detail)。** - -### 3、小型系统内核开发指南(LiteOS-A核)---招募内容体验&验证 - -- 文档计划 - - - 优化后内核文档初稿完成,鼓励开发者体验新内容,验证内容。 - - 社区化文档运作,鼓励社区开发者参与文档的优化编写,文档问题反馈。 - -- **访问[《OpenHarmony 内核开发指南(LiteOS-A核) 文档大纲》](#kernel_a_tutorial_outline_detail)。** - - - - -## 文档大纲及认领明细 - -✨**文档大纲用于维护文档的组成章节、章节意图,编写责任人,及PR合入状态**。 - -✨**使用对号[✔]表示文档的完成状态,第一个对号表示文档开发完成,第二个对号表示文档开发完成**。 - -### 一、基于Qemu运行OpenHarmony 文档大纲 - -#### 1 Qemu简介 [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] [@mgy917](https://gitee.com/mgy917) [✔] - - - -#### 2 开发环境准备 [@mgy917](https://gitee.com/mgy917) [✔] [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] - -- 2.1 OpenHarmony开发环境准备 - - - 环境搭建 - - 获取OpenHarmony源码 - -- 2.2 Qemu软件安装 - - 开发者根据需求,选择运行LiteOS-A、LiteOS-M的Qemu软件。 - - - Qemu软件编译安装 - - Qemu-Virt软件 - - Qemu-Riscv32软件 [@zhushengle](https://gitee.com/zhushengle) [✔] - - - -#### 3 Qemu工程源码介绍 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -* 3.1 Qemu工程源码介绍 - -#### 4 编译运行LiteOS-A Qemu Virt工程 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -- 4.1 编译构建LiteOS-A -- 4.2 运行镜像 - - 准备Flash镜像 - - 配置主机网桥 - - 运行程序 - -#### 5 编译运行LiteOS-M Qemu Riscv工程 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -- 4.1 编译构建LiteOS-M -- 4.2 运行程序 - -### 二、小型系统三方芯片移植指南 ---招募内容体验&验证 - -#### 1 移植准备 [@arvinzzz](https://gitee.com/arvinzzz) [✔] [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] - - - -##### 1.1 移植须知 - -##### 1.2 编译构建 - -#### 2 内核移植 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - -- 2.1 LiteOS-A内核 - - - - - 2.1.1 移植概述 - - 2.1.2 内核基础适配 - - 2.1.3 内核移植验证 - -- 2.2 Linux内核 - - - -#### 3 板级移植 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -### 三、小型系统内核开发指南(LiteOS-A核)---招募内容体验&验证 - -#### 1 认识LiteOS-A内核 [@kkup180](https://gitee.com/kkup180) [✔] [@mgy917](https://gitee.com/mgy917) [✔] - - - -- 1.1 简介 -- 1.2 内核架构 -- 1.3 CPU体系架构支持 - -#### 2 基础内核 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 2.1 中断及异常处理 -- 2.2 进程管理 -- 2.3 线程管理 -- 2.4 调度 -- 2.5 内存管理 - - 2.5.1 堆内存管理 - - 2.5.2 虚拟内存管理 - - 2.5.3 物理内存管理 - - 2.5.4 虚实映射 -- 2.6 IPC - - 2.6.1 事件 - - 2.6.2 信号量 - - 2.6.3 互斥锁 - - 2.6.4 消息队列 - - 2.6.5 读写锁 - - 2.6.6 futex - - 2.6.7 信号 -- 2.7 系统调用 -- 2.8 时间管理 -- 2.9 软件定时器 -- 2.10 原子操作 -#### 3 扩展组件 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 3.1 ELF内核加载器 -- 3.2 VDSO -- 3.3 LiteIPC -- 3.4 CPUP -- 3.5 C++支持 -#### 4 文件系统 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 4.1 vfs - -- 4.2 支持的文件系统 - - 4.2.1 FAT - - 4.2.2 jffs2 - - 4.2.3 nfs - - 4.2.4 ramfs - - 4.2.5 procfs -- 4.3 适配新的文件系统 -#### 5 内核启动 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] -- 5.1 运行机制 -#### 6 用户态启动 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] -- 6.1 用户态根进程启动 -- 6.2 用户态程序运行 -#### 7 调测 [@waitForContributor](https://gitee.com/openharmony/docs/issues)[ ?] - - - -- 7.1 内存调测 -- 7.2 Trace -- 7.3 魔法键 -- 7.4 Dying gasp -- 7.5 常见问题定位方法 -#### 8 附录 [@rtos_yuan](https://gitee.com/rtos_yuan) [✔] [@harylee](https://gitee.com/harylee)[✔] -- 8.1 基本数据结构 - - 8.1.1 双向链表 - - 8.1.2 位操作 - diff --git "a/zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100644 index 976524f98b7145daf34642bd563c4d442de35cd6..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,51 +0,0 @@ -# 常见问题 - -** *【写作要求】*** - - -*可选。描述开发过程遇到的各类问题以及解决方案,以提高开发效率。* - - -- * 如果无常见问题,删除此章节。* - -- * 如果有常见问题,建议单独章节,后续具备扩展性。* - -- * 如果有常见问题,问题少于1屏且未来扩充可能性不大,可放在“开发指导”。* - - -*具体写作要求见下,完成写作后,请逐项自检下。* - - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **N1** | **整体要求** | | -| N1.1 | 问题是否对外呈现(考虑重要性、出现概率等),请在部门内部CCB达成一致。 | | -| N1.2 | 每个问题描述里一般只问一个问题,避免多个问题合在一个问题描述。 | | -| N1.3 | 如果问题比较多,可以对问题进行分类。 | | -| **N2** | **单个问题要求** | | -| N2.1 | 标题:1句话描述问题场景、现象。 | | -| N2.2 | 现象描述:以用户视角黑盒描述问题出现的场景、现象、条件、概率等。描述问题现象清晰,没有歧义。 | | -| N2.3 | 可能原因:明确问题根本的原因。 | | -| N2.4 | 处理步骤-1:明确处理问题的步骤,step by step操作,具体要求同“开发步骤”部分。 | | -| N2.5 | 处理步骤-2:答复必须是严谨、明确的解决方法,口径与产品宣传一致,不能是参考建议这类含糊的回答。 | | -| N2.6 | 处理步骤-3:如果问题与能力版本有关联性的,需要明确。 | | - - -## 1.XX问题(简单问题) - -XXX - - -## 2.XX问题(复杂问题) - -**现象描述** - -XXX - -**可能原因** - -XXX - -**解决办法** - -XXX diff --git "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" "b/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" deleted file mode 100644 index 54133ebda8d12e93b00dfd1c9be5f062874cbe77..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\345\256\236\344\276\213.md" +++ /dev/null @@ -1,49 +0,0 @@ -# 开发实例 - -** *【写作要求】*** - - -*必选。描述开发完成后,基于一个任务整体做代码段的描述。* - - -- * 标题名称不变。如果“开发指导”是多场景,标题名称可以调整为拍照开发实例、预览开发指导等。* - -- * 标题可合并。如果产品链接到示例代码或内容少于1屏,可合并到“开发指导”,整本统一。* - - -*具体写作要求见下,完成写作后,请逐项自检下。* - - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| M1.1 | 有任务的场景介绍,且和代码端内容呼应。 | | -| M1.2 | 代码段顺利指导完成操作,无缺失。 | | -| M1.3 | 代码涉及开发者拷贝的命令,必须用可编辑的报文呈现,避免截图(DOCS插入Screen)。 | | -| M1.4 | 代码中关键段用蓝色(RGB:0.0.255)突出显示,关键步骤要有注释说明。 | | -| M1.5 | 代码显示符合代码缩进要求。 | | - - -**【写作样例---节选】** - - -SDIO设备完整的使用示例如下所示,首先打开总线号为1的SDIO控制器,然后独占HOST、使能设备、注册中断,接着进行SDIO通信(读写等),通信完成之后,释放中断、去使能设备、释放HOST,最后关闭SDIO控制器。 -``` -#include "hdf_log.h" -#include "sdio_if.h" - -#define TEST_FUNC_NUM 1 /* 本测试用例中,使用编号为1的I/O function */ -#define TEST_FBR_BASE_ADDR 0x100 /* 编号为1的I/O function的FBR基地址 */ -#define TEST_ADDR_OFFSET 9 /* 本测试用例中,需要读写的寄存器的地址偏移 */ -#define TEST_DATA_LEN 3 /* 本测试用例中,读写数据的长度 */ -#define TEST_BLOCKSIZE 2 /* 本测试用例中,数据块的大小,单位字节 */ - -/* 中断服务函数,需要根据各自平台的情况去实现 */ -static void SdioIrqFunc(void *data) -{ - if (data == NULL) { - HDF_LOGE("SdioIrqFunc: data is NULL.\n"); - return; - } - /* 需要开发者自行添加具体的实现 */ -} -``` diff --git "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100644 index 2b4b6a3a9381255de70fbcd23281176f0e38560b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,128 +0,0 @@ -# 开发指导 - -** *【写作要求】*** - - -*必选。* *描述各个场景下,开发者如何完成开发任务。* *可根据多场景任务增加章节。写作要求见下,完成写作后,请逐项自检。* - - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| H.1.1 | 如果有多个场景,请写起多个“开发指导”章节,如音频播放开发指导、音量管理开发指导、短音播放开发指导。 | | -| H.1.2 | 标题尽量使用“动词+名词”的句式表述任务操作。 | | - - -## 场景介绍 - -** *【写作要求】*** - -*必选。* *描述在什么情景下解决什么问题,最终达到什么样的效果。*应用SCQA描述方法: - -- S:situation(情景),由大家都熟悉的的情景,事实引入。 - -- C:complication(冲突),但是实际情况往往和我们的要求有冲突。 - -- Q:question(疑问),怎么办? - -- A:answer(回答),我们的解决方案是 … - -*写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| I.1.1 | 背景原因、什么时候在哪、做了什么操作、最终解决什么问题或操作效果都明确。 | | - -**【写作样例】** - -音频播放的主要工作是将音频数据转码为可听见的音频模拟信号并通过输出设备进行播放,同时对播放任务进行管理。 - - -## 接口说明 - -** *【写作要求】*** - -*必选。* *描述本开发指导相关的接口有哪些,旨在要开发者在开发前有大体了解,提升开发效率。* *写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| J.1.1 | 不在本开发任务的接口无需提供。 | | -| J.1.2 | 如果接口太多,超过10个,可以提供主要的接口 | | - -**【写作样例】** - -音频播放开放能力如下:AudioRenderer类,具体的API详见接口文档。 - -**表1** 音频播放API接口功能介绍 - -| 接口名 | 描述 | -| -------- | -------- | -| AudioRenderer(AudioRendererInfo audioRendererInfo, PlayMode pm) throws IllegalArgumentException | 构造函数,设置播放相关音频参数和播放模式,使用默认播放设备 | -| AudioRenderer(AudioRendererInfo audioRendererInfo, PlayMode pm, AudioDeviceDescriptor outputDevice) throws IllegalArgumentException | 构造函数,设置播放相关音频参数、播放模式和播放设备 | -| boolean play() | 播放音频流 | -| boolean write(byte[] data, int offset, int size) | 将音频数据以byte流写入音频接收器以进行播放 | - - -## 开发步骤 - -** *【写作要求】*** - - * 必选。描述* *开发的整体过程,便于开发者快速完成开发。* * 具体 写作要求见下,完成写作后,请逐项自检下。* -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **K.1** | **如何写好步骤** | | -| K.1.1 | 步骤完整:提供必须的步骤,顺利指导完成操作,无缺失。 | | -| K.1.2 | 脉络清楚:文档逻辑清晰、合理。文档前面的概述、准备、操作围绕一条线描述,不能章节断裂或前后矛盾的现象。 | | -| K.1.3 | 任务句式:标题或句子尽量使用“动词+名词”的句式表述动作。 | | -| K.1.4 | 预防提前:操作过程中的限制、易错的、有潜在风险的,要提前描述,使用DOCS平台的“插入> 说明 > 须知”描述。 | | -| K.1.5 | 步骤清晰-1:无论步骤简单或复杂,都需要写步骤目的,即为什么做。 | | -| K.1.6 | 步骤清晰-2:明确在什么环境下,使用什么工具,做什么操作,怎么做该操作。 | | -| K.1.7 | 步骤具体:如果操作可选,要明确可选条件。 | | -| K.1.8 | 在开发步骤执行完成后,及时明确操作正确的标准。 | | -| **K.2** | **如何写好代码段** | | -| K.2.1 | 代码涉及开发者拷贝的命令,必须用可编辑的报文呈现,避免截图(DOCS插入Screen)。 | | -| K.2.2 | 代码中关键段用蓝色(RGB:0.0.255)突出显示,关键步骤要有注释说明。 | | -| K.2.3 | 代码显示符合代码缩进要求。 | | -| K.2.4 | 步骤涉及接口调用,清晰给出接口及其使用说明或示例代码,代码来源于具体实例。 | | - -**【写作样例】** - -1. 构造音频流参数的数据结构AudioStreamInfo,推荐使用AudioStreamInfo.Builder类来构造,模板如下,模板中设置的均为AudioStreamInfo.Builder类的默认值,根据音频流的具体规格来设置具体参数。 - ``` - AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().sampleRate( AudioStreamInfo.SAMPLE_RATE_UNSPECIFIED) .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_NONE) .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_INVALID) .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_INVALID) .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_UNKNOWN) .build(); - ``` - - 以真实的播放pcm流为例: - ``` - AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder().sampleRate(44100)//44.1kHz .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK)//混音 .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT)//16-bit PCM .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_OUT_STEREO)//双声道 .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA)//媒体类音频 .build(); - ``` - -2. 使用步骤1创建的音频流构建音频播放的参数结构AudioRendererInfo,推荐使用AudioRendererInfo.Builder类来构造,模板如下,模板中设置的均为AudioRendererInfo.Builder类的默认值,根据音频播放的具体规格来设置具体参数。 - ``` - AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo) .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_NONE) .bufferSizeInBytes(0) .distributedDeviceId("") .isOffload(false) .sessionID(AudioRendererInfo.SESSION_ID_UNSPECIFIED) .build(); - ``` - - 以真实的播放pcm流为例: - ``` - AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(audioStreamInfo) .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM)//pcm格式的输出流 .bufferSizeInBytes(100) .distributedDeviceId("E54***5E8")//使用分布式设备E54***5E8播放 .isOffload(false)//false表示分段传输buffer并播放,true表示整个音频流一次性传输到HAL层播放 .build(); - ``` - -3. 根据要播放音频流指定PlayMode,不同的PlayMode在写数据时存在差异,详情见步骤7,其余播放流程是无区别的。并通过构造函数获取AudioRenderer类的实例化对象。 - .... - -4. 播放任务结束后,调用AudioRenderer实例化对象的release()释放资源。 - - -## 调测验证(可选) - -** *【写作要求】*** - -*可选。* *描述开发完成后,进行调测验证,确保最终操作成功。* *操作步骤要求同“开发指导”,其他具体写作要求见下,完成写作后,请逐项自检下。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| L1.1 | 仅进行最后的业务调测,每个小任务的操作结果,在开发步骤执行完成后,及时验证操作结果。 | | -| L1.2 | 明确开发成功标准。 | | - -**【写作样例---节选】** - -![1624266401415](C:\Users\LWX104~1\AppData\Local\Temp\1624266401415.png) diff --git "a/zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" "b/zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" deleted file mode 100644 index 743adf6abcf01ab23d2112c2cffd2fb99d3db197..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\346\220\255\345\273\272\347\216\257\345\242\203.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 搭建环境 - -** *【写作要求】*** - - -*条件必选。* *如果在快速入门里已提供此部分,此章节可以不提供。明确如何搭建开发环境(如开发工具、编译工具)*。 - - -## 环境要求 - -** *【写作要求】*** - -*必选。* *明确开发环境所需要的软硬件配置,* *旨在要用户提前准备环境。*如果软硬件内容比较多,可以再增加子标题。写作要求见下,完成写作后,请逐项自检。 - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| E.1.1 | 分别明确开发的软硬环境和手机的开发环境,下载路径。 | | -| E1.2 | 明确具体的版本号。 | | - - -**【写作样例】** - - -**表1** 环境要求 - -| 项目 | PC | 手机 | -| -------- | -------- | -------- | -| 硬件 | - 内存:8G及以上
- 硬盘:100G及以上
- 分辨率:1280\*800 | 处理器不低于kirin 980的华为手机 | -| 软件 | 操作系统:Windows10 64位  或 Mac 10。 | 系统软件版本不低于EMUI_10.0.0 | - - -## 安装环境 - -** *【写作要求】*** - -必选。描述安装环境的具体步骤,如果内容比较多,可以区分安装环境章节,如:安装编译基础环境、安装编译工具环境、安装gcc_riscv32(WLAN模组类编译工具链)。 - -写作要求见下,完成写作后,请逐项自检。 - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **F.1** | **如何写好步骤** | | -| F.1.1 | 步骤完整:提供必须的步骤,顺利指导完成操作,无缺失。 | | -| F.1.2 | 脉络清楚:文档逻辑清晰、合理。文档前面的概述、准备、操作围绕一条线描述,不能章节断裂或前后矛盾的现象。 | | -| F.1.3 | 任务句式:标题或句子尽量使用“动词+名词”的句式表述动作。 | | -| F.1.4 | 预防提前:操作过程中的限制、易错的、有潜在风险的,要提前描述,使用DOCS平台的“插入> 说明 > 须知”描述。 | | -| F.1.5 | 步骤清晰-1:无论步骤简单或复杂,都需要写步骤目的,即为什么做。 | | -| F.1.6 | 步骤清晰-2:明确在什么环境下,使用什么工具,做什么操作,怎么做该操作。 | | -| F.1.7 | 步骤具体:如果操作可选,要明确可选条件。 | | -| F.1.8 | 在开发步骤执行完成后,及时明确操作正确的标准。 | | -| **F.2** | **如何写好代码段** | | -| F.2.1 | 代码涉及开发者拷贝的命令,必须用可编辑的报文呈现,避免截图(DOCS插入Screen)。 | | -| F.2.2 | 代码中关键段用蓝色(RGB:0.0.255)突出显示,关键步骤要有注释说明。 | | -| F.2.3 | 代码显示符合代码缩进要求。 | | -| F.2.4 | 步骤涉及接口调用,清晰给出接口及其使用说明或示例代码,代码来源于具体实例。 | | - -**【写作样例】** - -1. 双击下载的exe文件,进入DevEco Studio安装向导。 - -2. 配置DevEco Studio安装路径,点击Next。 - -3. 配置DevEco Studio安装选项,点击Next。 - - Create Desktop Shortcut:配置是否创建桌面快捷方式,根据操作系统位数进行选择。 - - Update PATH variable:配置是否将启动器路径添加到环境变量PATH中,需要从命令行启动DevEco Studio时,需要勾选Add launchers dir to the PATH。 - - Update context menu:配置是否将DevEco Studio功能添加至上下文菜单。勾选后,右键上下文菜单将出现“Open Folder as Project”选项。 - -4. 配置桌面快捷方式的开始菜单文件夹,点击Install。 - -5. 等待DevEco Studio安装完成后,点击Finish。 - - -## 检验环境是否搭建成功 - -** *【写作要求】*** - -*必选。* *环境搭建完成后,需要明确给出环境搭建是否成功的检验标准*。 - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| G.1.1 | 仅进行最后的结果验证,每个小任务的操作结果,在开发步骤执行完成后,及时验证操作结果。 | | -| G1.2 | 明确搭建成功的标准。 | | diff --git "a/zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" deleted file mode 100644 index c3ab6dfa23f8ee7ea737e10d460553c498632a77..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel-contribution/template/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,169 +0,0 @@ -# 概述 - -* **【开发指南总体** **写作要求】*** - - -* 适用于鸿蒙南北向子系统开发、应用侧的设备开发、南向开发指南。* - - -* 章节调整:本模板知识点内容结构可以根据产品内容多少微调,具体操作方式见下。* - - -| 章节 | 可选/必选说明 | 备注 | -| -------- | -------- | -------- | -| 概述 | 必选,标题名称不变 | - | -| 搭建环境 | 可选,如果快速入门已有,可不用提供,否则需提供。 | - | -| 开发指导 | 必选,可根据多场景任务增加章节。 | 拍照开发指导
预览开发指导
录像开发指导 | -| 开发实例 | 必选。
- 标题名称可自定义。如果“开发指导”是多场景,标题名称可以调整为拍照开发实例、预览开发实例等。
- 标题可合并。如果产品链接到示例代码或内容少于1屏,可合并到“开发指导”,整本统一。 | - | -| 常见问题 | 可选,标题不变。
- 如果无常见问题,删除此章节。
- 如果有常见问题,建议单独章节,后续具备扩展性。
- 如果有常见问题,问题少于1屏,未来扩充可能行不大,可放在“开发指导”。 | - | -| 参考 | 可选,根据实际需要补充。 | - | - - - * 整体写作要求见下,完成写作后,请逐项自检。* -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| **A.1** | **用语要求** | | -| A.1.1 | 行文风格:文档在官方网站发布,用语正式,避免口语化。 | | -| A.1.2 | 合规要求:不能使用Android特有概念等存在合规和法务风险的词汇。敏感词汇包含但不限于:Android、Google、EMUI、Activity、AOSP、provider、binder、APK、Dalvik、AVD、ADT、DDMS、adb、AAPT、AndroidManifest、NDK、ART、dex、ANR、Cursor、Blacklist、Whitelist、Master、Slave、L0、L1、轻鸿蒙、富鸿蒙等。 | | -| A.1.3 | 内容简洁:内容采用信息必备、最小化原则,旨在指导开发者在尽量短的时间完成操作。 | | -| A.1.4 | 内容正确:文档的代码、需要设置的参数等需要跟产品实际情况实时保持一致。 | | -| A.1.5 | 用语准确:应当确切,不能出现多义性的描述。 | | -| A.1.6 | 用语一致:同一叫法,全文保持一致,术语与术语库保持一致,正文中缩略语首次出现要给出全称。 | | -| A.1.7 | 用语具体:如表示数量或程度时,避免用笼统的“多”“少”“大”,建议用具体数字表示。 | | -| **A.2** | **格式要求** | | -| A.2.1 | 标点符号正确、句尾有符号结尾。 | | -| A.2.2 | 内容尽量用项目列表或分类的方式清晰呈现。不要有单个项目列表;不要有多余空行。 | | -| A.2.3 | 英文字母和中文字之间不要有空格。 | | -| A.2.4 | 链接必须有效,具体,可直接跳转或下载。 | | -| A.2.5 | 如果是内容的辅助说明,请使用“说明”式样;如果提前申明事项,,请使用“须知”式样。To D的资料不用“注意”格式。 | | -| **A.3** | **表格** | | -| A.3.1 | 表格有表注,表头风格一致,采用名词或名词词组形式。 | | -| A.3.2 | 表格有表头,至少为2行2列,避免出现单行或单列表。 | | -| A.3.3 | 表格无内容用“_”,不出现空白的单元格。 | | -| **A.4** | **图形** | | -| A.4.2 | 符合华为调性,避免互联网化,避免涉及宗教信仰类截图。 | | -| A.4.3 | 图文并茂,行文应力求简明,如有可能,配以适当的图,表。 | | -| A.4.4 | 图形有图注(不可直接粘贴图形),图注风格一致,采用名词或名词词组形式。 | | -| A.4.5 | 图形应清晰可辩识,信息表达完整,易于阅读。如流程图不可缺少“开始”和“结束”。 | | -| A.4.6 | 图形逻辑清晰,图文配合使用,切忌图文分离。 | | -| A.4.7 | 图片的高度建议在640px左右,宽度不超过820px,一般为.png格式,图片的大小建议不超过150k。 | | -| A.4.8 | 图形建议尽量不要用文字,中文图用中文,英文图用英文。 | | - - -## 基本概念 - -*【 **写作要求】*** - -*必选,描述本开发任务相关的基本概念,帮助开发者更好的理解开发任务。* *写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| B.1.1 | 业界通用的概念不用再此赘述。 | | -| B.1.2 | 注意使用业界通用术语来表达,不用华为研发内部语言。 | | -| B.1.3 | 基本概念要黑盒描述,不用体现具体细节。 | | - - -【写作样例】 - - -鸿蒙系统音频模块支持音频业务的开发,提供音频相关的功能,主要包括音频播放、音频采集、音量管理和短音播放等。 - - -在进行应用的开发前,开发者应了解以下基本概念: - - -- 采样 - 采样就是把模拟信号数字化的过程,所有的模拟信号都需要通过采样转换为可以用0101来表示的数字信号。 - -- 采样率 - 采样率为每秒从连续信号中提取并组成离散信号的采样次数,单位用赫兹(Hz)来表示。通常人耳能听到频率范围大约在20Hz~20kHz之间的声音。常用的音频采样频率有:8kHz、11.025kHz、22.05kHz、16kHz、37.8kHz、44.1kHz、48kHz、96kHz、192kHz等。 - -- 声道 - 声道是指声音在录制或播放时在不同空间位置采集或回放的相互独立的音频信号,所以声道数也就是声音录制时的音源数量或回放时相应的扬声器数量。 - -- 音频帧 - 音频数据是流式的,本身没有明确的一帧帧的概念,在实际的应用中,为了音频算法处理/传输的方便,一般约定俗成取2.5ms~60ms为单位的数据量为一帧音频。这个时间被称之为“采样时间”,其长度没有特别的标准,它是根据编解码器和具体应用的需求来决定的。 - - -## 运作机制 - -*【 **写作要求】*** - -*可选。如果机制比较简单,通过前面基本概念就可以说清楚,此章节可以不用提供,删除标题即可。* - -*描述实现原理介绍机制,如关键步骤相关接口调用时机和触发时机,帮助开发者了解该功能的基本运作原理,以便更好的理解开发任务和定位问题。* - -* 写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| C.1.1 | 仅描述开发任务相关的原理。 | | -| C.1.2 | 尽量图文配合,一般使用时序图、流程图等形式。文字描述与图形描述匹配。 | | -| C.1.3 | 原理要黑盒描述,注意不要泄密。 | | - -【写作样例-1】 - -- 信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,受内存限制),并把所有的信号量初始化成未使用,并加入到未使用链表中供系统使用。 - -- 信号量创建,从未使用的信号量链表中获取一个信号量资源,并设定初值。 - -- 信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 - -- 信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 - -- 信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 - -- 信号量允许多个任务在同一时刻访问同一资源,但会限制同一时刻访问此资源的最大任务数目。访问同一资源的任务数达到该资源的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 - ![1624266502700](C:\Users\LWX104~1\AppData\Local\Temp\1624266502700.png) - - 【写作样例-2】 - - **互斥锁运作原理** - - 多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢? - - 用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 - - **图2** 互斥锁运作示意图 - ![1624266485662](C:\Users\LWX104~1\AppData\Local\Temp\1624266485662.png) - - -## 约束与限制 - -* **【写作要求】*** - -*必选。* *描述本开发任务过程中* *的约束条件,以及此操作约束带来相应的负面影响,包括但不限于如下几方面:* - -* **功能限制:*** - -- * 功能使用范围(明确不支持的场景)。* - -- *规格限制。* - -* **操作限制** **:*** - -- * 已知问题的操作。* - -- * 潜在风险的操作(如引起性能降低)。* - -- * 引起性能降低的操作*。 - -* 写作要求见下,完成写作后,请逐项自检。* - -| 要求项 | 内容要求 | 是否满足 | -| -------- | -------- | -------- | -| D.1.1 | 明确功能限制或操作限制。 | | -| D.1.2 | 约束对指导任务开发有影响或体验有感知,否则不用体现。 | | -| D.1.3 | 容易出错的操作在步骤里描述,不在此体现。 | | - -**【写作样例】** - -**互斥锁的约束与限制:** - -- 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。 - -- 互斥锁不能在中断服务程序中使用。 - -- Huawei LiteOS作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。 - -- 持有互斥锁的过程中,不得再调用LOS_TaskPriSet等接口更改持有互斥锁任务的优先级。 diff --git "a/zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" "b/zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" deleted file mode 100644 index 86080372577209de5d8bdb01955b3e6834525b1c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/C++\346\224\257\346\214\201.md" +++ /dev/null @@ -1,86 +0,0 @@ -# C++支持 - -- [基本概念](#section11374125415814) - - [运行机制](#section125251720195) - -- [开发指导](#section166302407911) - - [接口说明](#section1881825119919) - - [开发流程](#section76371145108) - - [编程实例](#section994427141111) - - -## 基本概念 - -C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上开发的一种面向对象的编程语言。 - -### 运行机制 - -C++代码的识别主要由编译器支持,系统主要对全局对象进行构造函数调用,进行初始化操作。 - -## 开发指导 - -### 接口说明 - -**表 1** C++支持接口 - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

使用C++特性的前置条件

-

LOS_CppSystemInit

-

C++构造函数初始化

-
- -### 开发流程 - -使用C++特性之前,需要调用函数LOS\_CppSystemInit,实现C++构造函数初始化,其中被初始化的构造函数存在init\_array这个段中,段区间通过变量\_\_init\_array\_start\_\_、\_\_init\_array\_end\_\_传递。 - -**表 2** 参数说明 - - - - - - - - - - - - - -

参数

-

参数说明

-

__init_array_start__

-

init_array段起始位置

-

__init_array_end__

-

init_array段结束位置

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->调用该函数时,一定要在c++业务前。另外部分与系统资源强相关的类或接口,如std::thread,std::mutex等,在三方编译器使用的c库非musl c时,存在兼容性问题,不建议使用。 - -### 编程实例 - -``` -void app_init(void) -{ -...... -/* 启动阶段C++初始化 */ -LOS_CppSystemInit((UINTPTR)&__init_array_start__, (UINTPTR)&__init_array_end__); -/* C++业务 */ -...... -} -``` - diff --git "a/zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" "b/zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" deleted file mode 100644 index 4f64bc6b8ca9b68a2f5b19dd23c7548555cb71b6..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/CMSIS\346\224\257\346\214\201.md" +++ /dev/null @@ -1,487 +0,0 @@ -# CMSIS支持 - -- [基本概念](#section131091144111615) -- [开发指导](#section57653573161) - - [接口说明](#section1795910417173) - - [开发流程](#section48301225131720) - - [编程实例](#section524434761713) - - -## 基本概念 - -[CMSIS](https://developer.arm.com/tools-and-software/embedded/cmsis)是Cortex Microcontroller Software Interface Standard(Cortex微控制器软件接口标准)的缩写,是对于那些基于ARM Cortex处理器的微控制器独立于供应商的硬件抽象层。它包含多个组件层,其中之一是RTOS层,该层定义了一套通用及标准化的RTOS API接口,减少了应用开发者对特定RTOS的依赖,方便用户软件的移植重用。该套API有2个版本,分别为版本1(CMSIS-RTOS v1)和版本2(CMSIS-RTOS v2),OpenHarmony LiteOS-M仅提供其版本2的实现。 - -## 开发指导 - -### 接口说明 - -CMSIS-RTOS v2提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** CMSIS-RTOS v2接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

内核信息与控制

-

osKernelGetInfo

-

获取RTOS内核信息。

-

osKernelGetState

-

获取当前的RTOS内核状态。

-

osKernelGetSysTimerCount

-

获取RTOS内核系统计时器计数。

-

osKernelGetSysTimerFreq

-

获取RTOS内核系统计时器频率。

-

osKernelInitialize

-

初始化RTOS内核。

-

osKernelLock

-

锁定RTOS内核调度程序。

-

osKernelUnlock

-

解锁RTOS内核调度程序。

-

osKernelRestoreLock

-

恢复RTOS内核调度程序锁定状态。

-

osKernelResume

-

恢复RTOS内核调度程序。(暂未实现)

-

osKernelStart

-

启动RTOS内核调度程序。

-

osKernelSuspend

-

挂起RTOS内核调度程序。(暂未实现)

-

osKernelGetTickCount

-

获取RTOS内核滴答计数。

-

osKernelGetTickFreq

-

获取RTOS内核滴答频率。

-

线程管理

-

osThreadDetach

-

分离线程(线程终止时可以回收线程存储)。(暂未实现)

-

osThreadEnumerate

-

枚举活动线程。(暂未实现)

-

osThreadExit

-

终止当前正在运行的线程的执行。

-

osThreadGetCount

-

获取活动线程的数量。

-

osThreadGetId

-

返回当前正在运行的线程的线程ID。

-

osThreadGetName

-

获取线程的名称。

-

osThreadGetPriority

-

获取线程的当前优先级。

-

osThreadGetStackSize

-

获取线程的堆栈大小。

-

osThreadGetStackSpace

-

根据执行期间的堆栈水印记录获取线程的可用堆栈空间。

-

osThreadGetState

-

获取线程的当前线程状态。

-

osThreadJoin

-

等待指定线程终止。(暂未实现)

-

osThreadNew

-

创建一个线程并将其添加到活动线程中。

-

osThreadResume

-

恢复线程的执行。

-

osThreadSetPriority

-

更改线程的优先级。

-

osThreadSuspend

-

暂停执行线程。

-

osThreadTerminate

-

终止线程的执行。

-

osThreadYield

-

将控制权传递给处于就绪状态的下一个线程。

-

线程标志

-

osThreadFlagsSet

-

设置线程的指定线程标志。(暂未实现)

-

osThreadFlagsClear

-

清除当前正在运行的线程的指定线程标志。(暂未实现)

-

osThreadFlagsGet

-

获取当前正在运行的线程的当前线程标志。(暂未实现)

-

osThreadFlagsWait

-

等待当前正在运行的线程的一个或多个线程标志发出信号。(暂未实现)

-

事件标志

-

osEventFlagsGetName

-

获取事件标志对象的名称。(暂未实现)

-

osEventFlagsNew

-

创建并初始化事件标志对象。

-

osEventFlagsDelete

-

删除事件标志对象。

-

osEventFlagsSet

-

设置指定的事件标志。

-

osEventFlagsClear

-

清除指定的事件标志。

-

osEventFlagsGet

-

获取当前事件标志。

-

osEventFlagsWait

-

等待一个或多个事件标志被发出信号。

-

通用等待函数

-

osDelay

-

等待超时(时间延迟)。

-

osDelayUntil

-

等到指定时间。

-

计时器管理

-

osTimerDelete

-

删除计时器。

-

osTimerGetName

-

获取计时器的名称。(暂未实现)

-

osTimerIsRunning

-

检查计时器是否正在运行。

-

osTimerNew

-

创建和初始化计时器。

-

osTimerStart

-

启动或重新启动计时器。

-

osTimerStop

-

停止计时器。

-

互斥管理

-

osMutexAcquire

-

获取互斥或超时(如果已锁定)。

-

osMutexDelete

-

删除互斥对象。

-

osMutexGetName

-

获取互斥对象的名称。(暂未实现)

-

osMutexGetOwner

-

获取拥有互斥对象的线程。

-

osMutexNew

-

创建并初始化Mutex对象。

-

osMutexRelease

-

释放由osMutexAcquire获取的Mutex。

-

信号量

-

osSemaphoreAcquire

-

获取信号量令牌或超时(如果没有可用的令牌)。

-

osSemaphoreDelete

-

删除一个信号量对象。

-

osSemaphoreGetCount

-

获取当前信号量令牌计数。

-

osSemaphoreGetName

-

获取信号量对象的名称。(暂未实现)

-

osSemaphoreNew

-

创建并初始化一个信号量对象。

-

osSemaphoreRelease

-

释放信号量令牌,直到初始最大计数。

-

内存池

-

osMemoryPoolAlloc

-

从内存池分配一个内存块。

-

osMemoryPoolDelete

-

删除内存池对象。

-

osMemoryPoolFree

-

将分配的内存块返回到内存池。

-

osMemoryPoolGetBlockSize

-

获取内存池中的内存块大小。

-

osMemoryPoolGetCapacity

-

获取内存池中最大的内存块数。

-

osMemoryPoolGetCount

-

获取内存池中使用的内存块数。

-

osMemoryPoolGetName

-

获取内存池对象的名称。

-

osMemoryPoolGetSpace

-

获取内存池中可用的内存块数。

-

osMemoryPoolNew

-

创建并初始化一个内存池对象。

-

消息队列

-

osMessageQueueDelete

-

删除消息队列对象。

-

osMessageQueueGet

-

从队列获取消息,或者如果队列为空,则从超时获取消息。

-

osMessageQueueGetCapacity

-

获取消息队列中的最大消息数。

-

osMessageQueueGetCount

-

获取消息队列中排队的消息数。

-

osMessageQueueGetMsgSize

-

获取内存池中的最大消息大小。

-

osMessageQueueGetName

-

获取消息队列对象的名称。(暂未实现)

-

osMessageQueueGetSpace

-

获取消息队列中消息的可用插槽数。

-

osMessageQueueNew

-

创建和初始化消息队列对象。

-

osMessageQueuePut

-

如果队列已满,则将消息放入队列或超时。

-

osMessageQueueReset

-

将消息队列重置为初始空状态。(暂未实现)

-
- -### 开发流程 - -CMSIS-RTOS2组件可以作为库或源代码提供(下图显示了库)。通过添加CMSIS-RTOS2组件(通常是一些配置文件),可以将基于CMSIS的应用程序扩展为具有RTOS功能。只需包含cmsis\_os2.h头文件就可以访问RTOS API函数,这使用户应用程序能够处理RTOS内核相关事件,而在更换内核时无需重新编译源代码。 - -静态对象分配需要访问RTOS对象控制块定义。特定于实现的头文件(下图中的os\_xx .h)提供对此类控制块定义的访问。对于OpenHarmony LiteOS-M内核,由文件名以los\_开头的头文件提供,这些文件包含OpenHarmony LiteOS-M内核的这些定义。 - -![](figures/zh-cn_image_0000001121429646.png) - -### 编程实例 - -``` -#include ... -#include "cmsis_os2.h" - -/*---------------------------------------------------------------------------- - * 应用程序主线程 - *---------------------------------------------------------------------------*/ -void app_main (void *argument) { - // ... - for (;;) {} -} - -int main (void) { - // 系统初始化 - MySystemInit(); - // ... - - osKernelInitialize(); // 初始化CMSIS-RTOS - osThreadNew(app_main, NULL, NULL); // 创建应用程序主线程 - osKernelStart(); // 开始执行线程 - for (;;) {} -} -``` - diff --git a/zh-cn/device-dev/kernel/FAT-20.md b/zh-cn/device-dev/kernel/FAT-20.md deleted file mode 100644 index 7b8620cb01f87d0e84a8f72b5b253536ac440ed9..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/FAT-20.md +++ /dev/null @@ -1,176 +0,0 @@ -# FAT - -- [基本概念](#section1772629121418) -- [开发指导](#section1149072811148) - - [驱动适配](#section19174939191414) - - [开发流程](#section131211626151513) - - [编程实例](#section206071303163) - - [实例描述](#section45337345313) - - [示例代码](#section119813171539) - - [结果验证](#section7987101232311) - - -## 基本概念 - -FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。 - -OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。 - -## 开发指导 - -### 驱动适配 - -FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要: - -1、适配板端EMMC驱动,实现disk\_status、disk\_initialize、disk\_read、disk\_write、disk\_ioctl接口; - -2、新增fs\_config.h文件,配置FS\_MAX\_SS(存储设备最大sector大小)、FF\_VOLUME\_STRS(分区名)等信息,例如: - -``` -#define FF_VOLUME_STRS "system", "inner", "update", "user" -#define FS_MAX_SS 512 -#define FAT_MAX_OPEN_FILES 50 -``` - -### 开发流程 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- FATFS文件与目录操作: -> - 单个文件大小不超过4G。 -> - 支持同时打开的文件数最大为FAT\_MAX\_OPEN\_FILES,文件夹数最大为FAT\_MAX\_OPEN\_DIRS。 -> - 暂不支持根目录管理,文件/目录名均以分区名开头,例如“user/testfile”就是在“user”分区下名为“testfile”的文件或目录。 -> - 若需要同时多次打开同一文件,必须全部使用只读方式(O\_RDONLY)。以可写方式(O\_RDWR、O\_WRONLY等)只能打开一次。 -> - 读写指针未分离,例如以O\_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。 -> - 暂不支持文件与目录的权限管理。 -> - stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。 ->- FATFS分区挂载与卸载: -> - 支持以只读属性挂载分区。当mount函数的入参为MS\_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O\_RDONLY属性的open,将均被拒绝。 -> - mount支持通过MS\_REMOUNT标记修改已挂载分区的权限。 -> - 在umount操作前,需确保所有目录及文件全部关闭。 -> - umount2支持通过MNT\_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。 ->- FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs\_fdisk与fatfs\_format: -> - 在fatfs\_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。 -> - 在fatfs\_fdisk操作前,需要该设备中的所有分区均已umount。 -> - fatfs\_fdisk与fatfs\_format会造成设备数据丢失,请谨慎使用。 - -### 编程实例 - -### 实例描述 - -本实例实现以下功能: - -1. 创建目录“user/test” -2. 在“user/test”目录下创建文件“file.txt” -3. 在文件起始位置写入“Hello OpenHarmony!” -4. 将文件内容刷入设备中 -5. 设置偏移到文件起始位置 -6. 读取文件内容 -7. 关闭文件 -8. 删除文件 -9. 删除目录 - -### 示例代码 - -前提条件: - -- 系统已将MMC设备分区挂载到user目录 - -代码实现如下: - -``` -#include -#include -#include "sys/stat.h" -#include "fcntl.h" -#include "unistd.h" - -#define LOS_OK 0 -#define LOS_NOK -1 - -int FatfsTest(void) -{ - int ret; - int fd = -1; - ssize_t len; - off_t off; - char dirName[20] = "user/test"; - char fileName[20] = "user/test/file.txt"; - char writeBuf[20] = "Hello OpenHarmony!"; - char readBuf[20] = {0}; - - /* 创建目录“user/test” */ - ret = mkdir(dirName, 0777); - if (ret != LOS_OK) { - printf("mkdir failed.\n"); - return LOS_NOK; - } - - /* 创建可读写文件"user/test/file.txt" */ - fd = open(fileName, O_RDWR | O_CREAT, 0777); - if (fd < 0) { - printf("open file failed.\n"); - return LOS_NOK; - } - - /* 将writeBuf中的内容写入文件 */ - len = write(fd, writeBuf, strlen(writeBuf)); - if (len != strlen(writeBuf)) { - printf("write file failed.\n"); - return LOS_NOK; - } - - /* 将文件内容刷入存储设备中 */ - ret = fsync(fd); - if (ret != LOS_OK) { - printf("fsync failed.\n"); - return LOS_NOK; - } - - /* 将读写指针偏移至文件头 */ - off = lseek(fd, 0, SEEK_SET); - if (off != 0) { - printf("lseek failed.\n"); - return LOS_NOK; - } - - /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */ - len = read(fd, readBuf, sizeof(readBuf)); - if (len != strlen(writeBuf)) { - printf("read file failed.\n"); - return LOS_NOK; - } - printf("%s\n", readBuf); - - /* 关闭文件 */ - ret = close(fd); - if (ret != LOS_OK) { - printf("close failed.\n"); - return LOS_NOK; - } - - /* 删除文件"user/test/file.txt" */ - ret = unlink(fileName); - if (ret != LOS_OK) { - printf("unlink failed.\n"); - return LOS_NOK; - } - - /* 删除目录“user/test” */ - ret = rmdir(dirName); - if (ret != LOS_OK) { - printf("rmdir failed.\n"); - return LOS_NOK; - } - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Hello OpenHarmony! -``` - diff --git a/zh-cn/device-dev/kernel/IPC.md b/zh-cn/device-dev/kernel/IPC.md deleted file mode 100644 index 14c3d35d893aa9d29c15274d40231c9393ee0fa0..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/IPC.md +++ /dev/null @@ -1,11 +0,0 @@ -# IPC - -- **[事件](事件.md)** - -- **[互斥锁](互斥锁.md)** - -- **[消息队列](消息队列.md)** - -- **[信号量](信号量.md)** - - diff --git "a/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" deleted file mode 100755 index 1dec4cb1447cc02fce0739300e12aeef80e135c7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\347\274\226\350\257\221\344\270\216\346\236\204\345\273\272\346\214\207\345\257\274.md" +++ /dev/null @@ -1,47 +0,0 @@ -# Linux内核编译与构建指导 - -- [开发示例1](#section19369206113115) - - [场景1:版本级编译原生方式](#section1025111193220) - - [场景2:单独编译修改后的内核](#section17446652173211) - - -## 开发示例1 - -以hi3516dv300开源开发板+ubuntu x86主机开发环境为例。 - -### 场景1:版本级编译原生方式 - -使用工程的全量编译命令,编译生成uImage内核镜像 - -``` -./build.sh --product-name Hi3516DV300 # 编译hi3516dv300的uImage内核镜像 -``` - -### 场景2:单独编译修改后的内核 - -1. 准备工作 - - 1. 按[开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md)打入所需补丁。 - 2. 准备编译环境,可以使用开源arm clang/gcc编译器。 - - 进入工程主目录配置环境变量: - - ``` - export PATH=`pwd`/prebuilts/clang/host/linux-x86/clang-r353983c/bin:`pwd`/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/:$PATH # 配置编译环境 - MAKE_OPTIONES="ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CC=clang HOSTCC=clang" # 使用工程项目自带的clang环境 - ``` - -2. 修改内核代码或内核config (OpenHarmony提供对应平台的defconfig供参考)。 -3. 创建编译目录及生成内核.config。 - - ``` - make ${MAKE_OPTIONES} hi3516dv300_emmc_smp_hos_l2_defconfig # 使用自带的默认config 构建内核 - ``` - -4. 编译生成对应的内核Image。 - - ``` - make ${MAKE_OPTIONES} -j32 uImage # 编译uImage内核镜像 - ``` - - diff --git a/zh-cn/device-dev/kernel/LittleFS.md b/zh-cn/device-dev/kernel/LittleFS.md deleted file mode 100644 index 1f8ad2cec85fe0c0b5c45076a705e5f12045fa8c..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/LittleFS.md +++ /dev/null @@ -1,7 +0,0 @@ -# LittleFS - -- **[基本概念](基本概念-21.md)** - -- **[开发指导](开发指导-22.md)** - - diff --git a/zh-cn/device-dev/kernel/NFS.md b/zh-cn/device-dev/kernel/NFS.md deleted file mode 100755 index d319329c44d3c54e4597a68ce64465886143c7b2..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/NFS.md +++ /dev/null @@ -1,163 +0,0 @@ -# NFS - -- [概述](#section18322139164413) -- [注意事项](#section532912331467) -- [开发指导](#section166873374711) - -## 概述 - -NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。因此,用户可以简单地将它看做是一个文件系统服务,在一定程度上相当于Windows环境下的共享文件夹。 - -NFS客户端用户,能够将网络远程的NFS服务端分享的目录挂载到本地端的机器中,运行程序和共享文件,但不占用当前的系统资源,所以,在本地端的机器看起来,远程服务端的目录就好像是自己的一个磁盘一样。 - -## 注意事项 - -- 当前NFS文件不支持权限控制,请在创建NFS目录和文件时使用777权限。 - -- 当前NFS文件不支读阻塞和写阻塞。 - -- 当前NFS文件不支持信号功能。 - -- 当前NFS文件系统mount路径长度(不包含IP的长度)不超过255个字符,超过时返回ENAMETOOLONG错误。 - -- 当前NFS文件支持的操作有:open, close, read, write, seek, dup, dup2, sync, opendir, closedir, readdir, readdir\_r, rewinddir, scandir, statfs, remove, unlink, mkdir, rmdir, rename, stat, stat64, seek64, mmap, mount, umount。 - -- 当前NFS支持TCP和UDP两种传输层协议,默认使用TCP。 - -- open打开一个文件,参数有O\_TRUNC时,必须同时拥有写的权限,才会将文件中的内容清空。 - -- 在文件未关闭的情况下,rename\(\)函数重命名A为B之后,不会改变文件fd。 - -- NFS功能目前处于beta测试阶段,可能存在功能不稳定的情况,建议您不要用于正式商用产品当中。 - - -## 开发指导 - -1. **搭建NFS服务器**。 - - 这里以Ubuntu操作系统为例,说明服务器端设置步骤。 - - 1. 安装NFS服务器软件。 - - 设置好Ubuntu系统的下载源,保证网络连接好的情况下执行: - - ``` - sudo apt-get install nfs-kernel-server - ``` - - 2. 创建用于挂载的目录并设置完全权限 - - ``` - mkdir /home/sqbin/nfs - sudo chmod 777 /home/sqbin/nfs - ``` - - 3. 设置和启动NFS server。 - - 修改NFS配置文件/etc/exports,添加如下一行: - - ``` - /home/sqbin/nfs *(rw,no_root_squash,async) - ``` - - 其中/home/sqbin/nfs是NFS共享的根目录。 - - 执行以下命令启动NFS server: - - ``` - sudo /etc/init.d/nfs-kernel-server start - ``` - - 执行以下命令重启NFS server: - - ``` - sudo /etc/init.d/nfs-kernel-server restart - ``` - - -2. **设置单板为NFS客户端**。 - - 本指导中的NFS客户端指运行OpenHarmony内核的设备。 - - 1. 硬件连接设置。 - - OpenHarmony内核设备连接到NFS服务器的网络。设置两者IP,使其处于同一网段。比如,设置NFS服务器的IP为10.67.212.178/24,设置OpenHarmony内核设备IP为10.67.212.3/24,注意:此IP为内网私有IP地址,用户使用时有差异,以用户实际IP为准。 - - OpenHarmony内核设备上的IP信息可通过ifconfig命令查看。 - - 2. 启动网络,确保单板到NFS服务器之间的网络通畅。 - - 启动以太网或者其他类型网络,使用ping命令检查到服务器的网络是否通畅。 - - ``` - OHOS # ping 10.67.212.178 - [0]Reply from 10.67.212.178: time=1ms TTL=63 - [1]Reply from 10.67.212.178: time=0ms TTL=63 - [2]Reply from 10.67.212.178: time=1ms TTL=63 - [3]Reply from 10.67.212.178: time=1ms TTL=63 - --- 10.67.212.178 ping statistics --- - 4 packets transmitted, 4 received, 0 loss - ``` - - 客户端NFS初始化,运行命令: - - ``` - OHOS # mkdir /nfs - OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 - ``` - - 将从串口得到如下回应信息,表明初始化NFS客户端成功。 - - ``` - OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 - Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000 - Mount nfs finished. - ``` - - 该命令将服务器10.67.212.178上的/home/sqbin/nfs目录mount在OpenHarmony内核设备上的/nfs上。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >本例默认nfs server已经配置可用,即示例中服务器10.67.212.178上的/home/sqbin/nfs已配置可访问。 - - mount命令的格式为: - - ``` - mount nfs - ``` - - 其中“SERVER\_IP“表示服务器的IP地址;“SERVER\_PATH“表示服务器端NFS共享目录路径;“CLIENT\_PATH“表示设备上的NFS路径。 - - 如果不想有NFS访问权限限制,请在Linux命令行将NFS根目录权限设置成777: - - ``` - chmod -R 777 /home/sqbin/nfs - ``` - - 至此,NFS客户端设置完毕。NFS文件系统已成功挂载。 - - -3. **利用NFS共享文件**。 - - 在NFS服务器下新建目录dir,并保存。在OpenHarmony内核下运行ls命令: - - ``` - OHOS # ls /nfs - ``` - - 则可从串口得到如下回应: - - ``` - OHOS # ls /nfs - Directory /nfs: - drwxr-xr-x 0 u:0 g:0 dir - ``` - - 可见,刚刚在NFS服务器上新建的dir目录已同步到客户端\(OpenHarmony内核系统\)的/nfs目录,两者保持同步。 - - 同样地,在客户端\(OpenHarmony内核系统\)上创建文件和目录,在NFS服务器上也可以访问,读者可自行体验。 - - **平台差异性:** - - 目前,NFS客户端仅支持NFS v3部分规范要求,因此对于规范支持不全的服务器,无法完全兼容。在开发测试过程中,建议使用Linux的NFS server,因为其对NFS支持很完善。 - - diff --git "a/zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 25eadc954a75a4ec4e0f5855b95e9d2e527d31a7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/OpenHarmony\345\274\200\345\217\221\346\235\277Patch\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,17 +0,0 @@ -# OpenHarmony开发板Patch使用指导 - -Patch文件位于工程项目源码路径:kernel/linux/patches/linux-4.19,存放特定芯片架构驱动补丁。 - -如需使用特定芯片平台驱动的Patch,需要在内核仓代码完成对芯片平台驱动补丁合入。 - -合入芯片平台驱动补丁,针对不同芯片平台合入对应的patch: - -以Hi3516dv300为例: - -``` -patch -p1 < device/hisilicon/hi3516dv300/sdk_linux/open_source/linux/hisi_linux-4.19_hos_l2.patch -``` - ->![](public_sys-resources/icon-notice.gif) **须知:** ->由于OpenHarmony的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用OpenHarmony的版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 - diff --git a/zh-cn/device-dev/kernel/Readme-CN.md b/zh-cn/device-dev/kernel/Readme-CN.md index 8b5a59ad1b9f2ddb7beb2c0424b72dd5bc53d432..3149ba1128ab511901f59a3614f077695b183cf0 100755 --- a/zh-cn/device-dev/kernel/Readme-CN.md +++ b/zh-cn/device-dev/kernel/Readme-CN.md @@ -1,166 +1,152 @@ # 内核使用指南 -- [轻量和小型系统内核](轻量和小型系统内核.md) - - [轻量系统内核](轻量系统内核.md) - - [基础内核](基础内核.md) - - [进程](进程.md) - - [线程](线程.md) - - [内存](内存.md) - - [网络](网络.md) - - - [文件系统](文件系统.md) - - [VFS](VFS.md) - - [NFS](NFS.md) - - [RAMFS](RAMFS.md) - - [FAT](FAT.md) - - [JFFS2](JFFS2.md) - - - [标准库](标准库.md) - - [标准库](标准库-0.md) - - [与Linux标准库的差异](与Linux标准库的差异.md) - - - [调测](调测.md) - - [Shell介绍](Shell介绍.md) - - [Shell命令开发指导](Shell命令开发指导.md) - - [Shell命令编程实例](Shell命令编程实例.md) - - [Shell命令使用详解](Shell命令使用详解.md) - - [系统命令](系统命令.md) - - [cpup](cpup.md) - - [date](date.md) - - [dmesg](dmesg.md) - - [exec](exec.md) - - [free](free.md) - - [help](help.md) - - [hwi](hwi.md) - - [kill](kill.md) - - [log](log.md) - - [memcheck](memcheck.md) - - [oom](oom.md) - - [pmm](pmm.md) - - [reset](reset.md) - - [sem](sem.md) - - [stack](stack.md) - - [su](su.md) - - [swtmr](swtmr.md) - - [systeminfo](systeminfo.md) - - [task](task.md) - - [uname](uname.md) - - [vmm](vmm.md) - - [watch](watch.md) - - - [文件命令](文件命令.md) - - [cat](cat.md) - - [cd](cd.md) - - [chgrp](chgrp.md) - - [chmod](chmod.md) - - [chown](chown.md) - - [cp](cp.md) - - [format](format.md) - - [ls](ls.md) - - [lsfd](lsfd.md) - - [mkdir](mkdir.md) - - [mount](mount.md) - - [partinfo](partinfo.md) - - [partition](partition.md) - - [pwd](pwd.md) - - [rm](rm.md) - - [rmdir](rmdir.md) - - [statfs](statfs.md) - - [sync](sync.md) - - [touch](touch.md) - - [writeproc](writeproc.md) - - [umount](umount.md) - - - [网络命令](网络命令.md) - - [arp](arp.md) - - [dhclient](dhclient.md) - - [dns](dns.md) - - [ifconfig](ifconfig.md) - - [ipdebug](ipdebug.md) - - [netstat](netstat.md) - - [ntpdate](ntpdate.md) - - [ping](ping.md) - - [ping6](ping6.md) - - [telnet](telnet.md) - - [tftp](tftp.md) - - - [魔法键使用方法](魔法键使用方法.md) - - [用户态异常信息说明](用户态异常信息说明.md) - - - [小型系统内核](小型系统内核.md) - - [认识LiteOS-M内核](认识LiteOS-M内核.md) - - [快速入门](快速入门.md) - - [基础内核](基础内核-1.md) - - [中断管理](中断管理.md) - - [基本概念](基本概念.md) - - [开发指导](开发指导.md) - - - [任务管理](任务管理.md) - - [基本概念](基本概念-2.md) - - [开发指导](开发指导-3.md) - - - [内存管理](内存管理.md) - - [基本概念](基本概念-4.md) - - [静态内存](静态内存.md) - - [动态内存](动态内存.md) - - - [IPC](IPC.md) - - [事件](事件.md) - - [基本概念](基本概念-5.md) - - [开发指导](开发指导-6.md) - - - [互斥锁](互斥锁.md) - - [基本概念](基本概念-7.md) - - [开发指导](开发指导-8.md) - - - [消息队列](消息队列.md) - - [基本概念](基本概念-9.md) - - [开发指导](开发指导-10.md) - - - [信号量](信号量.md) - - [基本概念](基本概念-11.md) - - [开发指导](开发指导-12.md) - - - [时间管理](时间管理.md) - - [基本概念](基本概念-13.md) - - [开发指导](开发指导-14.md) - - - [软件定时器](软件定时器.md) - - [基本概念](基本概念-15.md) - - [开发指导](开发指导-16.md) - - - [扩展组件](扩展组件.md) - - [C++支持](C++支持.md) - - [CPUP](CPUP.md) - - [基本概念](基本概念-17.md) - - [开发指导](开发指导-18.md) - - - [文件系统](文件系统-19.md) - - [FAT](FAT-20.md) - - [LittleFS](LittleFS.md) - - [基本概念](基本概念-21.md) - - [开发指导](开发指导-22.md) - - - [内核调测](内核调测.md) - - [内存调测](内存调测.md) - - [内存信息统计](内存信息统计.md) - - [内存泄漏检测](内存泄漏检测.md) - - [踩内存检测](踩内存检测.md) - - - [异常调测](异常调测.md) - - [Trace调测](Trace调测.md) - - - [附录](附录.md) - - [内核编码规范](内核编码规范.md) - - [基本数据结构](基本数据结构.md) - - [双向链表](双向链表.md) - - - [标准库支持](标准库支持.md) - - [CMSIS支持](CMSIS支持.md) - - [POSIX支持](POSIX支持.md) - -- [标准系统内核](标准系统内核.md) - - [Linux内核概述](Linux内核概述.md) - - [OpenHarmony开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md) - - [Linux内核编译与构建指导](Linux内核编译与构建指导.md) +- [轻量和小型系统内核](kernel-lite.md) + + - [轻量系统内核](kernel-lite-mini.md) + - [内核概述](kernel-lite-mini-m.md) + - [基础内核](kernel-lite-mini-basic.md) + - [中断管理](kernel-lite-mini-basic-interrupt.md) + - [基本概念](kernel-lite-mini-basic-interrupt-concept.md) + - [开发指导](kernel-lite-mini-basic-interrupt-guide.md) + - [任务管理](kernel-lite-mini-basic-task.md) + - [基本概念](kernel-lite-mini-basic-task-basic.md) + - [开发指导](kernel-lite-mini-basic-task-guide.md) + - [内存管理](kernel-lite-mini-basic-memory.md) + - [基本概念](kernel-lite-mini-basic-memory-basic.md) + - [静态内存](kernel-lite-mini-basic-memory-static.md) + - [动态内存](kernel-lite-mini-basic-memory-dynamic.md) + - [内核通信机制](kernel-lite-mini-basic-ipc.md) + - [事件](kernel-lite-mini-basic-ipc-event.md) + - [基本概念](kernel-lite-mini-basic-ipc-event-guide.md) + - [开发指导](kernel-lite-mini-basic-ipc-event-basic.md) + - [互斥锁](kernel-lite-mini-basic-ipc-mutex.md) + - [基本概念](kernel-lite-mini-basic-ipc-mutex-basic.md) + - [开发指导](kernel-lite-mini-basic-ipc-mutex-guide.md) + - [消息队列](kernel-lite-mini-basic-ipc-queue.md) + - [基本概念](kernel-lite-mini-basic-ipc-queue-basic.md) + - [开发指导](kernel-lite-mini-basic-ipc-queue-guide.md) + - [信号量](kernel-lite-mini-basic-ipc-sem.md) + - [基本概念](kernel-lite-mini-basic-ipc-sem-basic.md) + - [开发指导](kernel-lite-mini-basic-ipc-sem-guide.md) + - [时间管理](kernel-lite-basic-mini-time.md) + - [基本概念](kernel-lite-mini-basic-time-basic.md) + - [开发指导](kernel-lite-mini-basic-time-guide.md) + - [软件定时器](kernel-lite-mini-basic-soft.md) + - [基本概念](kernel-lite-mini-basic-soft-basic.md) + - [开发指导](kernel-lite-mini-basic-soft-guide.md) + - [扩展组件](kernel-lite-mini-extend.md) + - [C++支持](kernel-lite-mini-extend-support.md) + - [CPU占用率](kernel-lite-mini-extend-cpup.md) + - [基本概念](kernel-lite-mini-extend-cpup-basic.md) + - [开发指导](kernel-lite-mini-extend-cpup-guide.md) + - [文件系统](kernel-lite-mini-extend-file.md) + - [FAT](kernel-lite-mini-extend-file-fat.md) + - [LittleFS](kernel-lite-mini-extend-file-lit.md) + - [基本概念](kernel-lite-mini-extend-file-lit-basic.md) + - [开发指导](kernel-lite-mini-extend-file-lit-guide.md) + - [内核调测](kernel-lite-mini-inner.md) + - [内存调测](kernel-lite-mini-inner-debug.md) + - [内存信息统计](kernel-lite-mini-inner-debug-mes.md) + - [内存泄漏检测](kernel-lite-mini-inner-debug-det.md) + - [踩内存检测](kernel-lite-mini-inner-debug-cet.md) + - [异常调测](kernel-lite-mini-inner-exception.md) + - [Trace调测](kernel-lite-mini-inner-trace.md) + - [附录](kernel-lite-mini-app.md) + - [内核编码规范](kernel-lite-mini-app-code.md) + - [基本数据结构](kernel-lite-mini-app-data.md) + - [双向链表](kernel-lite-mini-app-data-list.md) + - [标准库支持](kernel-lite-mini-app-lib.md) + - [CMSIS支持](kernel-lite-mini-app-lib-cmsis.md) + - [POSIX支持](kernel-lite-mini-app-lib-posix.md) + + - [小型系统内核](kernel-lite-small.md) + - [基础内核](kernel-lite-small-basic.md) + - [进程](kernel-lite-small-process.md) + - [线程](kernel-lite-small-thread.md) + - [内存](kernel-lite-small-memory.md) + - [网络](kernel-lite-small-net.md) + + - [文件系统](kernel-lite-small-file.md) + - [VFS](kernel-lite-small-file-vfs.md) + - [NFS](kernel-lite-small-file-nfs.md) + - [RAMFS](kernel-lite-small-file-ramfs.md) + - [FAT](kernel-lite-small-file-fat.md) + - [JFFS2](kernel-lite-small-file-jffs.md) + + - [标准库](kernel-lite-small-lib.md) + - [标准库](kernel-lite-small-lib-standard.md) + - [与Linux标准库的差异](kernel-lite-small-lib-differ.md) + + - [调测](kernel-lite-small-shell.md) + - [Shell介绍](kernel-lite-small-shell-des.md) + - [Shell命令开发指导](kernel-lite-small-shell-guide.md) + - [Shell命令编程实例](kernel-lite-small-shell-sample.md) + - [Shell命令使用详解](kernel-lite-small-shell-cmd.md) + - [系统命令](kernel-lite-small-shell-cmd-sys.md) + - [cpup](kernel-lite-small-shell-cmd-sys-cpup.md) + - [date](kernel-lite-small-shell-cmd-sys-date.md) + - [dmesg](kernel-lite-small-shell-cmd-sys-demsg.md) + - [exec](kernel-lite-small-shell-cmd-sys-exec.md) + - [free](kernel-lite-small-shell-cmd-sys-free.md) + - [help](kernel-lite-small-shell-cmd-sys-help.md) + - [hwi](kernel-lite-small-shell-cmd-sys-hwi.md) + - [kill](kernel-lite-small-shell-cmd-sys-kill.md) + - [log](kernel-lite-small-shell-cmd-sys-log.md) + - [memcheck](kernel-lite-small-shell-cmd-sys-mem.md) + - [oom](kernel-lite-small-shell-cmd-sys-oom.md) + - [pmm](kernel-lite-small-shell-cmd-sys-pmm.md) + - [reset](kernel-lite-small-shell-cmd-sys-reset.md) + - [sem](kernel-lite-small-shell-cmd-sys-sem.md) + - [stack](kernel-lite-small-shell-cmd-sys-stack.md) + - [su](kernel-lite-small-shell-cmd-sys-su.md) + - [swtmr](kernel-lite-small-shell-cmd-sys-swymr.md) + - [systeminfo](kernel-lite-small-shell-cmd-sys-sys.md) + - [task](kernel-lite-small-shell-cmd-sys-task.md) + - [uname](kernel-lite-small-shell-cmd-sys-uname.md) + - [vmm](kernel-lite-small-shell-cmd-sys-vmm.md) + - [watch](kernel-lite-small-shell-cmd-sys-watch.md) + + - [文件命令](kernel-lite-small-shell-cmd-file.md) + - [cat](kernel-lite-small-shell-cmd-file-cat.md) + - [cd](kernel-lite-small-shell-cmd-file-cd.md) + - [chgrp](kernel-lite-small-shell-cmd-file-chgrp.md) + - [chmod](kernel-lite-small-shell-cmd-file-chmod.md) + - [chown](kernel-lite-small-shell-cmd-file-chown.md) + - [cp](kernel-lite-small-shell-cmd-file-cp.md) + - [format](kernel-lite-small-shell-cmd-file-format.md) + - [ls](kernel-lite-small-shell-cmd-file-is.md) + - [lsfd](kernel-lite-small-shell-cmd-file-isfd.md) + - [mkdir](kernel-lite-small-shell-cmd-file-mkdir.md) + - [mount](kernel-lite-small-shell-cmd-file-mount.md) + - [partinfo](kernel-lite-small-shell-cmd-file-part.md) + - [partition](kernel-lite-small-shell-cmd-file-partion.md) + - [pwd](kernel-lite-small-shell-cmd-file-pwd.md) + - [rm](kernel-lite-small-shell-cmd-file-rm.md) + - [rmdir](kernel-lite-small-shell-cmd-file-rmdir.md) + - [statfs](kernel-lite-small-shell-cmd-file-sta.md) + - [sync](kernel-lite-small-shell-cmd-file-sync.md) + - [touch](kernel-lite-small-shell-cmd-file-touch.md) + - [writeproc](kernel-lite-small-shell-cmd-file-write.md) + - [umount](kernel-lite-small-shell-cmd-file-umount.md) + + - [网络命令](kernel-lite-small-shell-cmd-net.md) + - [arp](kernel-lite-small-shell-cmd-net-arp.md) + - [dhclient](kernel-lite-small-shell-cmd-net-dh.md) + - [dns](kernel-lite-small-shell-cmd-net-dns.md) + - [ifconfig](kernel-lite-small-shell-cmd-net-ipc.md) + - [ipdebug](kernel-lite-small-shell-cmd-net-ipd.md) + - [netstat](kernel-lite-small-shell-cmd-net-net.md) + - [ntpdate](kernel-lite-small-shell-cmd-net-ntp.md) + - [ping](kernel-lite-small-shell-cmd-net-ping.md) + - [ping6](kernel-lite-small-shell-cmd-net-ping6.md) + - [telnet](kernel-lite-small-shell-cmd-net-tel.md) + - [tftp](kernel-lite-small-shell-cmd-net-tftp.md) + + - [魔法键使用方法](kernel-lite-small-shell-cmd-mag.md) + - [用户态异常信息说明](kernel-lite-small-shell-cmd-abn.md) + +- [标准系统内核](kernel-standard.md) + - [Linux内核概述](kernel-standard-des.md) + - [OpenHarmony开发板Patch使用指导](kernel-standard-patch.md) + - [Linux内核编译与构建指导](kernel-standard-build.md) diff --git "a/zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" "b/zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" deleted file mode 100755 index f72e4f67cbb241de5b34b5fff11df56ef70ae2ef..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/Shell\344\273\213\347\273\215.md" +++ /dev/null @@ -1,36 +0,0 @@ -# Shell介绍 - -- [注意事项](#section12298165312328) - -OpenHarmony内核提供的Shell支持调试常用的基本功能,包含系统、文件、网络和动态加载相关命令。同时OpenHarmony内核的Shell支持添加新的命令,可以根据需求来进行定制。 - -- 系统相关命令:提供查询系统任务、内核信号量、系统软件定时器、CPU占用率、当前中断等相关信息的能力。 - -- 文件相关命令:支持基本的ls、cd等功能。 - -- 网络相关命令:支持查询接到开发板的其他设备的IP、查询本机IP、测试网络连接、设置开发板的AP和station模式等相关功能。 - - 新增命令的详细流程可参见[开发指导](Shell命令开发指导.md)和[编程实例](Shell命令编程实例.md)。 - - -## 注意事项 - -在使用Shell功能的过程中,需要注意以下几点: - -- Shell功能支持使用exec命令来运行可执行文件。 -- Shell功能支持默认模式下英文输入。如果出现用户在UTF-8格式下输入了中文字符的情况,只能通过回退三次来删除。 - -- Shell功能支持shell命令、文件名及目录名的Tab键联想补全。若有多个匹配项,则根据共同字符, 打印多个匹配项。对于过多的匹配项(打印多于24行),将会进行打印询问(Display all num possibilities?(y/n)),用户可输入y选择全部打印,或输入n退出打印,选择全部打印并打印超过24行后,会进行--More--提示,此时按回车键继续打印,按q键退出(支持Ctrl+c退出\)。 - -- Shell端工作目录与系统工作目录是分开的,即通过Shell端cd pwd等命令是对Shell端工作目录进行操作,通过chdir getcwd等命令是对系统工作目录进行操作,两个工作目录相互之间没有联系。当文件系统操作命令入参是相对路径时要格外注意。 - -- 在使用网络Shell指令前,需要先调用tcpip\_init函数完成网络初始化并完成telnet连接后才能起作用,内核默认不初始化tcpip\_init。 - -- 不建议使用Shell命令对/dev目录下的设备文件进行操作,这可能会引起不可预知的结果。 - -- Shell功能不符合POSIX标准,仅供调试使用。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >Shell功能仅供调试使用,在Debug版本中开启(使用时通过menuconfig在配置项中开启"LOSCFG\_DEBUG\_VERSION"编译开关进行相关控制),商用产品中禁止包含该功能。 - - diff --git "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" "b/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" deleted file mode 100755 index 2faa37c7405c336830f2cb2270275d44766497a6..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\344\275\277\347\224\250\350\257\246\350\247\243.md" +++ /dev/null @@ -1,13 +0,0 @@ -# Shell命令使用详解 - -本章节介绍了系统关键命令的功能、格式、参数范围、使用指南和使用实例。 - -不在本文档范围内的命令,详见[help](help.md)命令的输出内容,也可以通过命令的“-h | --help”选项,查看该命令的使用帮助。 - -- **[系统命令](系统命令.md)** - -- **[文件命令](文件命令.md)** - -- **[网络命令](网络命令.md)** - - diff --git "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index b8d1e6d8861489d99b76f84a56b9b0d2d09aecee..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,167 +0,0 @@ -# Shell命令开发指导 - -- [开发指导](#section22071515161018) - -## 开发指导 - -新增Shell命令的典型开发流程如下: - -1. 包含如下头文件: - - ``` - #include "shell.h" - #include "shcmd.h" - ``` - -2. 注册命令。用户可以选择静态注册命令方式和系统运行时动态注册命令方式,静态注册命令方式一般用在系统常用命令注册,动态注册命令方式一般用在用户命令注册。 - - 1. 静态注册命令方式: - - 1. 通过宏的方式注册。 - - 这个宏的原型为: - - ``` - SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) - ``` - - **表 1** SHELLCMD\_ENTRY参数详解 - - - - - - - - - - - - - - - - - - - - - - -

参数

-

描述

-

l

-

静态注册全局变量名(注意:不与系统中其他symbol重名)。

-

cmdType

-

命令类型:

-
  • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

    -
  • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

    -
-

cmdKey

-

命令关键字,函数在Shell中访问的名称。

-

paraNum

-

调用的执行函数的入参最大个数,暂不支持。

-

cmdHook

-

命令执行函数地址,即命令实际执行函数。

-
- - 如: - - ``` - SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) - ``` - - 2. 在build/mk/liteos\_tables\_ldflags.mk中添加相应选项: - - 如:上述“ls”命令注册时,需在build/mk/liteos\_tables\_ldflags.mk中添加“-uls\_shellcmd”。其中-u后面跟SHELLCMD\_ENTRY的第一个参数。 - - - 2. 动态注册命令方式: - - 注册函数原型: - - ``` - UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) - ``` - - **表 2** UINT32 osCmdReg参数详解 - - - - - - - - - - - - - - - - - - - -

参数

-

描述

-

cmdType

-

命令类型:

-
  • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

    -
  • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

    -
-

cmdKey

-

命令关键字,函数在Shell中访问的名称。

-

paraNum

-

调用的执行函数的入参最大个数,暂不支持该参数;当前为默认值XARGS(0xFFFFFFFF)。

-

cmdHook

-

命令执行函数地址,即命令实际执行函数。

-
- - 如: - - ``` - osCmdReg(CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) - ``` - - - >![](public_sys-resources/icon-note.gif) **说明:** - >命令关键字必须是唯一的,也即两个不同的命令项不能拥有相同的命令关键字,否则只会执行其中一个。 - >Shell在执行用户命令时,如果存在多个命令关键字相同的命令,只会执行其中在"help"命令中排序在最前面的一个。 - -3. 添加内置命令函数原型。 - - ``` - UINT32 osShellCmdLs(UINT32 argc, CHAR **argv) - ``` - - **表 3** osShellCmdLs参数说明 - - - - - - - - - - - - - -

参数

-

参数描述

-

argc

-

Shell命令中,参数个数。

-

argv

-

为指针数组,每个元素指向一个字符串,可以根据选择命令类型,决定是否要把命令关键字传入给注册函数。

-
- -4. 输入Shell命令,有两种输入方式: - - 在串口工具中直接输入Shell命令。 - - - 在telnet工具中输入Shell命令(telnet使用方式详见[telnet](telnet.md))。 - - - diff --git a/zh-cn/device-dev/kernel/VFS.md b/zh-cn/device-dev/kernel/VFS.md deleted file mode 100755 index 0a16319ccd1b2bc85ec7f546416d13a925806124..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/VFS.md +++ /dev/null @@ -1,171 +0,0 @@ -# VFS - -- [概述](#section132540468341) -- [基本概念](#section229417111227) -- [运作机制](#section18114182834215) -- [注意事项](#section18311145173712) -- [开发指导](#section422619258380) -- [编程实例](#section180311121420) -- [结果验证](#section16772334714) - -## 概述 - -## 基本概念 - -VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。 - -由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。VFS和各个具体文件系统的关系如下: - -**图 1** VFS和各个文件系统的关系 -![](figures/VFS和各个文件系统的关系.png "VFS和各个文件系统的关系") - -OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个inode结构体。设备注册和文件系统挂载后会根据路径在树中生成相应的结点。VFS最主要是两个功能: - -- 查找节点。 -- 统一调用(标准)。 - -## 运作机制 - -通过VFS层,可以使用标准的Unix文件操作函数(如open、read、write等)来实现对不同介质上不同文件系统的访问。 - -VFS框架内存中的inode树结点有三种类型: - -- 虚拟结点:作为VFS框架的虚拟文件,保持树的连续性,如/usr、/usr/bin。 -- 设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0。 -- 挂载点:挂载具体文件系统,如/vs/sd、/mnt。 - -**图 2** 文件系统树形结构 -![](figures/文件系统树形结构.png "文件系统树形结构") - -## 注意事项 - -- VFS下的所有文件系统,创建的目录名和文件名最多只可以有255个字节,能支持的全路径长度最长为259字节,超过这个路径长度的文件和目录无法创建。 - -- 目前仅有jffs2文件系统支持完整的权限控制。 - -- inode\_find\(\)函数调用后会使查找到的inode节点连接数+1,调用完成后需要调用inode\_release\(\)使连接数-1,所以一般inode\_find\(\)要和inode\_release\(\)配套使用。 - -- 设备分为字符设备和块设备,为了块设备上的文件系统系统数据安全,需挂载相应文件系统后通过文件系统接口操作数据。 - -- los\_vfs\_init\(\)只能调用一次,多次调用将会造成文件系统异常。 - -- 目前OpenHarmony内核所有的文件系统中的文件名和目录名中只可以出现“-” 与“\_”两种特殊字符,使用其他特殊字符可能造成的后果不可预知,请谨慎为之。 - -- OpenHarmony内核支持open\(\)+O\_DIRECTORY的方法获取目录数据信息。 - -- 挂载点必须为空目录,不能重复挂载至同一挂载点或挂载至其他挂载点下的目录或文件,错误挂载可能损坏设备及系统。 - -- open打开一个文件时,参数O\_RDWR、O\_WRONLY、O\_RDONLY互斥,只能出现一个,若出现2个或以上作为open的参数,文件读写操作会被拒绝,并返回EACCESS错误码,禁止使用。 - -- OpenHarmony内核文件系统在umount操作之前,需确保所有目录及文件全部关闭,否则umount会失败。如果强制umount,可能导致包括但不限于文件系统损坏、设备损坏等问题。 - -- SD卡移除前,需确保所有目录及文件全部关闭,并进行umount操作。如果强制拔卡,可能导致包括但不限于SD数据丢失、SD卡损坏等问题。 - - -## 开发指导 - -**开发流程** - -推荐驱动开发人员使用VFS框架来注册/卸载设备,即调用register\_driver\(\)、register\_blockdriver\(\)接口生成设备结点,应用层使用open\(\)、read\(\)操作设备(字符设备)文件来调用驱动。 - -**文件描述符** - -本系统中,进程的文件描述符最多有256个(File和Socket描述符合并统计),系统文件描述符共640个,系统文件描述符规格: - -- File描述符,普通文件描述符,系统总规格为512。 - -- Socket描述符,系统总规格为128。 - - -**VFS支持的操作** - -open, close, read, write, seek, ioctl, fcntl, mmap, sync, dup, dup2, truncate, opendir, closedir, readdir, rewinddir, mount, umount, statfs, unlink, remove, mkdir, rmdir, rename, stat, utime, seek64, fallocate, fallocate64, truncate64, chmod, chown。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 当前只提供修改jffs2文件以及vfs设备节点属性的接口,各个系统对只读等属性有各自的处理方式。 ->- 在OpenHarmony内核中属性并不冲突(可以任意修改)。 ->- 在OpenHarmony内核中只读属性文件/目录不允许被删除。 ->- 在OpenHarmony内核中只读属性文件/目录允许rename。 ->- 只读文件不允许以O\_CREAT、O\_TRUNC,以及有含有写的权限的方式打开。 ->- 在OpenHarmony内核中设置的系统文件加上隐藏属性,在Windows中只能通过命令行找到(在显示,不显示隐藏文件的属性情况下都不能看到)。 - -## 编程实例 - -``` -/* 说明:展示创建目录,和遍历目录的操作 */ -#include -#include -#include -#include -#include -#include - -int main() -{ - int ret; - char *dirname = "/test"; - char *pathname0 = "/test/test0"; - char *pathname1 = "/test/test1"; - char *pathname2 = "/test/test2"; - struct dirent **namelist; - int num; - - ret = mkdir(dirname, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", dirname, errno); - goto EXIT; - } - - ret = mkdir(pathname0, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", pathname0, errno); - goto EXIT0; - } - - ret = mkdir(pathname1, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", pathname1, errno); - goto EXIT1; - } - - ret = mkdir(pathname2, 0777); - if ((ret < 0) && (errno != EEXIST)) { - printf("mkdir failed. path=%s, errno=%d\n", pathname2, errno); - goto EXIT2; - } - - num = scandir(dirname, &namelist, NULL, alphasort); - if (num < 0) { - perror("scandir"); - } else { - while (num--) { - printf("%s\n", namelist[num]->d_name); - free(namelist[num]); - } - free(namelist); - } - - printf("fs_demo exit.\n"); - return 0; - -EXIT2: - remove(pathname2); -EXIT1: - remove(pathname1); -EXIT0: - remove(pathname0); -EXIT: - remove(dirname); - return 0; -} -``` - -## 结果验证 - -``` -OHOS # test2 -test1 -test0 -fs_demo exit. -``` - diff --git a/zh-cn/device-dev/kernel/arp.md b/zh-cn/device-dev/kernel/arp.md deleted file mode 100755 index 2cf3628efa4968b0e5ba3d9ee4cd520a97392441..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/arp.md +++ /dev/null @@ -1,114 +0,0 @@ -# arp - -- [命令功能](#section201149459368) -- [命令格式](#section579813484364) -- [参数说明](#section168065311366) -- [使用指南](#section19190125723612) -- [使用实例](#section10383416372) - -## 命令功能 - -在以太网中,主机之间的通信是直接使用MAC地址(非IP地址)来通信的,所以,对于使用IP通信的协议,必须能够将IP地址转换成MAC地址,才能在局域网(以太网)内通信。解决这个问题的方法就是主机存储一张IP和MAC地址对应的表,即ARP缓存,主机要往一个局域网内的目的IP地址发送IP包时,就可以从ARP缓存表中查询到目的MAC地址。ARP缓存是由TCP/IP协议栈维护的,用户可通过ARP命令查看和修改ARP表。 - -## 命令格式 - -arp - -arp \[_-i IF_\] -s _IPADDR HWADDR_ - -arp \[_-i IF_\] -d _IPADDR_ - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-

打印整个ARP缓存的内容。

-

N/A

-

-i IF

-

指定的网络接口(可选参数)。

-

N/A

-

-s IPADDR

-

HWADDR

-

增加一条ARP表项,后面的参数是局域网中另一台主机的IP地址及其对应的MAC地址。

-

N/A

-

-d IPADDR

-

删除一条ARP表项。

-

N/A

-
- -## 使用指南 - -- arp命令用来查询和修改TCP/IP协议栈的ARP缓存表,增加非同一子网内的IP地址的ARP表项是没有意义的,协议栈会返回失败。 -- 命令需要启动TCP/IP协议栈后才能使用。 - -## 使用实例 - -举例: - -1. 输入arp - - **图 1** 打印整个 ARP 缓存表 - - - ![](figures/Snipaste_2021-01-26_10-38-58.png) - - **表 2** 参数说明 - - - - - - - - - - - - - - - - - - - -

参数

-

说明

-

Address

-

表示网络设备的IPv4地址。

-

HWaddress

-

表示网络设备的MAC地址。

-

Iface

-

表示该ARP表项使用的接口名。

-

Type

-

表示该ARP表项是动态的还是静态的,动态是指ARP表项由协议栈自动创建,静态是指ARP表项是由用户增加的。

-
- - diff --git a/zh-cn/device-dev/kernel/cat.md b/zh-cn/device-dev/kernel/cat.md deleted file mode 100755 index ef609b4dc074a005ff49eb4718b5b8bc069867d8..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/cat.md +++ /dev/null @@ -1,53 +0,0 @@ -# cat - -- [命令功能](#section16710153391315) -- [命令格式](#section1699392313158) -- [参数说明](#section1677217374136) -- [使用指南](#section186772414131) -- [使用实例](#section12158131814561) -- [输出说明](#section183926225561) - -## 命令功能 - -cat用于显示文本文件的内容。 - -## 命令格式 - -cat \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

pathname

-

文件路径。

-

已存在的文件。

-
- -## 使用指南 - -cat用于显示文本文件的内容。 - -## 使用实例 - -举例:cat hello-harmony.txt - -## 输出说明 - -**图 1** 查看 hello-harmony.txt 文件的信息 -![](figures/查看-hello-harmony-txt-文件的信息.png "查看-hello-harmony-txt-文件的信息") - diff --git a/zh-cn/device-dev/kernel/cd.md b/zh-cn/device-dev/kernel/cd.md deleted file mode 100755 index 8acd5da837df72b9755ac1e90032c26ece690a6b..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/cd.md +++ /dev/null @@ -1,57 +0,0 @@ -# cd - -- [命令功能](#section11690184921316) -- [命令格式](#section75695409569) -- [参数说明](#section71961353181311) -- [使用指南](#section3629759111317) -- [使用实例](#section211620301412) -- [输出说明](#section1968117214577) - -## 命令功能 - -cd命令用来改变当前目录。 - -## 命令格式 - -cd \[_path_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

path

-

文件路径。

-

用户必须具有指定目录中的执行(搜索)许可权。

-
- -## 使用指南 - -- 未指定目录参数时,会跳转至根目录。 -- cd后加路径名时,跳转至该路径。 -- 路径名以 /(斜杠)开头时,表示根目录。 -- .(点)表示当前目录。 -- ..(点点)表示父目录。 - -## 使用实例 - -举例:cd .. - -## 输出说明 - -**图 1** 显示结果如下 -![](figures/显示结果如下.png "显示结果如下") - diff --git a/zh-cn/device-dev/kernel/chgrp.md b/zh-cn/device-dev/kernel/chgrp.md deleted file mode 100755 index dc292bf35fdd9f18d169039d5f8c7cc10fffe446..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/chgrp.md +++ /dev/null @@ -1,60 +0,0 @@ -# chgrp - -- [命令功能](#section6103119161418) -- [命令格式](#section186958132141) -- [参数说明](#section81796174141) -- [使用指南](#section14330152417140) -- [使用实例](#section951823119149) -- [输出说明](#section14271133125715) - -## 命令功能 - -chgrp用于修改文件的群组。 - -## 命令格式 - -chgrp \[_group_\] \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

group

-

文件群组。

-

[0,0xFFFFFFFF]

-

pathname

-

文件路径。

-

已存在的文件。

-
- -## 使用指南 - -在需要修改的文件名前加上文件群组值就可以修改该文件的所属组。 - -## 使用实例 - -举例:chgrp 100 hello-harmony.txt - -## 输出说明 - -**图 1** 修改 hello-harmony.txt 文件的群组为100 -![](figures/修改-hello-harmony-txt-文件的群组为100.png "修改-hello-harmony-txt-文件的群组为100") - diff --git a/zh-cn/device-dev/kernel/chmod.md b/zh-cn/device-dev/kernel/chmod.md deleted file mode 100755 index a77659fcddfc8998b2f1d62b32b06cbbba2be19f..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/chmod.md +++ /dev/null @@ -1,60 +0,0 @@ -# chmod - -- [命令功能](#section13992936121418) -- [命令格式](#section63342439147) -- [参数说明](#section894414671411) -- [使用指南](#section182415221419) -- [使用实例](#section8518195718147) -- [输出说明](#section127391818158) - -## 命令功能 - -chmod用于修改文件操作权限。 - -## 命令格式 - -chmod \[_mode_\] \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

mode

-

文件或文件夹权限,用8进制表示对应User、Group、及Other(拥有者、群组、其他组)的权限。

-

[0,777]

-

pathname

-

文件路径。

-

已存在的文件。

-
- -## 使用指南 - -在需要修改的文件名前加上文件权限值就可以修改该文件的权限值。 - -## 使用实例 - -举例:chmod 666 hello-harmony.txt - -## 输出说明 - -**图 1** 修改 hello-harmony.txt 文件的权限为666 -![](figures/修改-hello-harmony-txt-文件的权限为666.png "修改-hello-harmony-txt-文件的权限为666") - diff --git a/zh-cn/device-dev/kernel/chown.md b/zh-cn/device-dev/kernel/chown.md deleted file mode 100755 index 467da9d89cedc0b704a913bd20cd84fa1f95654d..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/chown.md +++ /dev/null @@ -1,70 +0,0 @@ -# chown - -- [命令功能](#section247414691513) -- [命令格式](#section14773151018159) -- [参数说明](#section598731391517) -- [使用指南](#section16524152071510) -- [使用实例](#section17901152561510) -- [输出说明](#section15513163115816) - -## 命令功能 - -chmod用于将指定文件的拥有者改为指定的用户或组。 - -## 命令格式 - -chown \[_owner_\] \[_group_\] \[_pathname_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

owner

-

文件拥有者。

-

[0,0xFFFFFFFF]

-

group

-

文件群组。

-

1、为空。

-

2、[0,0xFFFFFFFF]

-

pathname

-

文件路径。

-

已存在的文件。

-
- -## 使用指南 - -- 在需要修改的文件名前加上文件拥有者和文件群组就可以分别修改该文件的拥有者和群组。 -- 当owner或group值为-1时则表示对应的owner或group不修改。 -- group参数可以为空。 - -## 使用实例 - -举例:chown 100 200 hello-harmony.txt - -## 输出说明 - -**图 1** 修改 hello-harmony.txt 文件的uid为100,gid为200 -![](figures/修改-hello-harmony-txt-文件的uid为100-gid为200.png "修改-hello-harmony-txt-文件的uid为100-gid为200") - diff --git a/zh-cn/device-dev/kernel/cp.md b/zh-cn/device-dev/kernel/cp.md deleted file mode 100755 index eab217ee504586612e96af7bd6f3ac9869a6f435..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/cp.md +++ /dev/null @@ -1,68 +0,0 @@ -# cp - -- [命令功能](#section6841203041513) -- [命令格式](#section24286359150) -- [参数说明](#section558617385152) -- [使用指南](#section16128156162) -- [使用实例](#section19354171211618) -- [输出说明](#section16754183195914) - -## 命令功能 - -拷贝文件,创建一份副本。 - -## 命令格式 - -cp \[_SOURCEFILE_\] \[_DESTFILE_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

SOURCEFILE

-

源文件路径。

-

目前只支持文件,不支持目录。

-

DESTFILE

-

目的文件路径。

-

支持目录以及文件。

-
- -## 使用指南 - -- 同一路径下,源文件与目的文件不能重名。 -- 源文件必须存在,且不为目录。 -- 源文件路径支持“\*”和“?”通配符,“\*”代表任意多个字符,“?”代表任意单个字符。目的路径不支持通配符。当源路径可匹配多个文件时,目的路径必须为目录。 -- 目的路径为目录时,该目录必须存在。此时目的文件以源文件命名。 -- 目的路径为文件时,所在目录必须存在。此时拷贝文件的同时为副本重命名。 -- 目前不支持多文件拷贝。参数大于2个时,只对前2个参数进行操作。 -- 目的文件不存在时创建新文件,已存在则覆盖。 - -拷贝系统重要资源时,会对系统造成死机等重大未知影响,如用于拷贝/dev/uartdev-0 文件时,会产生系统卡死现象。 - -## 使用实例 - -举例:cp hello-harmony.txt ./tmp/ - -## 输出说明 - -**图 1** 显示结果如下 -![](figures/显示结果如下-0.png "显示结果如下-0") - diff --git a/zh-cn/device-dev/kernel/cpup.md b/zh-cn/device-dev/kernel/cpup.md deleted file mode 100755 index c2bf2bba4636e7a8c5ec0d36b281fc49c1ad5d15..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/cpup.md +++ /dev/null @@ -1,65 +0,0 @@ -# cpup - -- [命令功能](#section1842161614217) -- [命令格式](#section5629527427) -- [参数说明](#section133651361023) -- [使用指南](#section156611948521) -- [使用实例](#section68501605319) -- [输出说明](#section19871522144219) - -## 命令功能 - -cpup命令用于查询系统CPU的占用率。 - -## 命令格式 - -cpup \[_mode_\] \[_taskID_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

mode

-

● 缺省:显示系统最近10s内的CPU占用率。

-

● 0:显示系统最近10s内的CPU占用率。

-

● 1:显示系统最近1s内的CPU占用率。

-

● 其他数字:显示系统启动至今总的CPU 占用率。

-

[0,0xFFFFFFFF]

-

taskID

-

任务ID号

-

[0,0xFFFFFFFF]

-
- -## 使用指南 - -- 参数缺省时,显示系统10s前的CPU占用率。 -- 只有一个参数时,该参数为mode,显示系统相应时间前的CPU占用率。 -- 输入两个参数时,第一个参数为mode,第二个参数为taskID,显示对应ID号任务的相应时间前的CPU占用率。 - -## 使用实例 - -举例:输入cpup 1 5 - -## 输出说明 - -**图 1** 指令输出结果 -![](figures/指令输出结果.png "指令输出结果") - diff --git a/zh-cn/device-dev/kernel/date.md b/zh-cn/device-dev/kernel/date.md deleted file mode 100755 index d359856e2043798eae4396e86919a098171ddce4..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/date.md +++ /dev/null @@ -1,94 +0,0 @@ -# date - -- [命令功能](#section56472016338) -- [命令格式](#section16635112512316) -- [参数说明](#section15896030039) -- [使用指南](#section116361036636) -- [使用实例](#section021711411237) -- [输出说明](#section17950184414312) - -## 命令功能 - -date命令用于查询及设置系统日期和时间。 - -## 命令格式 - -date - -date --help - -date +\[_Format_\] - -date -s_ _\[_YY/MM/DD_\] - -date_ _-s_ _\[_hh:mm:ss_\]__ - -date -r \[_Filename_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

--help

-

使用帮助。

-

N/A

-

+Format

-

根据Format格式打印日期和时间。

-

--help中列出的占位符。

-

-s YY/MM/DD

-

设置系统时间,用“/”分割的年月日。

-

>= 1970/01/01

-

-s hh:mm:ss

-

设置系统时间,用“:”分割的时分秒。

-

N/A

-

-r Filename

-

查询Filename文件的修改时间。

-

N/A

-
- -## 使用指南 - -- date参数缺省时,默认显示当前系统日期和时间。 -- --help、+Format、-s、-r不能混合使用。 - -## 使用实例 - -举例: - -输入date +%Y--%m--%d。 - -## 输出说明 - -**图 1** 按指定格式打印系统日期 -![](figures/按指定格式打印系统日期.png "按指定格式打印系统日期") - diff --git a/zh-cn/device-dev/kernel/dhclient.md b/zh-cn/device-dev/kernel/dhclient.md deleted file mode 100755 index 360efdc8085aa1f4c0585e1bc926eaa0fceba7aa..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/dhclient.md +++ /dev/null @@ -1,138 +0,0 @@ -# dhclient - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -设置和查看dhclient的参数。 - -## 命令格式 - -dhclient <_netif name_\> - -dhclient -x <_netif name_\> - -dhclient -gb <_netif name_\> - -dhclient -sv <_vendor_\> - -dhclient -gv - -dhclient -gd <_index_\> - -dhclient -sd <_dns\_ip_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

<netif name>

-

启动对应网卡的dhcp请求。

-

网卡名字,eth0。

-

-x <netif name>

-

关闭对应网卡的dhcp功能。

-

网卡名字,eth0。

-

-gb <netif name>

-

查看对应网卡的dhcp请求是否完成。

-

网卡名字,eth0。

-

-sv <vendor>

-

设置dhcp请求的厂商信息。

-

厂商信息,长度是32个字符。

-

-gv

-

查看dhcp请求的厂商信息。

-

N/A

-

-gd <index>

-

获取第index个dns server的信息。

-

index,0或者1。

-

-sd <dns_ip>

-

设置主dns server的ip。

-

dns的ip地址。

-
- -## 使用指南 - -dhclient eth0 - -dhclient -x eth0 - -dhclient -gb eth0 - -dhclient -sv MFSI - -dhclient -gv - -dhclient -gd 0 - -dhclient -sd 8.8.8.8 - -## 使用实例 - -![](figures/zh-cn_image_0000001053224218.png) - -## 输出说明 - -**表 2** 输出说明 - - - - - - - - - - - - - -

输出

-

说明

-

dhclient: set vendor info [MFSI] success

-

设置厂商信息MFSI信息成功。

-

dns[0]: 192.168.1.100

-

dns server ip地址为192.168.1.100。

-
- diff --git a/zh-cn/device-dev/kernel/dmesg.md b/zh-cn/device-dev/kernel/dmesg.md deleted file mode 100755 index 197e38fdfffb35ce283113c49a392b50799f9d67..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/dmesg.md +++ /dev/null @@ -1,113 +0,0 @@ -# dmesg - -- [命令功能](#section4643204919313) -- [命令格式](#section6553153635) -- [参数说明](#section208971157532) -- [使用指南](#section213115219413) -- [使用实例](#section13736564418) -- [输出说明](#section194005101413) - -## 命令功能 - -dmesg命令用于控制内核dmesg缓存区。 - -## 命令格式 - -dmesg - -dmesg \[_-c/-C/-D/-E/-L/-U_\] - -dmesg -s \[_size_\] - -dmesg -l \[_level_\] - -dmesg \> \[_fileA_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-c

-

打印缓存区内容并清空缓存区。

-

N/A

-

-C

-

清空缓存区。

-

N/A

-

-D/-E

-

关闭/开启控制台打印。

-

N/A

-

-L/-U

-

关闭/开启串口打印。

-

N/A

-

-s size

-

设置缓存区大小 size是要设置的大小。

-

N/A

-

-l level

-

设置缓存等级。

-

0 - 5

-

> fileA

-

将缓存区内容写入文件。

-

N/A

-
- -## 使用指南 - -- 该命令依赖于LOSCFG\_SHELL\_DMESG,使用时通过menuconfig在配置项中开启"Enable Shell dmesg": - - Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell dmesg - -- dmesg参数缺省时,默认打印缓存区内容。 -- 各“ - ”选项不能混合使用。 - 1. 写入文件需确保已挂载文件系统。 - 2. 关闭串口打印会影响shell使用,建议先连接telnet再尝试关闭串口。 - - -## 使用实例 - -举例: - -输入dmesg \> /usr/dmesg.log。 - -## 输出说明 - -**图 1** dmesg重定向到文件。 -![](figures/dmesg重定向到文件.png "dmesg重定向到文件") - diff --git a/zh-cn/device-dev/kernel/exec.md b/zh-cn/device-dev/kernel/exec.md deleted file mode 100755 index a3b0933672ad5f5347812edf8ed4844bcd2e0621..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/exec.md +++ /dev/null @@ -1,60 +0,0 @@ -# exec - -- [命令功能](#section4643204919313) -- [命令格式](#section6553153635) -- [参数说明](#section208971157532) -- [使用指南](#section213115219413) -- [使用实例](#section13736564418) -- [输出说明](#section194005101413) - -## 命令功能 - -exec命令属于shell内置命令,目前实现最基础的执行用户态程序的功能。 - -## 命令格式 - -exec <_executable-file_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

executable-file

-

有效的可执行文件。

-

N/A

-
- -## 使用指南 - -该命令当前仅支持执行有效的二进制程序,程序成功执行,默认后台运行,但与Shell共用终端,可能会导致程序打印输出与Shell输出交错显示。 - -## 使用实例 - -举例: - -输入exec helloworld。 - -## 输出说明 - -``` -OHOS # exec helloworld -OHOS # hello world! -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->可执行文件执行后,先打印“OHOS \#”提示符原因:目前Shell “exec”命令执行均为后台执行,结果可能导致提示符提前打印。 - diff --git "a/zh-cn/device-dev/kernel/figure/Cow\346\234\272\345\210\266\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/Cow\346\234\272\345\210\266\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..bee6020f58b7127c24d0adc1da77fe1761b386de Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/Cow\346\234\272\345\210\266\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/PID\344\270\2723\347\232\204\350\277\233\347\250\213\350\231\232\346\213\237\345\206\205\345\255\230\344\275\277\347\224\250\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" "b/zh-cn/device-dev/kernel/figure/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" rename to "zh-cn/device-dev/kernel/figure/POSIX\346\216\245\345\217\243\346\241\206\346\236\266.png" diff --git a/zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-1.png b/zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-18.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-1.png rename to zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-18.png diff --git a/zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-2.png b/zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-19.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58-2.png rename to zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58-19.png diff --git a/zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58.png b/zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/Snipaste_2021-01-26_10-38-58.png rename to zh-cn/device-dev/kernel/figure/Snipaste_2021-01-26_10-38-58.png diff --git "a/zh-cn/device-dev/kernel/figures/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" "b/zh-cn/device-dev/kernel/figure/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" rename to "zh-cn/device-dev/kernel/figure/VFS\345\222\214\345\220\204\344\270\252\346\226\207\344\273\266\347\263\273\347\273\237\347\232\204\345\205\263\347\263\273.png" diff --git "a/zh-cn/device-dev/kernel/figures/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" "b/zh-cn/device-dev/kernel/figure/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" rename to "zh-cn/device-dev/kernel/figure/dmesg\351\207\215\345\256\232\345\220\221\345\210\260\346\226\207\344\273\266.png" diff --git "a/zh-cn/device-dev/kernel/figures/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" "b/zh-cn/device-dev/kernel/figure/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" rename to "zh-cn/device-dev/kernel/figure/lsfd\350\276\223\345\207\272\350\257\264\346\230\216.png" diff --git "a/zh-cn/device-dev/kernel/figures/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" "b/zh-cn/device-dev/kernel/figure/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" rename to "zh-cn/device-dev/kernel/figure/statfs\350\276\223\345\207\272\350\257\264\346\230\216.png" diff --git "a/zh-cn/device-dev/kernel/figures/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" "b/zh-cn/device-dev/kernel/figure/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" rename to "zh-cn/device-dev/kernel/figure/umount\350\276\223\345\207\272\347\244\272\344\276\213.png" diff --git "a/zh-cn/device-dev/kernel/figures/watch-task-\347\273\223\346\236\234.png" "b/zh-cn/device-dev/kernel/figure/watch-task-\347\273\223\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/watch-task-\347\273\223\346\236\234.png" rename to "zh-cn/device-dev/kernel/figure/watch-task-\347\273\223\346\236\234.png" diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001051690323.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001051690323.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001051690323.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001051690323.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370303.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370303.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370303.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370303.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370305.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370305.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370305.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370305.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370307.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370307.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052370307.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052370307.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052530298.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052530298.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052530298.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052530298.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810300.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810300.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810300.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810300.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810304.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810304.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001052810304.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001052810304.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053224218.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053224218.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053224218.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053224218.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053710680.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053710680.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053710680.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053710680.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053826366.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053826366.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001053826366.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001053826366.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001054624363.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001054624363.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001054624363.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001054624363.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001121429646.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001121429646.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001121429646.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001121429646.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124146302.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124146302.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124146302.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124146302.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124147160.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124147160.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124147160.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124147160.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124306828.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124306828.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124306828.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124306828.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124307264.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124307264.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124307264.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124307264.png diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124310992.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124310992.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001124310992.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001124310992.png diff --git a/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132085260.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132085260.png new file mode 100644 index 0000000000000000000000000000000000000000..4bc250489d5cfba6848f63abd9a1ea12502fd9df Binary files /dev/null and b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132085260.png differ diff --git a/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132778524.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132778524.png new file mode 100644 index 0000000000000000000000000000000000000000..7836a009e5e3cb6351c807daf9b927c7d3b71a86 Binary files /dev/null and b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132778524.png differ diff --git a/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132935054.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132935054.png new file mode 100644 index 0000000000000000000000000000000000000000..238a15fa82b6095a13ee54bd3014ed3c08c21b4e Binary files /dev/null and b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001132935054.png differ diff --git a/zh-cn/device-dev/kernel/figures/zh-cn_image_0000001170790681.png b/zh-cn/device-dev/kernel/figure/zh-cn_image_0000001170790681.png similarity index 100% rename from zh-cn/device-dev/kernel/figures/zh-cn_image_0000001170790681.png rename to zh-cn/device-dev/kernel/figure/zh-cn_image_0000001170790681.png diff --git "a/zh-cn/device-dev/kernel/figures/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\344\272\213\344\273\266\350\277\220\344\275\234\345\216\237\347\220\206\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figure/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..37559a2a230b4d0a17fa07aaac2ea5ed3923b4df Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" rename to "zh-cn/device-dev/kernel/figure/\344\273\245\344\270\211\347\247\215\346\226\271\345\274\217\346\230\276\347\244\272\345\206\205\345\255\230\344\275\277\347\224\250\346\203\205\345\206\265.png" diff --git "a/zh-cn/device-dev/kernel/figure/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..75c79e501c27a2c41ff011133197eb646981b0f3 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\345\244\261\350\264\245.png" diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\345\217\221\351\200\201\347\273\223\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..02437a72c3de38cbddf5233282ef9354220002bf Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" "b/zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204uid\344\270\272100-gid\344\270\272200.png" diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" "b/zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\346\235\203\351\231\220\344\270\272666.png" diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" "b/zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" rename to "zh-cn/device-dev/kernel/figure/\344\277\256\346\224\271-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\347\276\244\347\273\204\344\270\272100.png" diff --git "a/zh-cn/device-dev/kernel/figure/\345\205\203\346\225\260\346\215\256\345\255\230\345\202\250\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\205\203\346\225\260\346\215\256\345\255\230\345\202\250\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..8566e16dbc675362366f07cf9497c2d9073d6f56 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\205\203\346\225\260\346\215\256\345\255\230\345\202\250\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" new file mode 100644 index 0000000000000000000000000000000000000000..6c211cb88534ae6a28e6dbdaed8bd1b2717d7366 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\345\206\205\346\240\270\346\236\266\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" "b/zh-cn/device-dev/kernel/figure/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" rename to "zh-cn/device-dev/kernel/figure/\345\207\272\347\216\260\345\206\205\345\255\230\350\266\212\347\225\214.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" "b/zh-cn/device-dev/kernel/figure/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\207\346\215\242\345\210\260\344\270\272uid\344\270\2721000-gid\344\270\2721000\347\232\204\347\224\250\346\210\267.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" "b/zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272-share-\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" "b/zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\233\345\273\272\344\270\200\344\270\252\345\220\215\344\270\272-file-c-\347\232\204\346\226\207\344\273\266.png" diff --git "a/zh-cn/device-dev/kernel/figures/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" "b/zh-cn/device-dev/kernel/figure/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" rename to "zh-cn/device-dev/kernel/figure/\345\210\240\351\231\244\344\270\200\344\270\252\345\220\215\344\270\272-dir-\347\232\204\347\233\256\345\275\225.png" diff --git "a/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" "b/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" new file mode 100644 index 0000000000000000000000000000000000000000..955aff65c1c8365cc6c932a5e89ef944384bb489 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" differ diff --git "a/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..e67cd13c295d19b6ce45c4749644eea42ada7f05 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" "b/zh-cn/device-dev/kernel/figure/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" rename to "zh-cn/device-dev/kernel/figure/\345\217\221\351\200\201\344\277\241\345\217\267\347\273\231\346\214\207\345\256\232\350\277\233\347\250\213.png" diff --git "a/zh-cn/device-dev/kernel/figure/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..6ac9200e867f2c87d14ef89ca8c15102e83d4c10 Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" "b/zh-cn/device-dev/kernel/figure/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" rename to "zh-cn/device-dev/kernel/figure/\345\275\223\345\211\215\346\262\241\346\234\211\345\206\205\345\255\230\350\266\212\347\225\214.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" "b/zh-cn/device-dev/kernel/figure/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" rename to "zh-cn/device-dev/kernel/figure/\346\214\207\344\273\244\350\276\223\345\207\272\347\273\223\346\236\234.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" "b/zh-cn/device-dev/kernel/figure/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" rename to "zh-cn/device-dev/kernel/figure/\346\214\211\346\214\207\345\256\232\346\240\274\345\274\217\346\211\223\345\215\260\347\263\273\347\273\237\346\227\245\346\234\237.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" "b/zh-cn/device-dev/kernel/figure/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" rename to "zh-cn/device-dev/kernel/figure/\346\226\207\344\273\266\347\263\273\347\273\237\346\240\221\345\275\242\347\273\223\346\236\204.png" diff --git "a/zh-cn/device-dev/kernel/figure/\346\227\245\345\277\227\346\226\271\345\274\217\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\346\227\245\345\277\227\346\226\271\345\274\217\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..caf4127a296227a121ef155f9354d1f3ef3837dd Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\346\227\245\345\277\227\346\226\271\345\274\217\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-0.png" "b/zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-17.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-0.png" rename to "zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213-17.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" "b/zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" rename to "zh-cn/device-dev/kernel/figure/\346\230\276\347\244\272\347\273\223\346\236\234\345\246\202\344\270\213.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213-hello-harmony-txt-\346\226\207\344\273\266\347\232\204\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\347\263\273\347\273\237\350\267\257\345\276\204\344\270\213\347\232\204\347\233\256\345\275\225-\346\230\276\347\244\272\347\232\204\345\206\205\345\256\271\345\246\202\344\270\213.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\345\275\223\345\211\215\350\267\257\345\276\204.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\211\251\347\220\206\351\241\265\344\275\277\347\224\250\346\203\205\345\206\265.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\347\263\273\347\273\237\350\265\204\346\272\220\344\275\277\347\224\250\346\203\205\345\206\265.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\347\234\213\350\277\233\347\250\213PID.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\344\273\273\345\212\241\351\203\250\345\210\206\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\345\257\271\345\272\224-ID-\347\232\204\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\345\234\250\347\224\250\347\232\204\344\277\241\345\217\267\351\207\217\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" "b/zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" rename to "zh-cn/device-dev/kernel/figure/\346\237\245\350\257\242\346\211\200\346\234\211\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250\347\233\270\345\205\263\344\277\241\346\201\257.png" diff --git "a/zh-cn/device-dev/kernel/figures/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" "b/zh-cn/device-dev/kernel/figure/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" rename to "zh-cn/device-dev/kernel/figure/\347\224\250-rm--r-\345\210\240\351\231\244\347\233\256\345\275\225-sd.png" diff --git "a/zh-cn/device-dev/kernel/figures/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" "b/zh-cn/device-dev/kernel/figure/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" rename to "zh-cn/device-dev/kernel/figure/\347\224\250-rm-\345\221\275\344\273\244\345\210\240\351\231\244\346\226\207\344\273\266-log1-txt.png" diff --git "a/zh-cn/device-dev/kernel/figures/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\347\272\277\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figures/\350\276\223\345\205\245-telnet-on.png" "b/zh-cn/device-dev/kernel/figure/\350\276\223\345\205\245-telnet-on.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\350\276\223\345\205\245-telnet-on.png" rename to "zh-cn/device-dev/kernel/figure/\350\276\223\345\205\245-telnet-on.png" diff --git "a/zh-cn/device-dev/kernel/figures/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/figures/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/kernel/figure/\350\277\233\347\250\213\347\212\266\346\200\201\350\277\201\347\247\273\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/kernel/figure/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figure/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..f7ffdd153fcfffcc4fdf97a51b66c11c502c6a9c Binary files /dev/null and "b/zh-cn/device-dev/kernel/figure/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" differ diff --git "a/zh-cn/device-dev/kernel/figures/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index 7cc6c5fa458d60bdf1ad1d7494ab3982adc8d1f0..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\344\272\222\346\226\245\351\224\201\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index cf0684595b4e7b07dfebf6c55c867a97e1e71663..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\344\273\273\345\212\241\347\212\266\346\200\201\347\244\272\346\204\217\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index fc4591567b7f1643e1c065df5860af3e7aff2a3b..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\344\277\241\345\217\267\351\207\217\350\277\220\344\275\234\347\244\272\346\204\217\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" deleted file mode 100644 index cb86acd9c05059302f21ac10a3d8604b6e742652..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\345\206\205\346\240\270\345\220\257\345\212\250\346\265\201\347\250\213.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" "b/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" deleted file mode 100644 index c32b7cf60be9ed557f5c3139aed303b105a4e2d9..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\346\240\270\345\277\203\347\256\227\346\263\225.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" deleted file mode 100644 index 96a1c33d124ad5cd67afa331154840ad7b59c9ab..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\345\212\250\346\200\201\345\206\205\345\255\230\347\256\241\347\220\206\347\273\223\346\236\204\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index ce4103b3f82838d3593e7d04523b402b4283effa..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\345\240\206\346\240\210\345\210\206\346\236\220\345\216\237\347\220\206\347\244\272\346\204\217\345\233\276.png" and /dev/null differ diff --git "a/zh-cn/device-dev/kernel/figures/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/kernel/figures/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" deleted file mode 100644 index b21c09ee49ceda81474ce085aae1f67feea17f3a..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/kernel/figures/\351\235\231\346\200\201\345\206\205\345\255\230\347\244\272\346\204\217\345\233\276.png" and /dev/null differ diff --git a/zh-cn/device-dev/kernel/format.md b/zh-cn/device-dev/kernel/format.md deleted file mode 100755 index ecddf4e03134b2a3a3503bd30d1c7f3a26989ad7..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/format.md +++ /dev/null @@ -1,69 +0,0 @@ -# format - -- [命令功能](#section1922331919169) -- [命令格式](#section249226169) -- [参数说明](#section985173416177) -- [使用指南](#section1510162714162) -- [使用实例](#section25691431161611) -- [输出说明](#section17368112365920) - -## 命令功能 - -format指令用于格式化磁盘。 - -## 命令格式 - -format <_dev\_inodename_\> <_sectors_\> <_option_\> \[_label_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

dev_inodename

-

设备名。

-

sectors

-

分配的单元内存或扇区大小,如果输入0表示参数为空。(取值必须为0或2的幂,fat32下最大值为128,取值0表示自动选择合适的簇大小,不同size的分区,可用的簇大小范围不同,错误的簇大小指定可能导致格式化失败)。

-

option

-
格式化选项,用来选择文件系统的类型,有如下几种参数选择:
  • 0x01:FMT_FAT
  • 0x02:FMT_FAT32
  • 0x07:FMT_ANY
  • 0x08:FMT_ERASE (USB不支持该选项)
-
-

传入其他值皆为非法值,将由系统自动选择格式化方式。若格式化U盘时低格位为 1,会出现错误打印。

-

label

-

该参数为可选参数,输入值应为字符串,用来指定卷标名。当输入字符串"null"时,则把之前设置的卷标名清空。

-
- -## 使用指南 - -- format指令用于格式化磁盘,设备名可以在dev目录下查找。format时必须安装存储卡。 -- format只能格式化U盘、sd和mmc卡,对Nand flash和Nor flash格式化不起作用。 -- sectors参数必须传入合法值,传入非法参数可能引发异常。 - -## 使用实例 - -举例:输入format /dev/mmcblk0 128 2 - -## 输出说明 - -结果如下 - -![](figures/zh-cn_image_0000001052370307.png) - diff --git a/zh-cn/device-dev/kernel/free.md b/zh-cn/device-dev/kernel/free.md deleted file mode 100755 index 56734efb792eaa38e825d4cfd42edcd6baf12b0f..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/free.md +++ /dev/null @@ -1,119 +0,0 @@ -# free - -- [命令功能](#section175151514841) -- [命令格式](#section8488721749) -- [参数说明](#section27272181949) -- [使用指南](#section148661259410) -- [使用实例](#section68081530242) -- [输出说明](#section171235517543) - -## 命令功能 - -free命令可显示系统内存的使用情况,同时显示系统的text段、data段、rodata段、bss段大小。 - -## 命令格式 - -free \[_-k | -m_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

无参数

-

以Byte为单位显示。

-

N/A

-

-k

-

以KB为单位显示。

-

N/A

-

-m

-

以MB为单位显示。

-

N/A

-
- -## 使用指南 - -无。 - -## 使用实例 - -举例:分别输入free、free -k、free -m. - -## 输出说明 - -**图 1** 以三种方式显示内存使用情况 -![](figures/以三种方式显示内存使用情况.png "以三种方式显示内存使用情况") - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

total

-

表示系统动态内存池总量。

-

used

-

表示已使用内存总量。

-

free

-

表示未被分配的内存大小。

-

heap

-

表示已分配堆大小。

-

text

-

表示代码段大小。

-

data

-

表示数据段大小。

-

rodata

-

表示只读数据段大小。

-

bss

-

表示未初始化全局变量占用内存大小。

-
- diff --git a/zh-cn/device-dev/kernel/hwi.md b/zh-cn/device-dev/kernel/hwi.md deleted file mode 100755 index d2ab70ddb335746aaba995bc090b946b4217d45b..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/hwi.md +++ /dev/null @@ -1,94 +0,0 @@ -# hwi - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -hwi命令查询当前中断信息 - -## 命令格式 - -hwi - -## 参数说明 - -无。 - -## 使用指南 - -- 输入hwi即显示当前中断号、中断次数及注册中断名称。 -- 若开关LOSCFG\_CPUP\_INCLUDE\_IRQ打开,则还会显示各个中断的处理时间(cycles)、CPU占用率以及中断类型。 - -## 使用实例 - -举例:输入hwi - -## 输出说明 - -1. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ关闭) - - ![](figures/zh-cn_image_0000001053826366.png) - -2. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ打开) - - ![](figures/zh-cn_image_0000001052810304.png) - - **表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

InterruptNo

-

中断号。

-

Count

-

中断次数。

-

Name

-

注册中断名称。

-

CYCLECOST

-

中断的处理时间(cycles)。

-

CPUUSE

-

CPU占用率。

-

CPUUSE10s

-

最近10s CPU占用率。

-

CPUUSE1s

-

最近1s CPU占用率。

-

mode

-

中断类型:

-
  • normal: 非共享中断。
  • shared: 共享中断。
-
- - diff --git a/zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md b/zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md new file mode 100644 index 0000000000000000000000000000000000000000..1cded0a67f9982198d4b112d092b821657d51b1b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-basic-mini-time.md @@ -0,0 +1,7 @@ +# 时间管理 + +- **[基本概念](kernel-lite-mini-basic-time-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-time-guide.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\206\205\346\240\270\347\274\226\347\240\201\350\247\204\350\214\203.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-app-code.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\206\205\346\240\270\347\274\226\347\240\201\350\247\204\350\214\203.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-app-code.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md new file mode 100644 index 0000000000000000000000000000000000000000..d219cc86b000959550b333309dcacc0aca028c30 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data-list.md @@ -0,0 +1,191 @@ +# 双向链表 + +- [基本概念](#section1990715203418) +- [功能说明](#section848334511411) +- [开发流程](#section01781261552) +- [编程实例](#section67569495514) + - [实例描述](#section48761994551) + - [示例代码](#section1280202685519) + - [结果验证](#section5811249105512) + + +## 基本概念 + +双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,还增加一个指向前一个节点的指针。其头指针head是唯一确定的。 + +从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。 + +## 功能说明 + +双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

初始化链表

+

LOS_ListInit

+

将指定双向链表节点初始化为双向链表

+

LOS_DL_LIST_HEAD

+

定义一个双向链表节点并以该节点初始化为双向链表

+

增加节点

+

LOS_ListAdd

+

将指定节点插入到双向链表头端

+

LOS_ListTailInsert

+

将指定节点插入到双向链表尾端

+

删除节点

+

LOS_ListDelete

+

将指定节点从链表中删除

+

LOS_ListDelInit

+

将指定节点从链表中删除,并使用该节点初始化链表

+

判断双向链表是否为空

+

LOS_ListEmpty

+

判断链表是否为空

+

获取结构体信息

+

LOS_DL_LIST_ENTRY

+

获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称

+

LOS_OFF_SET_OF

+

获取指定结构体内的成员相对于结构体起始地址的偏移量

+

遍历双向链表

+

LOS_DL_LIST_FOR_EACH

+

遍历双向链表

+

LOS_DL_LIST_FOR_EACH_SAFE

+

遍历双向链表,并存储当前节点的后继节点用于安全校验

+

遍历包含双向链表的结构体

+

LOS_DL_LIST_FOR_EACH_ENTRY

+

遍历指定双向链表,获取包含该链表节点的结构体地址

+

LOS_DL_LIST_FOR_EACH_ENTRY_SAFE

+

遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址

+
+ +## 开发流程 + +双向链表的典型开发流程: + +1. 调用LOS\_ListInit/LOS\_DL\_LIST\_HEAD初始双向链表。 +2. 调用LOS\_ListAdd向链表插入节点。 +3. 调用LOS\_ListTailInsert向链表尾部插入节点。 +4. 调用LOS\_ListDelete删除指定节点。 +5. 调用LOS\_ListEmpty判断链表是否为空。 +6. 调用LOS\_ListDelInit删除指定节点并以此节点初始化链表。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 需要注意节点指针前后方向的操作。 +>- 链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。 +>- 如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。 + +## 编程实例 + +### 实例描述 + +本实例实现如下功能: + +1. 初始化双向链表。 +2. 增加节点。 +3. 删除节点。 +4. 测试操作是否成功。 + +### 示例代码 + +示例代码如下: + +``` +#include "stdio.h" +#include "los_list.h" + +static UINT32 ListSample(VOID) +{ + LOS_DL_LIST listHead = {NULL,NULL}; + LOS_DL_LIST listNode1 = {NULL,NULL}; + LOS_DL_LIST listNode2 = {NULL,NULL}; + + //首先初始化链表 + printf("Initial head\n"); + LOS_ListInit(&listHead); + + //添加节点1和节点2,并校验他们的相互关系 + LOS_ListAdd(&listHead, &listNode1); + if (listNode1.pstNext == &listHead && listNode1.pstPrev == &listHead) { + printf("Add listNode1 success\n"); + } + + LOS_ListTailInsert(&listHead, &listNode2); + if (listNode2.pstNext == &listHead && listNode2.pstPrev == &listNode1) { + printf("Tail insert listNode2 success\n"); + } + + //删除两个节点 + LOS_ListDelete(&listNode1); + LOS_ListDelete(&listNode2); + + //确认链表为空 + if (LOS_ListEmpty(&listHead)) { + printf("Delete success\n"); + } + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Initial head +Add listNode1 success +Tail insert listNode2 success +Delete success +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md new file mode 100644 index 0000000000000000000000000000000000000000..78fda11861f02826b54e3ba8f97ef0f9308d413f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-data.md @@ -0,0 +1,5 @@ +# 基本数据结构 + +- **[双向链表](kernel-lite-mini-app-data-list.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md new file mode 100644 index 0000000000000000000000000000000000000000..fb77b086298240bc85ad0755df727f0b3a844b3c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-cmsis.md @@ -0,0 +1,487 @@ +# CMSIS支持 + +- [基本概念](#section131091144111615) +- [开发指导](#section57653573161) + - [接口说明](#section1795910417173) + - [开发流程](#section48301225131720) + - [编程实例](#section524434761713) + + +## 基本概念 + +[CMSIS](https://developer.arm.com/tools-and-software/embedded/cmsis)是Cortex Microcontroller Software Interface Standard(Cortex微控制器软件接口标准)的缩写,是对于那些基于ARM Cortex处理器的微控制器独立于供应商的硬件抽象层。它包含多个组件层,其中之一是RTOS层,该层定义了一套通用及标准化的RTOS API接口,减少了应用开发者对特定RTOS的依赖,方便用户软件的移植重用。该套API有2个版本,分别为版本1(CMSIS-RTOS v1)和版本2(CMSIS-RTOS v2),OpenHarmony LiteOS-M仅提供其版本2的实现。 + +## 开发指导 + +### 接口说明 + +CMSIS-RTOS v2提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** CMSIS-RTOS v2接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

内核信息与控制

+

osKernelGetInfo

+

获取RTOS内核信息。

+

osKernelGetState

+

获取当前的RTOS内核状态。

+

osKernelGetSysTimerCount

+

获取RTOS内核系统计时器计数。

+

osKernelGetSysTimerFreq

+

获取RTOS内核系统计时器频率。

+

osKernelInitialize

+

初始化RTOS内核。

+

osKernelLock

+

锁定RTOS内核调度程序。

+

osKernelUnlock

+

解锁RTOS内核调度程序。

+

osKernelRestoreLock

+

恢复RTOS内核调度程序锁定状态。

+

osKernelResume

+

恢复RTOS内核调度程序。(暂未实现)

+

osKernelStart

+

启动RTOS内核调度程序。

+

osKernelSuspend

+

挂起RTOS内核调度程序。(暂未实现)

+

osKernelGetTickCount

+

获取RTOS内核滴答计数。

+

osKernelGetTickFreq

+

获取RTOS内核滴答频率。

+

线程管理

+

osThreadDetach

+

分离线程(线程终止时可以回收线程存储)。(暂未实现)

+

osThreadEnumerate

+

枚举活动线程。(暂未实现)

+

osThreadExit

+

终止当前正在运行的线程的执行。

+

osThreadGetCount

+

获取活动线程的数量。

+

osThreadGetId

+

返回当前正在运行的线程的线程ID。

+

osThreadGetName

+

获取线程的名称。

+

osThreadGetPriority

+

获取线程的当前优先级。

+

osThreadGetStackSize

+

获取线程的堆栈大小。

+

osThreadGetStackSpace

+

根据执行期间的堆栈水印记录获取线程的可用堆栈空间。

+

osThreadGetState

+

获取线程的当前线程状态。

+

osThreadJoin

+

等待指定线程终止。(暂未实现)

+

osThreadNew

+

创建一个线程并将其添加到活动线程中。

+

osThreadResume

+

恢复线程的执行。

+

osThreadSetPriority

+

更改线程的优先级。

+

osThreadSuspend

+

暂停执行线程。

+

osThreadTerminate

+

终止线程的执行。

+

osThreadYield

+

将控制权传递给处于就绪状态的下一个线程。

+

线程标志

+

osThreadFlagsSet

+

设置线程的指定线程标志。(暂未实现)

+

osThreadFlagsClear

+

清除当前正在运行的线程的指定线程标志。(暂未实现)

+

osThreadFlagsGet

+

获取当前正在运行的线程的当前线程标志。(暂未实现)

+

osThreadFlagsWait

+

等待当前正在运行的线程的一个或多个线程标志发出信号。(暂未实现)

+

事件标志

+

osEventFlagsGetName

+

获取事件标志对象的名称。(暂未实现)

+

osEventFlagsNew

+

创建并初始化事件标志对象。

+

osEventFlagsDelete

+

删除事件标志对象。

+

osEventFlagsSet

+

设置指定的事件标志。

+

osEventFlagsClear

+

清除指定的事件标志。

+

osEventFlagsGet

+

获取当前事件标志。

+

osEventFlagsWait

+

等待一个或多个事件标志被发出信号。

+

通用等待函数

+

osDelay

+

等待超时(时间延迟)。

+

osDelayUntil

+

等到指定时间。

+

计时器管理

+

osTimerDelete

+

删除计时器。

+

osTimerGetName

+

获取计时器的名称。(暂未实现)

+

osTimerIsRunning

+

检查计时器是否正在运行。

+

osTimerNew

+

创建和初始化计时器。

+

osTimerStart

+

启动或重新启动计时器。

+

osTimerStop

+

停止计时器。

+

互斥管理

+

osMutexAcquire

+

获取互斥或超时(如果已锁定)。

+

osMutexDelete

+

删除互斥对象。

+

osMutexGetName

+

获取互斥对象的名称。(暂未实现)

+

osMutexGetOwner

+

获取拥有互斥对象的线程。

+

osMutexNew

+

创建并初始化Mutex对象。

+

osMutexRelease

+

释放由osMutexAcquire获取的Mutex。

+

信号量

+

osSemaphoreAcquire

+

获取信号量令牌或超时(如果没有可用的令牌)。

+

osSemaphoreDelete

+

删除一个信号量对象。

+

osSemaphoreGetCount

+

获取当前信号量令牌计数。

+

osSemaphoreGetName

+

获取信号量对象的名称。(暂未实现)

+

osSemaphoreNew

+

创建并初始化一个信号量对象。

+

osSemaphoreRelease

+

释放信号量令牌,直到初始最大计数。

+

内存池

+

osMemoryPoolAlloc

+

从内存池分配一个内存块。

+

osMemoryPoolDelete

+

删除内存池对象。

+

osMemoryPoolFree

+

将分配的内存块返回到内存池。

+

osMemoryPoolGetBlockSize

+

获取内存池中的内存块大小。

+

osMemoryPoolGetCapacity

+

获取内存池中最大的内存块数。

+

osMemoryPoolGetCount

+

获取内存池中使用的内存块数。

+

osMemoryPoolGetName

+

获取内存池对象的名称。

+

osMemoryPoolGetSpace

+

获取内存池中可用的内存块数。

+

osMemoryPoolNew

+

创建并初始化一个内存池对象。

+

消息队列

+

osMessageQueueDelete

+

删除消息队列对象。

+

osMessageQueueGet

+

从队列获取消息,或者如果队列为空,则从超时获取消息。

+

osMessageQueueGetCapacity

+

获取消息队列中的最大消息数。

+

osMessageQueueGetCount

+

获取消息队列中排队的消息数。

+

osMessageQueueGetMsgSize

+

获取内存池中的最大消息大小。

+

osMessageQueueGetName

+

获取消息队列对象的名称。(暂未实现)

+

osMessageQueueGetSpace

+

获取消息队列中消息的可用插槽数。

+

osMessageQueueNew

+

创建和初始化消息队列对象。

+

osMessageQueuePut

+

如果队列已满,则将消息放入队列或超时。

+

osMessageQueueReset

+

将消息队列重置为初始空状态。(暂未实现)

+
+ +### 开发流程 + +CMSIS-RTOS2组件可以作为库或源代码提供(下图显示了库)。通过添加CMSIS-RTOS2组件(通常是一些配置文件),可以将基于CMSIS的应用程序扩展为具有RTOS功能。只需包含cmsis\_os2.h头文件就可以访问RTOS API函数,这使用户应用程序能够处理RTOS内核相关事件,而在更换内核时无需重新编译源代码。 + +静态对象分配需要访问RTOS对象控制块定义。特定于实现的头文件(下图中的os\_xx .h)提供对此类控制块定义的访问。对于OpenHarmony LiteOS-M内核,由文件名以los\_开头的头文件提供,这些文件包含OpenHarmony LiteOS-M内核的这些定义。 + +![](figure/zh-cn_image_0000001132778524.png) + +### 编程实例 + +``` +#include ... +#include "cmsis_os2.h" + +/*---------------------------------------------------------------------------- + * 应用程序主线程 + *---------------------------------------------------------------------------*/ +void app_main (void *argument) { + // ... + for (;;) {} +} + +int main (void) { + // 系统初始化 + MySystemInit(); + // ... + + osKernelInitialize(); // 初始化CMSIS-RTOS + osThreadNew(app_main, NULL, NULL); // 创建应用程序主线程 + osKernelStart(); // 开始执行线程 + for (;;) {} +} +``` + diff --git "a/zh-cn/device-dev/kernel/POSIX\346\224\257\346\214\201.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-posix.md similarity index 100% rename from "zh-cn/device-dev/kernel/POSIX\346\224\257\346\214\201.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-app-lib-posix.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md new file mode 100644 index 0000000000000000000000000000000000000000..b2f157ae194d8a266d79477623dd40191882f753 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app-lib.md @@ -0,0 +1,7 @@ +# 标准库支持 + +- **[CMSIS支持](kernel-lite-mini-app-lib-cmsis.md)** + +- **[POSIX支持](kernel-lite-mini-app-lib-posix.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-app.md b/zh-cn/device-dev/kernel/kernel-lite-mini-app.md new file mode 100644 index 0000000000000000000000000000000000000000..1d46fa1186b838599b3ec26dbc154a99ff20a111 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-app.md @@ -0,0 +1,9 @@ +# 附录 + +- **[内核编码规范](kernel-lite-mini-app-code.md)** + +- **[基本数据结构](kernel-lite-mini-app-data.md)** + +- **[标准库支持](kernel-lite-mini-app-lib.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-concept.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-concept.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..346332358b3a116c07f195a0b5013617d500ef57 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt-guide.md @@ -0,0 +1,130 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section11841123033618) +- [编程实例](#section460018317164) + - [结果验证](#section1048572415182) + + +当产生中断请求时,CPU暂停当前的任务,转而去响应外设请求。用户可以根据需要注册对应的中断处理程序,指定CPU响应中断请求时所执行的具体操作。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的中断模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 中断模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

创建、删除中断

+

HalHwiCreate

+

中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序。

+

HalHwiDelete

+

根据指定的中断号,删除中断。

+

打开、关闭中断

+

LOS_IntUnLock

+

开中断,使能当前处理器所有中断响应。

+

LOS_IntLock

+

关中断,关闭当前处理器所有中断响应。

+

LOS_IntRestore

+

恢复到使用LOS_IntLock、LOS_IntUnLock操作之前的中断状态。

+
+ +## 开发流程 + +1. 调用中断创建接口HalHwiCreate创建中断。 +2. 调用TestHwiTrigger接口触发指定中断(该接口在测试套中定义,通过写中断控制器的相关寄存器模拟外部中断,一般的外设设备,不需要执行这一步)。 +3. 调用HalHwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 根据具体硬件,配置支持的最大中断数及可设置的中断优先级个数。 +>- 中断处理程序耗时不能过长,否则会影响CPU对中断的及时响应。 +>- 中断响应过程中不能直接、间接执行引起调度的LOS\_Schedule等函数。 +>- 中断恢复LOS\_IntRestore\(\)的入参必须是与之对应的LOS\_IntLock\(\)的返回值(即关中断之前的CPSR值)。Cortex-M系列处理器中0-15中断为内部使用,因此不建议用户去申请和创建。 + +## 编程实例 + +本实例实现如下功能: + +1. 创建中断。 +2. 触发中断。 +3. 删除中断。 + +代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI\_NUM\_TEST产生中断时,会调用中断处理函数: + +``` +#include "los_interrupt.h" + +/*创建中断*/ +#define HWI_NUM_TEST 7 + +STATIC VOID HwiUsrIrq(VOID) +{ + printf("in the func HwiUsrIrq \n"); +} + +static UINT32 Example_Interrupt(VOID) +{ + UINT32 ret; + HWI_PRIOR_T hwiPrio = 3; + HWI_MODE_T mode = 0; + HWI_ARG_T arg = 0; + + /*创建中断*/ + ret = HalHwiCreate(HWI_NUM_TEST, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, arg); + if(ret == LOS_OK){ + printf("Hwi create success!\n"); + } else { + printf("Hwi create failed!\n"); + return LOS_NOK; + } + + /* 延时50个Ticks, 当有硬件中断发生时,会调用函数HwiUsrIrq*/ + LOS_TaskDelay(50); + + /*删除中断*/ + ret = HalHwiDelete(HWI_NUM_TEST); + if(ret == LOS_OK){ + printf("Hwi delete success!\n"); + } else { + printf("Hwi delete failed!\n"); + return LOS_NOK; + } + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Hwi create success! +Hwi delete success!. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md new file mode 100644 index 0000000000000000000000000000000000000000..3b10c0482f68e943142f978ef11aac6d5c536b4e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-interrupt.md @@ -0,0 +1,7 @@ +# 中断管理 + +- **[基本概念](kernel-lite-mini-basic-interrupt-concept.md)** + +- **[开发指导](kernel-lite-mini-basic-interrupt-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..91a6c20c0e1a5260d405a66966c859bc36cb290c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-basic.md @@ -0,0 +1,194 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section896412438910) + - [示例代码](#section149077554912) + - [结果验证](#section4461439172017) + + +## 接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

事件检测

+

LOS_EventPoll

+

根据eventID,eventMask(事件掩码),mode(事件读取模式),检查用户期待的事件是否发生。

+
须知:

当mode含LOS_WAITMODE_CLR,且用户期待的事件发生时,此时eventID中满足要求的事件会被清零,这种情况下eventID既是入参也是出参。其他情况eventID只作为入参。

+
+

初始化

+

LOS_EventInit

+

事件控制块初始化。

+

事件读

+

LOS_EventRead

+

读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待;

+

未读取到事件时,返回值为0;

+

正常读取到事件时,返回正值(事件发生的集合);

+

其他情况返回特定错误码。

+

事件写

+

LOS_EventWrite

+

写一个特定的事件到事件控制块。

+

事件清除

+

LOS_EventClear

+

根据events掩码,清除事件控制块中的事件。

+

事件销毁

+

LOS_EventDestroy

+

事件控制块销毁。

+
+ +## 开发流程 + +事件的典型开发流程: + +1. 初始化事件控制块 +2. 阻塞读事件控制块 +3. 写入相关事件 +4. 阻塞任务被唤醒,读取事件并检查是否满足要求 +5. 处理事件控制块 +6. 事件控制块销毁 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 进行事件读写操作时,事件的第25位为保留位,不可以进行位设置。 +>- 对同一事件反复写入,算作一次写入。 + +## 编程实例 + +### 实例描述 + +示例中,任务Example\_TaskEntry创建一个任务Example\_Event,Example\_Event读事件阻塞,Example\_TaskEntry向该任务写事件。可以通过示例日志中打印的先后顺序理解事件操作时伴随的任务切换。 + +1. 在任务Example\_TaskEntry创建任务Example\_Event,其中任务Example\_Event优先级高于Example\_TaskEntry。 +2. 在任务Example\_Event中读事件0x00000001,阻塞,发生任务切换,执行任务Example\_TaskEntry。 +3. 在任务Example\_TaskEntry向任务Example\_Event写事件0x00000001,发生任务切换,执行任务Example\_Event。 +4. Example\_Event得以执行,直到任务结束。 +5. Example\_TaskEntry得以执行,直到任务结束。 + +### 示例代码 + +示例代码如下: + +``` +#include "los_event.h" +#include "los_task.h" +#include "securec.h" + +/* 任务ID */ +UINT32 g_testTaskId; + +/* 事件控制结构体 */ +EVENT_CB_S g_exampleEvent; + +/* 等待的事件类型 */ +#define EVENT_WAIT 0x00000001 + +/* 用例任务入口函数 */ +VOID Example_Event(VOID) +{ + UINT32 ret; + UINT32 event; + + /* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */ + printf("Example_Event wait event 0x%x \n", EVENT_WAIT); + + event = LOS_EventRead(&g_exampleEvent, EVENT_WAIT, LOS_WAITMODE_AND, 100); + if (event == EVENT_WAIT) { + printf("Example_Event,read event :0x%x\n", event); + } else { + printf("Example_Event,read event timeout\n"); + } +} + +UINT32 Example_TaskEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + + /* 事件初始化 */ + ret = LOS_EventInit(&g_exampleEvent); + if (ret != LOS_OK) { + printf("init event failed .\n"); + return -1; + } + + /* 创建任务 */ + (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Event; + task1.pcName = "EventTsk1"; + task1.uwStackSize = OS_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = 5; + ret = LOS_TaskCreate(&g_testTaskId, &task1); + if (ret != LOS_OK) { + printf("task create failed.\n"); + return LOS_NOK; + } + + /* 写g_testTaskId 等待事件 */ + printf("Example_TaskEntry write event.\n"); + + ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT); + if (ret != LOS_OK) { + printf("event write failed.\n"); + return LOS_NOK; + } + + /* 清标志位 */ + printf("EventMask:%d\n", g_exampleEvent.uwEventID); + LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID); + printf("EventMask:%d\n", g_exampleEvent.uwEventID); + + /* 删除任务 */ + ret = LOS_TaskDelete(g_testTaskId); + if (ret != LOS_OK) { + printf("task delete failed.\n"); + return LOS_NOK; + } + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Example_Event wait event 0x1 +Example_TaskEntry write event. +Example_Event,read event :0x1 +EventMask:1 +EventMask:0 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..47befc62231ddb127477e813a4d104f0b9d2f1be --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event-guide.md @@ -0,0 +1,52 @@ +# 基本概念 + +- [运行机制](#section1735611583011) + - [事件控制块](#section1161415384467) + - [事件运作原理](#section187761153144617) + + +事件(Event)是一种任务间的通信机制,可用于任务间的同步操作。事件的特点是: + +- 任务间的事件同步,可以一对多,也可以多对多。一对多表示一个任务可以等待多个事件,多对多表示多个任务可以等待多个事件。但是一次写事件最多触发一个任务从阻塞中醒来。 +- 事件读超时机制。 +- 只做任务间同步,不传输具体数据。 + +提供了事件初始化、事件读写、事件清零、事件销毁等接口。 + +## 运行机制 + +### 事件控制块 + +``` +/** + * 事件控制块数据结构 + */ +typedef struct tagEvent { + UINT32 uwEventID; /* 事件集合,表示已经处理(写入和清零)的事件集合 */ + LOS_DL_LIST stEventList; /* 等待特定事件的任务链表 */ +} EVENT_CB_S, *PEVENT_CB_S; +``` + +### 事件运作原理 + +**事件初始化:**会创建一个事件控制块,该控制块维护一个已处理的事件集合,以及等待特定事件的任务链表。 + +**写事件:**会向事件控制块写入指定的事件,事件控制块更新事件集合,并遍历任务链表,根据任务等待具体条件满足情况决定是否唤醒相关任务。 + +**读事件:**如果读取的事件已存在时,会直接同步返回。其他情况会根据超时时间以及事件触发情况,来决定返回时机:等待的事件条件在超时时间耗尽之前到达,阻塞任务会被直接唤醒,否则超时时间耗尽该任务才会被唤醒。 + +读事件条件满足与否取决于入参eventMask和mode,eventMask即需要关注的事件。mode是具体处理方式,分以下三种情况: + +LOS\_WAITMODE\_AND:表示eventMask中所有事件都发生时,才返回。 + +LOS\_WAITMODE\_OR:表示eventMask中任何事件发生时,就返回。 + +LOS\_WAITMODE\_CLR:事件读取成功后,对应读取到的事件会被清零。需要配合LOS\_WAITMODE\_AND或者LOS\_WAITMODE\_OR来使用。 + +**事件清零:**根据指定掩码,去对事件控制块的事件集合进行清零操作。当掩码为0时,表示将事件集合全部清零。当掩码为0xffff时,表示不清除任何事件,保持事件集合原状。 + +**事件销毁:**销毁指定的事件控制块。 + +**图 1** 事件运作原理图 +![](figure/事件运作原理图.png "事件运作原理图") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md new file mode 100644 index 0000000000000000000000000000000000000000..4f18b0192293cbdfa74b9107939fbe332b9999ce --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-event.md @@ -0,0 +1,7 @@ +# 事件 + +- **[基本概念](kernel-lite-mini-basic-ipc-event-guide.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-event-basic.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..1d2973462485dce46a4a02e8a25396b0670a020f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-basic.md @@ -0,0 +1,19 @@ +# 基本概念 + +- [运行机制](#section115161649726) + +互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。 + +任意时刻互斥锁的状态只有两种,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。当该任务释放它时,该互斥锁被开锁,任务失去该互斥锁的所有权。当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。 + +多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。另外互斥锁可以解决信号量存在的优先级翻转问题。 + +## 运行机制 + +多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢? + +用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 + +**图 1** 互斥锁运作示意图 +![](figure/互斥锁运作示意图.png "互斥锁运作示意图") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..053174daa324f172faeab2d5d47ea6651163c8e7 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex-guide.md @@ -0,0 +1,205 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section1426719434114) + - [实例描述](#section896412438910) + - [示例代码](#section149077554912) + - [结果验证](#section2059413981311) + + +## 接口说明 + +**表 1** 互斥锁模块接口 + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

互斥锁的创建和删除

+

LOS_MuxCreate

+

创建互斥锁

+

LOS_MuxDelete

+

删除指定的互斥锁

+

互斥锁的申请和释放

+

LOS_MuxPend

+

申请指定的互斥锁

+

LOS_MuxPost

+

释放指定的互斥锁

+
+ +## 开发流程 + +互斥锁典型场景的开发流程: + +1. 创建互斥锁LOS\_MuxCreate。 +2. 申请互斥锁LOS\_MuxPend。 + + 申请模式有三种:无阻塞模式、永久阻塞模式、定时阻塞模式。 + + - 无阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有任务持有,或者持有该互斥锁的任务和申请该互斥锁的任务为同一个任务,则申请成功。 + - 永久阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。 + - 定时阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,或者用户指定时间超时后,阻塞任务才会重新得以执行。 + +3. 释放互斥锁LOS\_MuxPost。 + - 如果有任务阻塞于指定互斥锁,则唤醒被阻塞任务中优先级高的,该任务进入就绪态,并进行任务调度; + - 如果没有任务阻塞于指定互斥锁,则互斥锁释放成功。 + +4. 删除互斥锁LOS\_MuxDelete。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。 +>- 互斥锁不能在中断服务程序中使用。 +>- LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。 +>- 持有互斥锁的过程中,不得再调用LOS\_TaskPriSet等接口更改持有互斥锁任务的优先级。 + +## 编程实例 + +### 实例描述 + +本实例实现如下流程。 + +1. 任务Example\_TaskEntry创建一个互斥锁,锁任务调度,创建两个任务Example\_MutexTask1、Example\_MutexTask2。Example\_MutexTask2优先级高于Example\_MutexTask1,解锁任务调度。 +2. Example\_MutexTask2被调度,以永久阻塞模式申请互斥锁,并成功获取到该互斥锁,然后任务休眠100Tick,Example\_MutexTask2挂起,Example\_MutexTask1被唤醒。 +3. Example\_MutexTask1以定时阻塞模式申请互斥锁,等待时间为10Tick,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。10Tick超时时间到达后,Example\_MutexTask1被唤醒,以永久阻塞模式申请互斥锁,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。 +4. 100Tick休眠时间到达后,Example\_MutexTask2被唤醒, 释放互斥锁,唤醒Example\_MutexTask1。Example\_MutexTask1成功获取到互斥锁后,释放,删除互斥锁。 + +### 示例代码 + +示例代码如下: + +``` +#include +#include "los_mux.h" + +/* 互斥锁句柄id */ +UINT32 g_testMux; +/* 任务ID */ +UINT32 g_testTaskId01; +UINT32 g_testTaskId02; + +VOID Example_MutexTask1(VOID) +{ + UINT32 ret; + + printf("task1 try to get mutex, wait 10 ticks.\n"); + /* 申请互斥锁 */ + ret = LOS_MuxPend(g_testMux, 10); + + if (ret == LOS_OK) { + printf("task1 get mutex g_testMux.\n"); + /* 释放互斥锁 */ + LOS_MuxPost(g_testMux); + return; + } + if (ret == LOS_ERRNO_MUX_TIMEOUT ) { + printf("task1 timeout and try to get mutex, wait forever.\n"); + /* 申请互斥锁 */ + ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); + if (ret == LOS_OK) { + printf("task1 wait forever, get mutex g_testMux.\n"); + /* 释放互斥锁 */ + LOS_MuxPost(g_testMux); + /* 删除互斥锁 */ + LOS_MuxDelete(g_testMux); + printf("task1 post and delete mutex g_testMux.\n"); + return; + } + } + return; +} + +VOID Example_MutexTask2(VOID) +{ + printf("task2 try to get mutex, wait forever.\n"); + /* 申请互斥锁 */ + (VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); + + printf("task2 get mutex g_testMux and suspend 100 ticks.\n"); + + /* 任务休眠100Ticks */ + LOS_TaskDelay(100); + + printf("task2 resumed and post the g_testMux\n"); + /* 释放互斥锁 */ + LOS_MuxPost(g_testMux); + return; +} + +UINT32 Example_TaskEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + TSK_INIT_PARAM_S task2; + + /* 创建互斥锁 */ + LOS_MuxCreate(&g_testMux); + + /* 锁任务调度 */ + LOS_TaskLock(); + + /* 创建任务1 */ + memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1; + task1.pcName = "MutexTsk1"; + task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = 5; + ret = LOS_TaskCreate(&g_testTaskId01, &task1); + if (ret != LOS_OK) { + printf("task1 create failed.\n"); + return LOS_NOK; + } + + /* 创建任务2 */ + memset(&task2, 0, sizeof(TSK_INIT_PARAM_S)); + task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2; + task2.pcName = "MutexTsk2"; + task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task2.usTaskPrio = 4; + ret = LOS_TaskCreate(&g_testTaskId02, &task2); + if (ret != LOS_OK) { + printf("task2 create failed.\n"); + return LOS_NOK; + } + + /* 解锁任务调度 */ + LOS_TaskUnlock(); + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +task2 try to get mutex, wait forever. +task2 get mutex g_testMux and suspend 100 ticks. +task1 try to get mutex, wait 10 ticks. +task1 timeout and try to get mutex, wait forever. +task2 resumed and post the g_testMux +task1 wait forever, get mutex g_testMux. +task1 post and delete mutex g_testMux. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md new file mode 100644 index 0000000000000000000000000000000000000000..e081c4154426c896c2f722f49d9e62e7a526dcdf --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-mutex.md @@ -0,0 +1,7 @@ +# 互斥锁 + +- **[基本概念](kernel-lite-mini-basic-ipc-mutex-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-mutex-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..06f38749defa69e8e6fc678643d342e07675f90d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-basic.md @@ -0,0 +1,67 @@ +# 基本概念 + +- [运行机制](#section1582619446311) + - [队列控制块](#section1648304614720) + - [队列运作原理](#section15384012164811) + + +队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 + +任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 + +可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 + +消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: + +- 消息以先进先出的方式排队,支持异步读写。 +- 读队列和写队列都支持超时机制。 +- 每读取一条消息,就会将该消息节点设置为空闲。 +- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 +- 一个任务能够从任意一个消息队列接收和发送消息。 +- 多个任务能够从同一个消息队列接收和发送消息。 +- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 + +## 运行机制 + +### 队列控制块 + +``` +/** + * 队列控制块数据结构 + */ +typedef struct +{ + UINT8 *queue; /* 队列消息内存空间的指针 */ + UINT16 queueState; /* 队列状态 */ + UINT16 queueLen; /* 队列中消息节点个数,即队列长度 */ + UINT16 queueSize; /* 消息节点大小 */ + UINT16 queueID; /* 队列ID */ + UINT16 queueHead; /* 消息头节点位置(数组下标)*/ + UINT16 queueTail; /* 消息尾节点位置(数组下标)*/ + UINT16 readWriteableCnt[OS_READWRITE_LEN]; /* 数组下标0的元素表示队列中可读消息数, + 数组下标1的元素表示队列中可写消息数 */ + LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /* 读取或写入消息的任务等待链表, + 下标0:读取链表,下标1:写入链表 */ + LOS_DL_LIST memList; /* 内存块链表 */ +} LosQueueCB; +``` + +每个队列控制块中都含有队列状态,表示该队列的使用情况: + +- OS\_QUEUE\_UNUSED:队列未被使用。 +- OS\_QUEUE\_INUSED:队列被使用中。 + +### 队列运作原理 + +- 创建队列时,创建队列成功会返回队列ID。 +- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 +- 写队列时,根据readWriteableCnt\[1\]判断队列是否可以写入,不能对已满(readWriteableCnt\[1\]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 +- 读队列时,根据readWriteableCnt\[0\]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt\[0\]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 +- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 + +图 1 队列读写数据操作示意图 + +![](figure/zh-cn_image_0000001132935054.png) + +上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..6c161853b669ecdd896c3a11cd01deb5d6bdf624 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue-guide.md @@ -0,0 +1,199 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section2148236125814) + - [示例代码](#section121451047155716) + - [结果验证](#section2742182082117) + + +## 接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

创建/删除消息队列

+

LOS_QueueCreate

+

创建一个消息队列,由系统动态申请队列空间。

+

LOS_QueueDelete

+

根据队列ID删除一个指定队列。

+

读/写队列(不带拷贝)

+

LOS_QueueRead

+

读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。

+

LOS_QueueWrite

+

向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)。

+

LOS_QueueWriteHead

+

向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)。

+

读/写队列(带拷贝)

+

LOS_QueueReadCopy

+

读取指定队列头节点中的数据。

+

LOS_QueueWriteCopy

+

向指定队列尾节点中写入入参bufferAddr中保存的数据。

+

LOS_QueueWriteHeadCopy

+

向指定队列头节点中写入入参bufferAddr中保存的数据。

+

获取队列信息

+

LOS_QueueInfoGet

+

获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务。

+
+ +## 开发流程 + +1. 用LOS\_QueueCreate创建队列。创建成功后,可以得到队列ID。 +2. 通过LOS\_QueueWrite或者LOS\_QueueWriteCopy写队列。 +3. 通过LOS\_QueueRead或者LOS\_QueueReadCopy读队列。 +4. 通过LOS\_QueueInfoGet获取队列信息。 +5. 通过LOS\_QueueDelete删除队列。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 +>- 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 +>- 队列接口函数中的入参timeOut是相对时间。 +>- LOS\_QueueReadCopy和LOS\_QueueWriteCopy及LOS\_QueueWriteHeadCopy是一组接口,LOS\_QueueRead和LOS\_QueueWrite及LOS\_QueueWriteHead是一组接口,每组接口需要配套使用。 +>- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS\_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 +>- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 + +## 编程实例 + +### 实例描述 + +创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 + +1. 通过LOS\_TaskCreate创建任务1和任务2。 +2. 通过LOS\_QueueCreate创建一个消息队列。 +3. 在任务1 SendEntry中发送消息。 +4. 在任务2 RecvEntry中接收消息。 +5. 通过LOS\_QueueDelete删除队列。 + +### 示例代码 + +示例代码如下: + +``` +#include "los_task.h" +#include "los_queue.h" +static UINT32 g_queue; +#define BUFFER_LEN 50 + +VOID SendEntry(VOID) +{ + UINT32 ret = 0; + CHAR abuf[] = "test message"; + UINT32 len = sizeof(abuf); + + ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); + if(ret != LOS_OK) { + printf("send message failure, error: %x\n", ret); + } +} + +VOID RecvEntry(VOID) +{ + UINT32 ret = 0; + CHAR readBuf[BUFFER_LEN] = {0}; + UINT32 readLen = BUFFER_LEN; + + //休眠1s + usleep(1000000); + ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); + if(ret != LOS_OK) { + printf("recv message failure, error: %x\n", ret); + } + + printf("recv message: %s\n", readBuf); + + ret = LOS_QueueDelete(g_queue); + if(ret != LOS_OK) { + printf("delete the queue failure, error: %x\n", ret); + } + + printf("delete the queue success!\n"); +} + +UINT32 ExampleQueue(VOID) +{ + printf("start queue example\n"); + UINT32 ret = 0; + UINT32 task1, task2; + TSK_INIT_PARAM_S initParam = {0}; + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; + initParam.usTaskPrio = 9; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + initParam.pcName = "SendQueue"; + + LOS_TaskLock(); + ret = LOS_TaskCreate(&task1, &initParam); + if(ret != LOS_OK) { + printf("create task1 failed, error: %x\n", ret); + return ret; + } + + initParam.pcName = "RecvQueue"; + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; + ret = LOS_TaskCreate(&task2, &initParam); + if(ret != LOS_OK) { + printf("create task2 failed, error: %x\n", ret); + return ret; + } + + ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); + if(ret != LOS_OK) { + printf("create queue failure, error: %x\n", ret); + } + + printf("create the queue success!\n"); + LOS_TaskUnlock(); + return ret; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +start test example +create the queue success! +recv message: test message +delete the queue success! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md new file mode 100644 index 0000000000000000000000000000000000000000..a278033961591f72c9adc5629729eb06f922b266 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-queue.md @@ -0,0 +1,7 @@ +# 消息队列 + +- **[基本概念](kernel-lite-mini-basic-ipc-queue-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-queue-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..79c4d7e6f5765673641968df9142a9db722fd0c2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-basic.md @@ -0,0 +1,53 @@ +# 基本概念 + +- [运行机制](#section1794010261861) + - [信号量控制块](#section11372149164815) + - [信号量运作原理](#section139726510491) + + +信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。 + +一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况: + +- 0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。 +- 正值,表示该信号量当前可被获取。 + +以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同: + +- 用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制。 +- 用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步。 + +## 运行机制 + +### 信号量控制块 + +``` +/** + * 信号量控制块数据结构 + */ +typedef struct { + UINT16 semStat; /* 信号量状态 */ + UINT16 semType; /* 信号量类型 */ + UINT16 semCount; /* 信号量计数 */ + UINT16 semId; /* 信号量索引号 */ + LOS_DL_LIST semList; /* 挂接阻塞于该信号量的任务 */ +} LosSemCB; +``` + +### 信号量运作原理 + +信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG\_BASE\_IPC\_SEM\_LIMIT宏实现),并把所有信号量初始化成未使用,加入到未使用链表中供系统使用。 + +信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。 + +信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 + +信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 + +信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 + +信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 + +**图 1** 信号量运作示意图 +![](figure/信号量运作示意图.png "信号量运作示意图") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..81715063b36a075044c4b1e2b98c14b7a2c67c15 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem-guide.md @@ -0,0 +1,206 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section22061718111412) + - [示例代码](#section1775922321416) + - [结果验证](#section160404016213) + + +## 接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

创建/删除信号量

+

LOS_SemCreate

+

创建信号量,返回信号量ID

+

LOS_BinarySemCreate

+

创建二值信号量,其计数值最大为1

+

LOS_SemDelete

+

删除指定的信号量

+

申请/释放信号量

+

LOS_SemPend

+

申请指定的信号量,并设置超时时间

+

LOS_SemPost

+

释放指定的信号量

+
+ +## 开发流程 + +1. 创建信号量LOS\_SemCreate,若要创建二值信号量则调用LOS\_BinarySemCreate。 +2. 申请信号量LOS\_SemPend。 +3. 释放信号量LOS\_SemPost。 +4. 删除信号量LOS\_SemDelete。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>由于中断不能被阻塞,因此不能在中断中使用阻塞模式申请信号量。 + +## 编程实例 + +### 实例描述 + +本实例实现如下功能: + +1. 测试任务ExampleSem创建一个信号量,锁任务调度,创建两个任务ExampleSemTask1、ExampleSemTask2, ExampleSemTask2优先级高于ExampleSemTask1,两个任务中申请同一信号量,解锁任务调度后两任务阻塞,测试任务ExampleSem释放信号量。 +2. ExampleSemTask2得到信号量,被调度,然后任务休眠20Tick,ExampleSemTask2延迟,ExampleSemTask1被唤醒。 +3. ExampleSemTask1定时阻塞模式申请信号量,等待时间为10Tick,因信号量仍被ExampleSemTask2持有,ExampleSemTask1挂起,10Tick后仍未得到信号量,ExampleSemTask1被唤醒,试图以永久阻塞模式申请信号量,ExampleSemTask1挂起。 +4. 20Tick后ExampleSemTask2唤醒, 释放信号量后,ExampleSemTask1得到信号量被调度运行,最后释放信号量。 +5. ExampleSemTask1执行完,40Tick后任务ExampleSem被唤醒,执行删除信号量。 + +### 示例代码 + +示例代码如下: + +``` +#include "los_sem.h" +#include "securec.h" + +/* 任务ID */ +static UINT32 g_testTaskId01; +static UINT32 g_testTaskId02; + +/* 测试任务优先级 */ +#define TASK_PRIO_TEST 5 + +/* 信号量结构体id */ +static UINT32 g_semId; + +VOID ExampleSemTask1(VOID) +{ + UINT32 ret; + + printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n"); + + /* 定时阻塞模式申请信号量,定时时间为10ticks */ + ret = LOS_SemPend(g_semId, 10); + + /* 申请到信号量 */ + if (ret == LOS_OK) { + LOS_SemPost(g_semId); + return; + } + /* 定时时间到,未申请到信号量 */ + if (ret == LOS_ERRNO_SEM_TIMEOUT) { + printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n"); + + /*永久阻塞模式申请信号量*/ + ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); + printf("ExampleSemTask1 wait_forever and get sem g_semId.\n"); + if (ret == LOS_OK) { + LOS_SemPost(g_semId); + return; + } + } +} + +VOID ExampleSemTask2(VOID) +{ + UINT32 ret; + printf("ExampleSemTask2 try get sem g_semId wait forever.\n"); + + /* 永久阻塞模式申请信号量 */ + ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); + + if (ret == LOS_OK) { + printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n"); + } + + /* 任务休眠20 ticks */ + LOS_TaskDelay(20); + + printf("ExampleSemTask2 post sem g_semId.\n"); + /* 释放信号量 */ + LOS_SemPost(g_semId); + return; +} + +UINT32 ExampleSem(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + TSK_INIT_PARAM_S task2; + + /* 创建信号量 */ + LOS_SemCreate(0, &g_semId); + + /* 锁任务调度 */ + LOS_TaskLock(); + + /* 创建任务1 */ + (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1; + task1.pcName = "TestTask1"; + task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = TASK_PRIO_TEST; + ret = LOS_TaskCreate(&g_testTaskId01, &task1); + if (ret != LOS_OK) { + printf("task1 create failed .\n"); + return LOS_NOK; + } + + /* 创建任务2 */ + (VOID)memset_s(&task2, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); + task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2; + task2.pcName = "TestTask2"; + task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task2.usTaskPrio = (TASK_PRIO_TEST - 1); + ret = LOS_TaskCreate(&g_testTaskId02, &task2); + if (ret != LOS_OK) { + printf("task2 create failed.\n"); + return LOS_NOK; + } + + /* 解锁任务调度 */ + LOS_TaskUnlock(); + + ret = LOS_SemPost(g_semId); + + /* 任务休眠400 ticks */ + LOS_TaskDelay(400); + + /* 删除信号量 */ + LOS_SemDelete(g_semId); + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +ExampleSemTask2 try get sem g_semId wait forever. +ExampleSemTask2 get sem g_semId and then delay 20 ticks. +ExampleSemTask1 try get sem g_semId, timeout 10 ticks. + +ExampleSemTask1 timeout and try get sem g_semId wait forever. +ExampleSemTask2 post sem g_semId. +ExampleSemTask1 wait_forever and get sem g_semId. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md new file mode 100644 index 0000000000000000000000000000000000000000..1b1afc6945e99589fb8185863fe4ce76b968a38d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc-sem.md @@ -0,0 +1,7 @@ +# 信号量 + +- **[基本概念](kernel-lite-mini-basic-ipc-sem-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-ipc-sem-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md new file mode 100644 index 0000000000000000000000000000000000000000..2acba70e2f90c17310c5ce4a77c8d12a9658afc7 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-ipc.md @@ -0,0 +1,11 @@ +# 内核通信机制 + +- **[事件](kernel-lite-mini-basic-ipc-event.md)** + +- **[互斥锁](kernel-lite-mini-basic-ipc-mutex.md)** + +- **[消息队列](kernel-lite-mini-basic-ipc-queue.md)** + +- **[信号量](kernel-lite-mini-basic-ipc-sem.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-4.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-4.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-basic.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md new file mode 100644 index 0000000000000000000000000000000000000000..c9f32f97ad19a097af45e8d43620c068241e3991 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-dynamic.md @@ -0,0 +1,227 @@ +# 动态内存 + +- [运行机制](#section328282013571) +- [开发指导](#section7921151015814) + - [使用场景](#section326917198583) + - [接口说明](#section1032331584) + - [开发流程](#section07271773592) + - [编程实例](#section84931234145913) + - [结果验证](#section165233233917) + + +## 运行机制 + +动态内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。 + +OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: + +**图 1** 动态内存核心算法 +![](figure/动态内存核心算法.png "动态内存核心算法") + +根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:\[4, 127\]和\[27, 231\],如上图size class所示: + +1. 对\[4,127\]区间的内存进行等分,如上图绿色部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。\[4,127\]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 +2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见上图蓝色的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。 + +例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间\[40,43\],第10个空闲链表,位图标记的第10比特位。把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间\[2^9,2^9+2^6\],第31+2\*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。 + +内存管理结构如下图所示: + +**图 2** 动态内存管理结构图 +![](figure/动态内存管理结构图.png "动态内存管理结构图") + +- 内存池池头部分 + + 内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。 + +- 内存池节点部分 + + 包含3种类型节点:未使用空闲内存节点,已使用内存节点和尾节点。每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。空闲内存节点和已使用内存节点后面的内存区域是数据域,尾节点没有数据域。 + + +## 开发指导 + +### 使用场景 + +动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。动态内存管理主要用于用户需要使用大小不等的内存块的场景,当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。 + +### 接口说明 + +OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 + +**表 1** 动态内存模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

初始化和删除内存池

+

LOS_MemInit

+

初始化一块指定的动态内存池,大小为size。

+

LOS_MemDeInit

+

删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。

+

申请、释放动态内存

+

LOS_MemAlloc

+

从指定动态内存池中申请size长度的内存。

+

LOS_MemFree

+

释放从指定动态内存中申请的内存。

+

LOS_MemRealloc

+

按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块。

+

LOS_MemAllocAlign

+

从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。

+

获取内存池信息

+

LOS_MemPoolSizeGet

+

获取指定动态内存池的总大小。

+

LOS_MemTotalUsedGet

+

获取指定动态内存池的总使用量大小。

+

LOS_MemInfoGet

+

获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。

+

LOS_MemPoolList

+

打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。

+

获取内存块信息

+

LOS_MemFreeNodeShow

+

打印指定内存池的空闲内存块的大小及数量。

+

LOS_MemUsedNodeShow

+

打印指定内存池的已使用内存块的大小及数量。

+

检查指定内存池的完整性

+

LOS_MemIntegrityCheck

+

对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS\_SYS\_MEM\_SIZE的大小。 +>- 对齐分配内存接口LOS\_MemAllocAlign/LOS\_MemMallocAlign因为要进行地址对齐,可能会额外消耗部分内存,故存在一些遗失内存,当系统释放该对齐内存时,同时回收由于对齐导致的遗失内存。 + +### 开发流程 + +本节介绍使用动态内存的典型场景开发流程。 + +1. 初始化LOS\_MemInit。 + + 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。注:EndNode作为内存池末尾的节点,size为0。 + + +1. 申请任意大小的动态内存LOS\_MemAlloc。 + + 判断动态内存池中是否存在大于申请量大小的空闲内存块空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。如果空闲内存块大于申请量,需要对内存块进行分割,剩余的部分作为空闲内存块挂载到空闲内存链表上。 + + +1. 释放动态内存LOS\_MemFree。 + + 回收内存块,供下一次使用。调用LOS\_MemFree释放内存块,则会回收内存块,并且将其标记为FreeNode。在回收内存块时,相邻的FreeNode会自动合并。 + + +### 编程实例 + +本实例执行以下步骤: + +1. 初始化一个动态内存池。 +2. 从动态内存池中申请一个内存块。 +3. 在内存块中存放一个数据。 +4. 打印出内存块中的数据。 +5. 释放该内存块。 + +示例代码如下: + +``` +#include "los_memory.h" + +VOID Example_DynMem(VOID) +{ + UINT32 *mem = NULL; + UINT32 ret; + + /*初始化内存池*/ + ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE); + if (LOS_OK == ret) { + printf("Mem init success!\n"); + } else { + printf("Mem init failed!\n"); + return; + } + + /*分配内存*/ + mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4); + if (NULL == mem) { + printf("Mem alloc failed!\n"); + return; + } + printf("Mem alloc success!\n"); + + /*赋值*/ + *mem = 828; + printf("*mem = %d\n", *mem); + + /*释放内存*/ + ret = LOS_MemFree(g_testPool, mem); + if (LOS_OK == ret) { + printf("Mem free success!\n"); + } else { + printf("Mem free failed!\n"); + } + + return; +} +``` + +### 结果验证 + +输出结果如下: + +``` +Mem init success! +Mem alloc success! +*mem = 828 +Mem free success! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md new file mode 100644 index 0000000000000000000000000000000000000000..b52510e80b57ef577efaa7babfebc808d6041ca5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory-static.md @@ -0,0 +1,182 @@ +# 静态内存 + +- [运行机制](#section165473517522) +- [开发指导](#section57511620165218) + - [使用场景](#section215474911529) + - [接口说明](#section79231214539) + - [开发流程](#section1388511316548) + - [编程实例](#section17801515105519) + - [结果验证](#section11818154112319) + + +## 运行机制 + +静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更。 + +静态内存池由一个控制块LOS\_MEMBOX\_INFO和若干相同大小的内存块LOS\_MEMBOX\_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。 + +**图 1** 静态内存示意图 +![](figure/静态内存示意图.png "静态内存示意图") + +## 开发指导 + +### 使用场景 + +当用户需要使用固定长度的内存时,可以通过静态内存分配的方式获取内存,一旦使用完毕,通过静态内存释放函数归还所占用内存,使之可以重复使用。 + +### 接口说明 + +OpenHarmony LiteOS-M的静态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 + +**表 1** 静态内存模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

初始化静态内存池

+

LOS_MemboxInit

+

初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小。

+

清除静态内存块内容

+

LOS_MemboxClr

+

清零从静态内存池中申请的静态内存块的内容。

+

申请、释放静态内存

+

LOS_MemboxAlloc

+

从指定的静态内存池中申请一块静态内存块。

+

LOS_MemboxFree

+

释放从静态内存池中申请的一块静态内存块。

+

获取、打印静态内存池信息

+

LOS_MemboxStatisticsGet

+

获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小。

+

LOS_ShowBox

+

打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址。

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>初始化后的内存池的内存块数量,不等于总大小除于内存块大小,因为内存池的控制块和每个内存块的控制头,都存在内存开销,设置总大小时,需要将这些因素考虑进去。 + +### 开发流程 + +本节介绍使用静态内存的典型场景开发流程。 + +1. 规划一片内存区域作为静态内存池。 +2. 调用LOS\_MemboxInit初始化静态内存池。 + + 初始化会将入参指定的内存区域分割为N块(N值取决于静态内存总大小和块大小),将所有内存块挂到空闲链表,在内存起始处放置控制头。 + +3. 调用LOS\_MemboxAlloc接口分配静态内存。 + + 系统将会从空闲链表中获取第一个空闲块,并返回该内存块的起始地址。 + +4. 调用LOS\_MemboxClr接口。 + + 将入参地址对应的内存块清零。 + +5. 调用LOS\_MemboxFree接口。 + + 将该内存块加入空闲链表。 + + +### 编程实例 + +本实例执行以下步骤: + +1. 初始化一个静态内存池。 +2. 从静态内存池中申请一块静态内存。 +3. 在内存块存放一个数据。 +4. 打印出内存块中的数据。 +5. 清除内存块中的数据。 +6. 释放该内存块。 + + 示例代码如下: + + +``` +#include "los_membox.h" + +VOID Example_StaticMem(VOID) +{ + UINT32 *mem = NULL; + UINT32 blkSize = 10; + UINT32 boxSize = 100; + UINT32 boxMem[1000]; + UINT32 ret; + + /*内存池初始化*/ + ret = LOS_MemboxInit(&boxMem[0], boxSize, blkSize); + if(ret != LOS_OK) { + printf("Membox init failed!\n"); + return; + } else { + printf("Membox init success!\n"); + } + + /*申请内存块*/ + mem = (UINT32 *)LOS_MemboxAlloc(boxMem); + if (NULL == mem) { + printf("Mem alloc failed!\n"); + return; + } + printf("Mem alloc success!\n"); + + /*赋值*/ + *mem = 828; + printf("*mem = %d\n", *mem); + + /*清除内存内容*/ + LOS_MemboxClr(boxMem, mem); + printf("Mem clear success \n *mem = %d\n", *mem); + + /*释放内存*/ + ret = LOS_MemboxFree(boxMem, mem); + if (LOS_OK == ret) { + printf("Mem free success!\n"); + } else { + printf("Mem free failed!\n"); + } + + return; +} +``` + +### 结果验证 + +输出结果如下: + +``` +Membox init success! +Mem alloc success! +*mem = 828 +Mem clear success +*mem = 0 +Mem free success! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md new file mode 100644 index 0000000000000000000000000000000000000000..e0f1da7e35707537406eccc8b425c8697e5e06e0 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-memory.md @@ -0,0 +1,9 @@ +# 内存管理 + +- **[基本概念](kernel-lite-mini-basic-memory-basic.md)** + +- **[静态内存](kernel-lite-mini-basic-memory-static.md)** + +- **[动态内存](kernel-lite-mini-basic-memory-dynamic.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-15.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-15.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-basic.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..0e9f963c0c631b7b8b8284dfa4f16e54d1de273d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft-guide.md @@ -0,0 +1,218 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section3741753191918) + - [示例代码](#section20760101182016) + - [结果验证](#section11244112818172) + + +## 接口说明 + +OpenHarmony LiteOS-M内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 软件定时器接口 + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

创建、删除定时器

+

LOS_SwtmrCreate

+

创建定时器

+

LOS_SwtmrDelete

+

删除定时器

+

启动、停止定时器

+

LOS_SwtmrStart

+

启动定时器

+

LOS_SwtmrStop

+

停止定时器

+

获得软件定时器剩余Tick数

+

LOS_SwtmrTimeGet

+

获得软件定时器剩余Tick数

+
+ +## 开发流程 + +软件定时器的典型开发流程: + +1. 配置软件定时器。 + - 确认配置项LOSCFG\_BASE\_CORE\_SWTMR和LOSCFG\_BASE\_IPC\_QUEUE为1打开状态; + - 配置LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数; + - 配置OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度; + +2. 创建定时器LOS\_SwtmrCreate。 + - 创建一个指定计时时长、指定超时处理函数、指定触发模式的软件定时器; + - 返回函数运行结果,成功或失败; + +3. 启动定时器LOS\_SwtmrStart。 +4. 获得软件定时器剩余Tick数LOS\_SwtmrTimeGet。 +5. 停止定时器LOS\_SwtmrStop。 +6. 删除定时器LOS\_SwtmrDelete。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 软件定时器的回调函数中不要做过多操作,不要使用可能引起任务挂起或者阻塞的接口或操作。 +>- 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级设定为0,且不允许修改 。 +>- 系统可配置的软件定时器资源个数是指:整个系统可使用的软件定时器资源总个数,而并非是用户可使用的软件定时器资源个数。例如:系统软件定时器多占用一个软件定时器资源数,那么用户能使用的软件定时器资源就会减少一个。 +>- 创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。 +>- 创建单次不自删除属性的定时器,用户需要调用定时器删除接口删除定时器,回收定时器资源,避免资源泄露。 + +## 编程实例 + +### 实例描述 + +在下面的例子中,演示如下功能: + +1. 软件定时器创建、启动、删除、暂停、重启操作。 +2. 单次软件定时器,周期软件定时器使用方法。 + +### 示例代码 + +前提条件: + +- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR配置项打开。 +- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR\_ALIGN配置项关闭,示例代码中演示代码不涉及定时器对齐。 +- 配置好LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数。 +- 配置好OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度。 + +代码实现如下: + +``` +#include "los_swtmr.h" + +/* Timer count */ +UINT32 g_timerCount1 = 0; +UINT32 g_timerCount2 = 0; + +/* 任务ID */ +UINT32 g_testTaskId01; + +void Timer1_Callback(UINT32 arg) // 回调函数1 +{ + UINT32 tick_last1; + g_timerCount1++; + tick_last1=(UINT32)LOS_TickCountGet(); // 获取当前Tick数 + printf("g_timerCount1=%d, tick_last1=%d\n", g_timerCount1, tick_last1); +} + +void Timer2_Callback(UINT32 arg) // 回调函数2 +{ + UINT32 tick_last2; + tick_last2=(UINT32)LOS_TickCountGet(); + g_timerCount2++; + printf("g_timerCount2=%d tick_last2=%d\n", g_timerCount2, tick_last2); +} + +void Timer_example(void) +{ + UINT32 id1; // timer id + UINT32 id2; // timer id + UINT32 uwTick; + + /*创建单次软件定时器,Tick数为1000,启动到1000Tick数时执行回调函数1 */ + LOS_SwtmrCreate (1000, LOS_SWTMR_MODE_ONCE, Timer1_Callback, &id1, 1); + + /*创建周期性软件定时器,每100Tick数执行回调函数2 */ + LOS_SwtmrCreate(100, LOS_SWTMR_MODE_PERIOD, Timer2_Callback, &id2, 1); + printf("create Timer1 success\n"); + + LOS_SwtmrStart (id1); //启动单次软件定时器 + printf("start Timer1 sucess\n"); + + LOS_TaskDelay(200); //延时200Tick数 + LOS_SwtmrTimeGet(id1, &uwTick); // 获得单次软件定时器剩余Tick数 + printf("uwTick =%d\n", uwTick); + + LOS_SwtmrStop(id1); // 停止软件定时器 + printf("stop Timer1 sucess\n"); + + LOS_SwtmrStart(id1); + LOS_TaskDelay(1000); + + LOS_SwtmrDelete(id1); // 删除软件定时器 + printf("delete Timer1 sucess\n"); + + LOS_SwtmrStart(id2); // 启动周期性软件定时器 + printf("start Timer2\n"); + + LOS_TaskDelay(1000); + LOS_SwtmrStop(id2); + LOS_SwtmrDelete(id2); +} + +UINT32 Example_TaskEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S task1; + + /* 锁任务调度 */ + LOS_TaskLock(); + + /* 创建任务1 */ + memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); + task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Timer_example; + task1.pcName = "TimerTsk"; + task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + task1.usTaskPrio = 5; + ret = LOS_TaskCreate(&g_testTaskId01, &task1); + if (ret != LOS_OK) { + printf("TimerTsk create failed.\n"); + return LOS_NOK; + } + + /* 解锁任务调度 */ + LOS_TaskUnlock(); + + return LOS_OK; +} +``` + +### 结果验证 + +编译烧录运行,输出结果如下: + +``` +create Timer1 success +start Timer1 sucess +uwTick =798 +stop Timer1 sucess +g_timerCount1=1, tick_last1=1208 +delete Timer1 sucess +start Timer2 +g_timerCount2=1 tick_last2=1313 +g_timerCount2=2 tick_last2=1413 +g_timerCount2=3 tick_last2=1513 +g_timerCount2=4 tick_last2=1613 +g_timerCount2=5 tick_last2=1713 +g_timerCount2=6 tick_last2=1813 +g_timerCount2=7 tick_last2=1913 +g_timerCount2=8 tick_last2=2013 +g_timerCount2=9 tick_last2=2113 +g_timerCount2=10 tick_last2=2213 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md new file mode 100644 index 0000000000000000000000000000000000000000..0aef7971458b34cc5b9b903ca9317026ee5c7a62 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-soft.md @@ -0,0 +1,7 @@ +# 软件定时器 + +- **[基本概念](kernel-lite-mini-basic-soft-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-soft-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..074596f401185126a3ea5701b115aba2887cebcf --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-basic.md @@ -0,0 +1,96 @@ +# 基本概念 + +- [任务相关概念](#section673132352511) +- [任务运行机制](#section176294469251) + +从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。 + +OpenHarmony LiteOS-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。任务模块具有如下特性: + +- 支持多任务。 +- 一个任务表示一个线程。 +- 抢占式调度机制,高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。 +- 相同优先级任务支持时间片轮转调度方式。 +- 共有32个优先级\[0-31\],最高优先级为0,最低优先级为31。 + +## 任务相关概念 + +**任务状态** + +任务有多种运行状态。系统初始化完成后,创建的任务就可以在系统中竞争一定的资源,由内核进行调度。 + +任务状态通常分为以下四种: + +- 就绪(Ready):该任务在就绪队列中,只等待CPU。 +- 运行(Running):该任务正在执行。 +- 阻塞(Blocked):该任务不在就绪队列中。包含任务被挂起(suspend状态)、任务被延时(delay状态)、任务正在等待信号量、读写队列或者等待事件等。 +- 退出态(Dead):该任务运行结束,等待系统回收资源。 + +**任务状态迁移** + +**图 1** 任务状态示意图 +![](figure/任务状态示意图.png "任务状态示意图") + +**任务状态迁移说明:** + +- 就绪态→运行态 + + 任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,同时该任务从就绪队列中移出。 + +- 运行态→阻塞态 + + 正在运行的任务发生阻塞(挂起、延时、读信号量等)时,该任务会从就绪队列中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。 + +- 阻塞态→就绪态(阻塞态→运行态) + + 阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态;此时如果被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态。 + +- 就绪态→阻塞态 + + 任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复。 + +- 运行态→就绪态 + + 有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中。 + +- 运行态→退出态 + + 运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态以及Invalid状态。例如,任务运行结束但是没有自删除,对外呈现的就是Invalid状态,即退出态。 + +- 阻塞态→退出态 + + 阻塞的任务调用删除接口,任务状态由阻塞态变为退出态。 + + +**任务ID** + +任务ID,在任务创建时通过参数返回给用户,是任务的重要标识。系统中的ID号是唯一的。用户可以通过任务ID对指定任务进行任务挂起、任务恢复、查询任务名等操作。 + +**任务优先级** + +优先级表示任务执行的优先顺序。任务的优先级决定了在发生任务切换时即将要执行的任务,就绪队列中最高优先级的任务将得到执行。 + +**任务入口函数** + +新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置。 + +**任务栈** + +每个任务都拥有一个独立的栈空间,我们称为任务栈。栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等。 + +**任务上下文** + +任务在运行过程中使用的一些资源,如寄存器等,称为任务上下文。当这个任务挂起时,其他任务继续执行,可能会修改寄存器等资源中的值。如果任务切换时没有保存任务上下文,可能会导致任务恢复后出现未知错误。因此在任务切换时会将切出任务的任务上下文信息,保存在自身的任务栈中,以便任务恢复后,从栈空间中恢复挂起时的上下文信息,从而继续执行挂起时被打断的代码。 + +**任务控制块TCB** + +每个任务都含有一个任务控制块\(TCB\)。TCB包含了任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息。TCB可以反映出每个任务运行情况。 + +**任务切换** + +任务切换包含获取就绪队列中最高优先级任务、切出任务上下文保存、切入任务上下文恢复等动作。 + +## 任务运行机制 + +用户创建任务时,系统会初始化任务栈,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。这样在任务第一次启动进入运行态时,将会执行“任务入口函数”。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..6b42cf5b4a99c1316d0388e23795ba3794b73d86 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task-guide.md @@ -0,0 +1,306 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [结果验证](#section189023104457) + + +任务创建后,内核可以执行锁任务调度,解锁任务调度,挂起,恢复,延时等操作,同时也可以设置任务优先级,获取任务优先级。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 任务管理模块接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

创建和删除任务

+

LOS_TaskCreateOnly

+

创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态。

+

LOS_TaskCreate

+

创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。

+

LOS_TaskDelete

+

删除指定的任务。

+

控制任务状态

+

LOS_TaskResume

+

恢复挂起的任务,使该任务进入ready状态。

+

LOS_TaskSuspend

+

挂起指定的任务,然后切换任务

+

LOS_TaskDelay

+

任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。

+

LOS_Msleep

+

传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。

+

LOS_TaskYield

+

当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。

+

控制任务调度

+

LOS_TaskLock

+

锁任务调度,但任务仍可被中断打断。

+

LOS_TaskUnlock

+

解锁任务调度。

+

LOS_Schedule

+

触发任务调度。

+

控制任务优先级

+

LOS_CurTaskPriSet

+

设置当前任务的优先级。

+

LOS_TaskPriSet

+

设置指定任务的优先级。

+

LOS_TaskPriGet

+

获取指定任务的优先级。

+

获取任务信息

+

LOS_CurTaskIDGet

+

获取当前任务的ID。

+

LOS_NextTaskIDGet

+

获取任务就绪队列中优先级最高的任务的ID。

+

LOS_NewTaskIDGet

+

等同LOS_NextTaskIDGet。

+

LOS_CurTaskNameGet

+

获取当前任务的名称。

+

LOS_TaskNameGet

+

获取指定任务的名称。

+

LOS_TaskStatusGet

+

获取指定任务的状态。

+

LOS_TaskInfoGet

+

获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。

+

LOS_TaskIsRunning

+

获取任务模块是否已经开始调度运行。

+

任务信息维测

+

LOS_TaskSwitchInfoGet

+

获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。

+
+ +## 开发流程 + +以创建任务为例,讲解开发流程。 + +1. 锁任务调度LOS\_TaskLock,防止高优先级任务调度。 +2. 创建任务LOS\_TaskCreate。 +3. 解锁任务LOS\_TaskUnlock,让任务按照优先级进行调度。 +4. 延时任务LOS\_TaskDelay,任务延时等待。 +5. 挂起指定的任务LOS\_TaskSuspend,任务挂起等待恢复操作。 +6. 恢复挂起的任务LOS\_TaskResume。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 执行Idle任务时,会对待回收链表中的任务控制块和任务栈进行回收。 +>- 任务名是指针,并没有分配空间,在设置任务名时,禁止将局部变量的地址赋值给任务名指针。 +>- 任务栈的大小按8字节大小对齐。确定任务栈大小的原则是,够用就行,多了浪费,少了任务栈溢出。 +>- 挂起当前任务时,如果已经锁任务调度,则无法挂起。 +>- Idle任务及软件定时器任务不能被挂起或者删除。 +>- 在中断处理函数中或者在锁任务的情况下,执行LOS\_TaskDelay会失败。 +>- 锁任务调度,并不关中断,因此任务仍可被中断打断。 +>- 锁任务调度必须和解锁任务调度配合使用。 +>- 设置任务优先级时可能会发生任务调度。 +>- 可配置的系统最大任务数是指:整个系统的任务总个数,而非用户能使用的任务个数。例如:系统软件定时器多占用一个任务资源,那么用户能使用的任务资源就会减少一个。 +>- LOS\_CurTaskPriSet和LOS\_TaskPriSet接口不能在中断中使用,也不能用于修改软件定时器任务的优先级。 +>- LOS\_TaskPriGet接口传入的task ID对应的任务未创建或者超过最大任务数,统一返回-1。 +>- 在删除任务时要保证任务申请的资源(如互斥锁、信号量等)已被释放。 + +## 编程实例 + +本实例介绍基本的任务操作方法,包含2个不同优先级任务的创建、任务延时、任务锁与解锁调度、挂起和恢复等操作,阐述任务优先级调度的机制以及各接口的应用。示例代码如下: + +``` +UINT32 g_taskHiId; +UINT32 g_taskLoId; +#define TSK_PRIOR_HI 4 +#define TSK_PRIOR_LO 5 + +UINT32 Example_TaskHi(VOID) +{ + UINT32 ret; + + printf("Enter TaskHi Handler.\n"); + + /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务(TaskLo任务) */ + ret = LOS_TaskDelay(100); + if (ret != LOS_OK) { + printf("Delay TaskHi Failed.\n"); + return LOS_NOK; + } + + /* 100个Ticks时间到了后,该任务恢复,继续执行 */ + printf("TaskHi LOS_TaskDelay Done.\n"); + + /* 挂起自身任务 */ + ret = LOS_TaskSuspend(g_taskHiId); + if (ret != LOS_OK) { + printf("Suspend TaskHi Failed.\n"); + return LOS_NOK; + } + printf("TaskHi LOS_TaskResume Success.\n"); + return ret; +} + +/* 低优先级任务入口函数 */ +UINT32 Example_TaskLo(VOID) +{ + UINT32 ret; + + printf("Enter TaskLo Handler.\n"); + + /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务 */ + ret = LOS_TaskDelay(100); + if (ret != LOS_OK) { + printf("Delay TaskLo Failed.\n"); + return LOS_NOK; + } + + printf("TaskHi LOS_TaskSuspend Success.\n"); + + /* 恢复被挂起的任务g_taskHiId */ + ret = LOS_TaskResume(g_taskHiId); + if (ret != LOS_OK) { + printf("Resume TaskHi Failed.\n"); + return LOS_NOK; + } + return ret; +} + +/* 任务测试入口函数,创建两个不同优先级的任务 */ +UINT32 Example_TskCaseEntry(VOID) +{ + UINT32 ret; + TSK_INIT_PARAM_S initParam; + + /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ + LOS_TaskLock(); + + printf("LOS_TaskLock() Success!\n"); + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi; + initParam.usTaskPrio = TSK_PRIOR_HI; + initParam.pcName = "TaskHi"; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + + /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + ret = LOS_TaskCreate(&g_taskHiId, &initParam); + if (ret != LOS_OK) { + LOS_TaskUnlock(); + + printf("Example_TaskHi create Failed!\n"); + return LOS_NOK; + } + + printf("Example_TaskHi create Success!\n"); + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo; + initParam.usTaskPrio = TSK_PRIOR_LO; + initParam.pcName = "TaskLo"; + initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; + + /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + ret = LOS_TaskCreate(&g_taskLoId, &initParam); + if (ret != LOS_OK) { + LOS_TaskUnlock(); + printf("Example_TaskLo create Failed!\n"); + return LOS_NOK; + } + + printf("Example_TaskLo create Success!\n"); + + /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ + LOS_TaskUnlock(); + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +LOS_TaskLock() Success! +Example_TaskHi create Success! +Example_TaskLo create Success! +Enter TaskHi Handler. +Enter TaskLo Handler. +TaskHi LOS_TaskDelay Done. +TaskHi LOS_TaskSuspend Success. +TaskHi LOS_TaskResume Success. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md new file mode 100644 index 0000000000000000000000000000000000000000..8ca91b1f10c4e6e638621cde1fc9338c0667bdb5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-task.md @@ -0,0 +1,7 @@ +# 任务管理 + +- **[基本概念](kernel-lite-mini-basic-task-basic.md)** + +- **[开发指导](kernel-lite-mini-basic-task-guide.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-13.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-13.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-basic.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..a0328b1c7ddea9644fa8c861fa9ac72453b72ae8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic-time-guide.md @@ -0,0 +1,159 @@ +# 开发指导 + +- [接口说明](#section158501652121514) +- [开发流程](#section783435801510) +- [编程实例](#section460018317164) + - [实例描述](#section127752801718) + - [示例代码](#section321653551711) + - [结果验证](#section4366193318167) + + +用户需要了解当前系统运行的时间以及Tick与秒、毫秒之间的转换关系时,需要使用到时间管理模块的接口。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 时间管理接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

时间转换

+

LOS_MS2Tick

+

毫秒转换成Tick

+

LOS_Tick2MS

+

Tick转化为毫秒

+

OsCpuTick2MS

+

Cycle数目转化为毫秒,使用2个

+

UINT32类型的数值分别表示结果数值的高、低32位。

+

OsCpuTick2US

+

Cycle数目转化为微秒,使用2个

+

UINT32类型的数值分别表示结果数值的高、低32位。

+

时间统计

+

LOS_SysClockGet

+

获取系统时钟

+

LOS_TickCountGet

+

获取自系统启动以来的Tick数

+

LOS_CyclePerTickGet

+

每个Tick多少Cycle数

+
+ +## 开发流程 + +时间管理的典型开发流程: + +1. 根据实际需求,完成板级配置适配,并配置系统主时钟频率OS\_SYS\_CLOCK(单位Hz)和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND。OS\_SYS\_CLOCK的默认值基于硬件平台配置。 +2. 调用时钟转换/统计接口。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 时间管理不是单独的功能模块,依赖于OS\_SYS\_CLOCK和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND两个配置选项。 +>- 系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间使用。 +>- 配置选项维护在开发板工程的文件target\_config.h。 + +## 编程实例 + +### 实例描述 + +在下面的例子中,介绍了时间管理的基本方法,包括: + +1. 时间转换:将毫秒数转换为Tick数,或将Tick数转换为毫秒数。 +2. 时间统计:每Tick的Cycle数、自系统启动以来的Tick数和延迟后的Tick数。 + +### 示例代码 + +前提条件: + +- 使用每秒的Tick数LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND的默认值100。 +- 配好OS\_SYS\_CLOCK系统主时钟频率。 + +时间转换: + +``` +VOID Example_TransformTime(VOID) +{ + UINT32 ms; + UINT32 tick; + + tick = LOS_MS2Tick(10000); // 10000ms转换为tick + dprintf("tick = %d \n", tick); + ms = LOS_Tick2MS(100); // 100tick转换为ms + dprintf("ms = %d \n", ms); +} +``` + +时间统计和时间延迟: + +``` +VOID Example_GetTime(VOID) +{ + UINT32 cyclePerTick; + UINT64 tickCount; + + cyclePerTick = LOS_CyclePerTickGet(); + if(0 != cyclePerTick) { + dprintf("LOS_CyclePerTickGet = %d \n", cyclePerTick); + } + + tickCount = LOS_TickCountGet(); + if(0 != tickCount) { + dprintf("LOS_TickCountGet = %d \n", (UINT32)tickCount); + } + + LOS_TaskDelay(200); + tickCount = LOS_TickCountGet(); + if(0 != tickCount) { + dprintf("LOS_TickCountGet after delay = %d \n", (UINT32)tickCount); + } +} +``` + +### 结果验证 + +编译运行得到的结果为: + +时间转换: + +``` +tick = 1000 +ms = 1000 +``` + +时间统计和时间延迟: + +``` +LOS_CyclePerTickGet = 495000 +LOS_TickCountGet = 1 +LOS_TickCountGet after delay = 201 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..fd6774bee47339f547587c7461b536ac5b8373e1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-basic.md @@ -0,0 +1,15 @@ +# 基础内核 + +- **[中断管理](kernel-lite-mini-basic-interrupt.md)** + +- **[任务管理](kernel-lite-mini-basic-task.md)** + +- **[内存管理](kernel-lite-mini-basic-memory.md)** + +- **[内核通信机制](kernel-lite-mini-basic-ipc.md)** + +- **[时间管理](kernel-lite-basic-mini-time.md)** + +- **[软件定时器](kernel-lite-mini-basic-soft.md)** + + diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-17.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-basic.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-17.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-basic.md diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-18.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-guide.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-18.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup-guide.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md new file mode 100644 index 0000000000000000000000000000000000000000..e49d8a7175b407625353d87a11996a65bf990992 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-cpup.md @@ -0,0 +1,7 @@ +# CPU占用率 + +- **[基本概念](kernel-lite-mini-extend-cpup-basic.md)** + +- **[开发指导](kernel-lite-mini-extend-cpup-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md new file mode 100644 index 0000000000000000000000000000000000000000..d96f14f3435c61968447f9b3cbfb62ccd0fce5c7 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-fat.md @@ -0,0 +1,176 @@ +# FAT + +- [基本概念](#section1772629121418) +- [开发指导](#section1149072811148) + - [驱动适配](#section19174939191414) + - [开发流程](#section131211626151513) + - [编程实例](#section206071303163) + - [实例描述](#section45337345313) + - [示例代码](#section119813171539) + - [结果验证](#section7987101232311) + + +## 基本概念 + +FAT文件系统是File Allocation Table(文件配置表)的简称,主要包括DBR区、FAT区、DATA区三个区域。其中,FAT区各个表项记录存储设备中对应簇的信息,包括簇是否被使用、文件下一个簇的编号、是否文件结尾等。FAT文件系统有FAT12、FAT16、FAT32等多种格式,其中,12、16、32表示对应格式中FAT表项的字节数。FAT文件系统支持多种介质,特别在可移动存储介质(U盘、SD卡、移动硬盘等)上广泛使用,使嵌入式设备和Windows、Linux等桌面系统保持很好的兼容性,方便用户管理操作文件。 + +OpenHarmony内核支持FAT12、FAT16与FAT32三种格式的FAT文件系统,具有代码量小、资源占用小、可裁切、支持多种物理介质等特性,并且与Windows、Linux等系统保持兼容,支持多设备、多分区识别等功能。OpenHarmony内核支持硬盘多分区,可以在主分区以及逻辑分区上创建FAT文件系统。 + +## 开发指导 + +### 驱动适配 + +FAT文件系统的使用需要底层MMC相关驱动的支持。在一个带MMC存储设备的板子上运行FATFS,需要: + +1、适配板端EMMC驱动,实现disk\_status、disk\_initialize、disk\_read、disk\_write、disk\_ioctl接口; + +2、新增fs\_config.h文件,配置FS\_MAX\_SS(存储设备最大sector大小)、FF\_VOLUME\_STRS(分区名)等信息,例如: + +``` +#define FF_VOLUME_STRS "system", "inner", "update", "user" +#define FS_MAX_SS 512 +#define FAT_MAX_OPEN_FILES 50 +``` + +### 开发流程 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- FATFS文件与目录操作: +> - 单个文件大小不超过4G。 +> - 支持同时打开的文件数最大为FAT\_MAX\_OPEN\_FILES,文件夹数最大为FAT\_MAX\_OPEN\_DIRS。 +> - 暂不支持根目录管理,文件/目录名均以分区名开头,例如“user/testfile”就是在“user”分区下名为“testfile”的文件或目录。 +> - 若需要同时多次打开同一文件,必须全部使用只读方式(O\_RDONLY)。以可写方式(O\_RDWR、O\_WRONLY等)只能打开一次。 +> - 读写指针未分离,例如以O\_APPEND(追加写)方式打开文件后,读指针也在文件尾,从头读文件前需要用户手动置位。 +> - 暂不支持文件与目录的权限管理。 +> - stat及fstat接口暂不支持查询修改时间、创建时间和最后访问时间。微软FAT协议不支持1980年以前的时间。 +>- FATFS分区挂载与卸载: +> - 支持以只读属性挂载分区。当mount函数的入参为MS\_RDONLY时,所有的带有写入的接口,如write、mkdir、unlink,以及非O\_RDONLY属性的open,将均被拒绝。 +> - mount支持通过MS\_REMOUNT标记修改已挂载分区的权限。 +> - 在umount操作前,需确保所有目录及文件全部关闭。 +> - umount2支持通过MNT\_FORCE参数强制关闭所有文件与文件夹并umount,但可能造成数据丢失,请谨慎使用。 +>- FATFS支持重新划分存储设备分区、格式化分区,对应接口为fatfs\_fdisk与fatfs\_format: +> - 在fatfs\_format操作之前,若需要格式化的分区已挂载,需确保分区中的所有目录及文件全部关闭,并且分区umount。 +> - 在fatfs\_fdisk操作前,需要该设备中的所有分区均已umount。 +> - fatfs\_fdisk与fatfs\_format会造成设备数据丢失,请谨慎使用。 + +### 编程实例 + +### 实例描述 + +本实例实现以下功能: + +1. 创建目录“user/test” +2. 在“user/test”目录下创建文件“file.txt” +3. 在文件起始位置写入“Hello OpenHarmony!” +4. 将文件内容刷入设备中 +5. 设置偏移到文件起始位置 +6. 读取文件内容 +7. 关闭文件 +8. 删除文件 +9. 删除目录 + +### 示例代码 + +前提条件: + +- 系统已将MMC设备分区挂载到user目录 + +代码实现如下: + +``` +#include +#include +#include "sys/stat.h" +#include "fcntl.h" +#include "unistd.h" + +#define LOS_OK 0 +#define LOS_NOK -1 + +int FatfsTest(void) +{ + int ret; + int fd = -1; + ssize_t len; + off_t off; + char dirName[20] = "user/test"; + char fileName[20] = "user/test/file.txt"; + char writeBuf[20] = "Hello OpenHarmony!"; + char readBuf[20] = {0}; + + /* 创建目录“user/test” */ + ret = mkdir(dirName, 0777); + if (ret != LOS_OK) { + printf("mkdir failed.\n"); + return LOS_NOK; + } + + /* 创建可读写文件"user/test/file.txt" */ + fd = open(fileName, O_RDWR | O_CREAT, 0777); + if (fd < 0) { + printf("open file failed.\n"); + return LOS_NOK; + } + + /* 将writeBuf中的内容写入文件 */ + len = write(fd, writeBuf, strlen(writeBuf)); + if (len != strlen(writeBuf)) { + printf("write file failed.\n"); + return LOS_NOK; + } + + /* 将文件内容刷入存储设备中 */ + ret = fsync(fd); + if (ret != LOS_OK) { + printf("fsync failed.\n"); + return LOS_NOK; + } + + /* 将读写指针偏移至文件头 */ + off = lseek(fd, 0, SEEK_SET); + if (off != 0) { + printf("lseek failed.\n"); + return LOS_NOK; + } + + /* 将文件内容读出至readBuf中,读取长度为readBuf大小 */ + len = read(fd, readBuf, sizeof(readBuf)); + if (len != strlen(writeBuf)) { + printf("read file failed.\n"); + return LOS_NOK; + } + printf("%s\n", readBuf); + + /* 关闭文件 */ + ret = close(fd); + if (ret != LOS_OK) { + printf("close failed.\n"); + return LOS_NOK; + } + + /* 删除文件"user/test/file.txt" */ + ret = unlink(fileName); + if (ret != LOS_OK) { + printf("unlink failed.\n"); + return LOS_NOK; + } + + /* 删除目录“user/test” */ + ret = rmdir(dirName); + if (ret != LOS_OK) { + printf("rmdir failed.\n"); + return LOS_NOK; + } + + return LOS_OK; +} +``` + +### 结果验证 + +编译运行得到的结果为: + +``` +Hello OpenHarmony! +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..17423ee5c40ff14e3d771ae1459055e49c1b52f8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-basic.md @@ -0,0 +1,72 @@ +# 基本概念 + +- [运行机制](#section10284121317365) + - [日志方式](#section13804114513361) + - [Cow机制](#section172771130193610) + - [LittleFS掉电保护](#section42941021173614) + + +LittleFS主要用在微控制器和Flash上,是一种嵌入式文件系统,具有掉电恢复、擦写均衡、节省ROM/RAM空间等特点。 + +## 运行机制 + +最经典的掉电保护方法有两种,一种是使用日志,一种是通过COW方式。LittleFS结合了两种方法,并优化了两种方案的缺点,提供了一套掉电保护策略 + +### 日志方式 + +**图 1** 日志方式示意图 +![](figure/日志方式示意图.png "日志方式示意图") + +具体步骤为: + +1. 写入数据之前,先在日志区存储开始标志,记录要写入的数据位置和大小; +2. 待写入的数据写入日志区; +3. 待写入的数据写入数据区; +4. 写入完成之后,在日志区记录结束标志。 + +模拟掉电场景: + +1. 步骤1完成,步骤2没有完成;重启之后,保持原来的数据,日志无效; +2. 步骤1,2完成了,步骤3没有完成,尝试把步骤2的数据写入到数据区; +3. 步骤1,2,3完成了,步骤4没有完成,同样尝试把步骤2的数据写入到数据区; + +### Cow机制 + +**图 2** Cow机制示意图 +![](figure/Cow机制示意图.png "Cow机制示意图") + +具体步骤为: + +1. 想更新节点F的数据,先申请一个新的节点,把F的旧数据拷贝过去,然后更新新的数据; +2. 把父节点的指针指向新的节点,去掉旧节点的指针。 + +模拟掉电场景: + +步骤1完成了,步骤2没有完成,则使用旧的数据,新的节点变成孤儿节点。 + +### LittleFS掉电保护 + +LittleFS结合了日志方式和COW机制两种方式进行掉电保护,并且优化了两种方案。 + +文件系统有三要素,超级块,inode,以及数据,对应LittleFS来说,它把超级块以及inode通过日志的方式存储,两种采用统一的存储结构,后文称两者为元数据;普通数据则采用cow的方式存储,采用czt逆序链表的方式。 + +![](figure/zh-cn_image_0000001124307264.png) + +**元数据的存储** + +元数据(对应root,dir)采用双block的方式存储,互为备份,每个block都有一个revision序号,值越大,表示block的数据越新,每个block默认可以存储最多0xff个文件的数据,如果超过这个值,则需要compact(压缩)。 + +Compact是干什么呢? 即当数据的大小大于某个值的时候,把数据整合,剔除同一个id的旧的数据,然后写入到备份block里面。如图所示: + +**图 3** 元数据存储示意图 +![](figure/元数据存储示意图.png "元数据存储示意图") + +**普通数据的存储** + +LittleFS的数据采用链表的方式逆向管理。 + +![](figure/zh-cn_image_0000001132085260.png) + +1. 采用逆向的指针,这样常规的追加数据,不需要额外的开销来重新建立所有的索引; +2. 每个偶数block有多个指针,指向更远的数据,这样可以在检索的时候加快速度。 + diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-22.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-guide.md similarity index 100% rename from "zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-22.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit-guide.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md new file mode 100644 index 0000000000000000000000000000000000000000..b0ffac3d6795718298342eb939196b45636ad6d0 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file-lit.md @@ -0,0 +1,7 @@ +# LittleFS + +- **[基本概念](kernel-lite-mini-extend-file-lit-basic.md)** + +- **[开发指导](kernel-lite-mini-extend-file-lit-guide.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md new file mode 100644 index 0000000000000000000000000000000000000000..c7ee5fabfdca2b92b4cba55758bf298edb554a72 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-file.md @@ -0,0 +1,204 @@ +# 文件系统 + +当前支持的文件系统有FATFS与LittleFS,支持的功能如下表所示: + +**表 1** ****功能列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

FATFS

+

LITTELFS

+

文件操作

+

open

+

打开文件

+

支持

+

支持

+

close

+

关闭文件

+

支持

+

支持

+

read

+

读取文件内容

+

支持

+

支持

+

write

+

往文件写入内容

+

支持

+

支持

+

lseek

+

设置文件偏移位置

+

支持

+

支持

+

unlink

+

删除文件

+

支持

+

支持

+

rename

+

重命名文件

+

支持

+

支持

+

fstat

+

通过文件句柄获取文件信息

+

支持

+

支持

+

stat

+

通过文件路径名获取文件信息

+

支持

+

支持

+

fsync

+

文件内容刷入存储设备

+

支持

+

支持

+

目录操作

+

mkdir

+

创建目录

+

支持

+

支持

+

opendir

+

打开目录

+

支持

+

支持

+

readdir

+

读取目录项内容

+

支持

+

支持

+

closedir

+

关闭目录

+

支持

+

支持

+

rmdir

+

删除目录

+

支持

+

支持

+

分区操作

+

mount

+

分区挂载

+

支持

+

支持

+

umount

+

分区卸载

+

支持

+

支持

+

umount2

+

分区卸载,可通过MNT_FORCE参数进行强制卸载

+

支持

+

不支持

+

statfs

+

获取分区信息

+

支持

+

不支持

+
+ +- **[FAT](kernel-lite-mini-extend-file-fat.md)** + +- **[LittleFS](kernel-lite-mini-extend-file-lit.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md new file mode 100644 index 0000000000000000000000000000000000000000..c0b1ed529142bba08729d4cc769f47554b4136ec --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend-support.md @@ -0,0 +1,86 @@ +# C++支持 + +- [基本概念](#section11374125415814) + - [运行机制](#section125251720195) + +- [开发指导](#section166302407911) + - [接口说明](#section1881825119919) + - [开发流程](#section76371145108) + - [编程实例](#section994427141111) + + +## 基本概念 + +C++作为目前使用最广泛的编程语言之一,支持类、封装、重载等特性,是在C语言基础上开发的一种面向对象的编程语言。 + +### 运行机制 + +C++代码的识别主要由编译器支持,系统主要对全局对象进行构造函数调用,进行初始化操作。 + +## 开发指导 + +### 接口说明 + +**表 1** C++支持接口 + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

使用C++特性的前置条件

+

LOS_CppSystemInit

+

C++构造函数初始化

+
+ +### 开发流程 + +使用C++特性之前,需要调用函数LOS\_CppSystemInit,实现C++构造函数初始化,其中被初始化的构造函数存在init\_array这个段中,段区间通过变量\_\_init\_array\_start\_\_、\_\_init\_array\_end\_\_传递。 + +**表 2** 参数说明 + + + + + + + + + + + + + +

参数

+

参数说明

+

__init_array_start__

+

init_array段起始位置

+

__init_array_end__

+

init_array段结束位置

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>调用该函数时,一定要在c++业务前。另外部分与系统资源强相关的类或接口,如std::thread,std::mutex等,在三方编译器使用的c库非musl c时,存在兼容性问题,不建议使用。 + +### 编程实例 + +``` +void app_init(void) +{ +...... +/* 启动阶段C++初始化 */ +LOS_CppSystemInit((UINTPTR)&__init_array_start__, (UINTPTR)&__init_array_end__); +/* C++业务 */ +...... +} +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-extend.md b/zh-cn/device-dev/kernel/kernel-lite-mini-extend.md new file mode 100644 index 0000000000000000000000000000000000000000..1d413abe902d5f6d590db74545381a6349dc1c23 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-extend.md @@ -0,0 +1,9 @@ +# 扩展组件 + +- **[C++支持](kernel-lite-mini-extend-support.md)** + +- **[CPU占用率](kernel-lite-mini-extend-cpup.md)** + +- **[文件系统](kernel-lite-mini-extend-file.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md new file mode 100644 index 0000000000000000000000000000000000000000..20a2b532d3a54324a02c9dd10fb8f3fdfed7487e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-cet.md @@ -0,0 +1,85 @@ +# 踩内存检测 + +- [基础概念](#section17368154517335) +- [功能配置](#section4696190123420) +- [开发指导](#section672362973417) + - [开发流程](#section026014863416) + - [编程实例](#section186311302356) + - [示例代码](#section12709533354) + - [结果验证](#section81214126369) + + +## 基础概念 + +踩内存检测机制作为内核的可选功能,用于检测动态内存池的完整性。通过该机制,可以及时发现内存池是否发生了踩内存问题,并给出错误信息,便于及时发现系统问题,提高问题解决效率,降低问题定位成本。 + +## 功能配置 + +LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 + +1. 开启这个功能,每次申请内存,会实时检测内存池的完整性。 +2. 如果不开启该功能,也可以调用LOS\_MemIntegrityCheck接口检测,但是每次申请内存时,不会实时检测内存完整性,而且由于节点头没有魔鬼数字(开启时才有,省内存),检测的准确性也会相应降低,但对于系统的性能没有影响,故根据实际情况开关该功能。 + +由于该功能只会检测出哪个内存节点被破坏了,并给出前节点信息(因为内存分布是连续的,当前节点最有可能被前节点破坏)。如果要进一步确认前节点在哪里申请的,需开启内存泄漏检测功能,通过LR记录,辅助定位。 + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>开启该功能,节点头多了魔鬼数字字段,会增大节点头大小。由于实时检测完整性,故性能影响较大;若性能敏感的场景,可以不开启该功能,使用LOS\_MemIntegrityCheck接口检测。 + +## 开发指导 + +### 开发流程 + +通过调用LOS\_MemIntegrityCheck接口检测内存池是否发生了踩内存,如果没有踩内存问题,那么接口返回0且没有log输出;如果存在踩内存问题,那么会输出相关log,详见下文编程实例的结果输出。 + +### 编程实例 + +本实例实现如下功能: + +1. 申请两个物理上连续的内存块; +2. 通过memset构造越界访问,踩到下个节点的头4个字节; +3. 调用LOS\_MemIntegrityCheck检测是否发生踩内存。 + +### 示例代码 + +代码实现如下: + +``` +#include +#include +#include "los_memory.h" +#include "los_config.h" + +void MemIntegrityTest(void) +{ + /* 申请两个物理连续的内存块 */ + void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + /* 第一个节点内存块大小是8字节,那么12字节的清零,会踩到第二个内存节点的节点头,构造踩内存场景 */ + memset(ptr1, 0, 8 + 4); + LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR); +} +``` + +### 结果验证 + +编译运行输出log如下: + +``` +[ERR][OsMemMagicCheckPrint], 2028, memory check error! +memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ + + broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 +/* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ + + broken node head LR info: /* 节点的LR信息需要开启内存检测功能才有有效输出 */ + LR[0]:0x0800414e + LR[1]:0x08000cc2 + LR[2]:0x00000000 + + pre node head LR info: /* 通过LR信息,可以在汇编文件中查找前节点是哪里申请,然后排查其使用的准确性 */ + LR[0]:0x08004144 + LR[1]:0x08000cc2 + LR[2]:0x00000000 +[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* 被破坏节点和其前节点的地址 */ +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md new file mode 100644 index 0000000000000000000000000000000000000000..7f49df4fc87257c46fbfdcdaa9dad954d1962484 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-det.md @@ -0,0 +1,128 @@ +# 内存泄漏检测 + +- [基础概念](#section1026719436293) +- [功能配置](#section13991354162914) +- [开发指导](#section95828159308) + - [开发流程](#section369844416304) + - [编程实例](#section460801313313) + - [示例代码](#section96539275311) + - [结果验证](#section20527343183119) + + +## 基础概念 + +内存泄漏检测机制作为内核的可选功能,用于辅助定位动态内存泄漏问题。开启该功能,动态内存机制会自动记录申请内存时的函数调用关系(下文简称LR)。如果出现泄漏,就可以利用这些记录的信息,找到内存申请的地方,方便进一步确认。 + +## 功能配置 + +1. LOSCFG\_MEM\_LEAKCHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 +2. LOSCFG\_MEM\_RECORD\_LR\_CNT:记录的LR层数,默认3层;每层LR消耗sizeof\(void \*\)字节数的内存。 +3. LOSCFG\_MEM\_OMIT\_LR\_CNT:忽略的LR层数,默认4层,即从调用LOS\_MemAlloc的函数开始记录,可根据实际情况调整。为啥需要这个配置?有3点原因如下: + - LOS\_MemAlloc接口内部也有函数调用; + - 外部可能对LOS\_MemAlloc接口有封装; + - LOSCFG\_MEM\_RECORD\_LR\_CNT 配置的LR层数有限; + + +正确配置这个宏,将无效的LR层数忽略,就可以记录有效的LR层数,节省内存消耗。 + +## 开发指导 + +### 开发流程 + +该调测功能可以分析关键的代码逻辑中是否存在内存泄漏。开启这个功能,每次申请内存时,会记录LR信息。在需要检测的代码段前后,调用LOS\_MemUsedNodeShow接口,每次都会打印指定内存池已使用的全部节点信息,对比前后两次的节点信息,新增的节点信息就是疑似泄漏的内存节点。通过LR,可以找到具体申请的代码位置,进一步确认是否泄漏。 + +调用LOS\_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3\~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 + +``` +node size LR[0] LR[1] LR[2] +0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 +0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4 +0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4 +0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0 +0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0 +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>开启内存检测会影响内存申请的性能,且每个内存节点都会记录LR地址,内存开销也加大。 + +### 编程实例 + +本实例实现如下功能:构建内存泄漏代码段。 + +1. 调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; +2. 申请内存,但没有释放,模拟内存泄漏; +3. 再次调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; +4. 将两次log进行对比,得出泄漏的节点信息; +5. 通过LR地址,找出泄漏的代码位置; + +### 示例代码 + +代码实现如下: + +``` +#include +#include +#include "los_memory.h" +#include "los_config.h" + +void MemLeakTest(void) +{ + LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); + void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); + LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); +} +``` + +### 结果验证 + +编译运行输出log如下: + +``` +node size LR[0] LR[1] LR[2] +0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc +0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc +0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e +0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a +0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 + +node size LR[0] LR[1] LR[2] +0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc +0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc +0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e +0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a +0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 +0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 +0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +``` + +对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: + +``` +0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 +0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 +``` + +部分汇编文件如下: + +``` + MemLeakTest: + 0x80041d4: 0xb510 PUSH {R4, LR} + 0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart + 0x80041d8: 0x0020 MOVS R0, R4 + 0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a + 0x80041de: 0x2108 MOVS R1, #8 + 0x80041e0: 0x0020 MOVS R0, R4 + 0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998 + 0x80041e6: 0x2108 MOVS R1, #8 + 0x80041e8: 0x0020 MOVS R0, R4 + 0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998 + 0x80041ee: 0x0020 MOVS R0, R4 + 0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a + 0x80041f4: 0xbd10 POP {R4, PC} + 0x80041f6: 0x0000 MOVS R0, R0 +``` + +其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md new file mode 100644 index 0000000000000000000000000000000000000000..0dd4f930425a171933e8dafe2f690804111ff257 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug-mes.md @@ -0,0 +1,107 @@ +# 内存信息统计 + +- [基础概念](#section52691565235) +- [功能配置](#section470611682411) +- [开发指导](#section9368374243) + - [开发流程](#section679912407257) + - [编程实例](#section1025453412611) + - [示例代码](#section165277971315) + - [结果验证](#section3460102414271) + + +## 基础概念 + +内存信息包括内存池大小、内存使用量、剩余内存大小、最大空闲内存、内存水线、内存节点数统计、碎片率等。 + +- 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小; + +- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-最大空闲内存块大小/剩余内存大小)来度量; + +- 其他参数:通过调用接口(详见[内存管理](kernel-lite-mini-basic-memory.md)章节接口说明),扫描内存池的节点信息,统计出相关信息。 + +## 功能配置 + +LOSCFG\_MEM\_WATERLINE:开关宏,默认打开;若关闭这个功能,在target\_config.h中将这个宏定义为0。如需获取内存水线,需要打开该配置。 + +## 开发指导 + +### 开发流程 + +关键结构体介绍: + +``` +typedef struct { + UINT32 totalUsedSize; // 内存池的内存使用量 + UINT32 totalFreeSize; // 内存池的剩余内存大小 + UINT32 maxFreeNodeSize; // 内存池的最大空闲内存块大小 + UINT32 usedNodeNum; // 内存池的非空闲内存块个数 + UINT32 freeNodeNum; // 内存池的空闲内存块个数 +#if (LOSCFG_MEM_WATERLINE == 1) // 默认打开,如需关闭,在target_config.h中将该宏设置为0 + UINT32 usageWaterLine; // 内存池的水线值 +#endif +} LOS_MEM_POOL_STATUS; +``` + +- 内存水线获取:调用LOS\_MemInfoGet接口,第1个参数是内存池首地址,第2个参数是LOS\_MEM\_POOL\_STATUS类型的句柄,其中字段usageWaterLine即水线值。 + +- 内存碎片率计算:同样调用LOS\_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。 + +### 编程实例 + +本实例实现如下功能: + +1.创建一个监控线程,用于获取内存池的信息; + +2.调用LOS\_MemInfoGet接口,获取内存池的基础信息; + +3.利用公式算出使用率及碎片率。 + +### 示例代码 + +代码实现如下: + +``` +#include +#include +#include "los_task.h" +#include "los_memory.h" +#include "los_config.h" + +void MemInfoTaskFunc(void) +{ + LOS_MEM_POOL_STATUS poolStatus = {0}; + LOS_MemInfoGet(pool, &poolStatus); + /* 算出内存池当前的碎片率百分比 */ + unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize; + /* 算出内存池当前的使用率百分比 */ + unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool); + printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, + poolStatus.totalFreeSize, poolStatus.usageWaterLine); +} + +int MemTest(void) +{ + unsigned int ret; + unsigned int taskID; + TSK_INIT_PARAM_S taskStatus = {0}; + taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc; + taskStatus.uwStackSize = 0x1000; + taskStatus.pcName = "memInfo"; + taskStatus.usTaskPrio = 10; + ret = LOS_TaskCreate(&taskID, &taskStatus); + if (ret != LOS_OK) { + printf("task create failed\n"); + return -1; + } + return 0; +} +``` + +### 结果验证 + +编译运行输出的结果如下: + +``` +usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md new file mode 100644 index 0000000000000000000000000000000000000000..0c4474cd15eb7b42235cdcc139be9a8f6dccb6b7 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-debug.md @@ -0,0 +1,11 @@ +# 内存调测 + +内存调测方法旨在辅助定位动态内存相关问题,提供了基础的动态内存池信息统计手段,向用户呈现内存池水线、碎片率等信息;提供了内存泄漏检测手段,方便用户准确定位存在内存泄漏的代码行,也可以辅助分析系统各个模块内存的使用情况;提供了踩内存检测手段,可以辅助定位越界踩内存的场景。 + +- **[内存信息统计](kernel-lite-mini-inner-debug-mes.md)** + +- **[内存泄漏检测](kernel-lite-mini-inner-debug-det.md)** + +- **[踩内存检测](kernel-lite-mini-inner-debug-cet.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md new file mode 100644 index 0000000000000000000000000000000000000000..5828d645f139907f9d8763226b3f4dbb269b2965 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-exception.md @@ -0,0 +1,329 @@ +# 异常调测 + +- [基本概念](#section2741911123412) +- [运行机制](#section16618124317346) +- [接口说明](#section16111931351) +- [使用指导](#section16317163520350) + - [开发流程](#section13457839133618) + - [定位流程](#section197332323815) + + +## 基本概念 + +OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析问题。异常接管是操作系统对运行期间发生的异常情况进行处理的一系列动作,例如打印异常发生时异常类型、发生异常时的系统状态、当前函数的调用栈信息、CPU现场信息、任务调用堆栈等信息。 + +## 运行机制 + +栈帧用于保存函数调用过程中的函数参数、变量、返回值等信息。调用函数时,会创建子函数的栈帧,同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。LR链接寄存器(Link Register)指向函数的返回地址,FP帧指针寄存器(Frame Point)指向当前函数的父函数的栈帧起始地址。利用FP寄存器可以得到父函数的栈帧,从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。 + +当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的栈帧中的LR链接寄存器、FP帧指针寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。 + +堆栈分析原理如下图所示,实际堆栈信息根据不同CPU架构有所差异,此处仅做示意。 + +**图 1** 堆栈分析原理示意图 +![](figure/堆栈分析原理示意图.png "堆栈分析原理示意图") + +图中不同颜色的寄存器表示不同的函数。可以看到函数调用过程中,寄存器的保存。通过FP寄存器,栈回溯到异常函数的父函数,继续按照规律对栈进行解析,推出函数调用关系,方便用户定位问题。 + +## 接口说明 + +OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详细信息可以查看API参考。 + +**表 1** 回溯栈模块接口 + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

回溯栈接口

+

LOS_BackTrace

+

打印调用处的函数调用栈关系。

+

LOS_RecordLR

+

在无法打印的场景,用该接口获取调用处的函数调用栈关系。

+
+ +## 使用指导 + +### 开发流程 + +开启异常调测的典型流程如下: + +1. 配置异常接管相关宏。 + + 需要在target\_config.h头文件中修改配置: + + + + + + + + + + + + + + + + +

配置项

+

含义

+

设置值

+

LOSCFG_BACKTRACE_DEPTH

+

函数调用栈深度,默认15层

+

15

+

LOSCFG_BACKTRACE_TYPE

+

回溯栈类型:

+

0:表示关闭该功能;

+

1:表示支持Cortex-m系列硬件的函数调用栈解析;

+

2:表示用于Risc-v系列硬件的函数调用栈解析;

+

根据工具链类型设置1或2

+
+ + +1. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。 + + 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: + + ``` + #include + #include "los_config.h" + #include "los_interrupt.h" + #include "los_task.h" + + UINT32 g_taskExcId; + #define TSK_PRIOR 4 + + /* 模拟异常函数 */ + + UINT32 Get_Result_Exception_0(UINT16 dividend){ + UINT32 divisor = 0; + UINT32 result = dividend / divisor; + return result; + } + + UINT32 Get_Result_Exception_1(UINT16 dividend){ + return Get_Result_Exception_0(dividend); + } + + UINT32 Get_Result_Exception_2(UINT16 dividend){ + return Get_Result_Exception_1(dividend); + } + + UINT32 Example_Exc(VOID) + { + UINT32 ret; + + printf("Enter Example_Exc Handler.\r\n"); + + /* 模拟函数调用 */ + ret = Get_Result_Exception_2(TSK_PRIOR); + printf("Divided result =%u.\r\n", ret); + + printf("Exit Example_Exc Handler.\r\n"); + return ret; + } + + + /* 任务测试入口函数,创建一个会发生异常的任务 */ + UINT32 Example_Exc_Entry(VOID) + { + UINT32 ret; + TSK_INIT_PARAM_S initParam; + + /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ + LOS_TaskLock(); + + printf("LOS_TaskLock() Success!\r\n"); + + initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Exc; + initParam.usTaskPrio = TSK_PRIOR; + initParam.pcName = "Example_Exc"; + initParam.uwStackSize = LOSCFG_SECURE_STACK_DEFAULT_SIZE; + /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ + ret = LOS_TaskCreate(&g_taskExcId, &initParam); + if (ret != LOS_OK) { + LOS_TaskUnlock(); + + printf("Example_Exc create Failed!\r\n"); + return LOS_NOK; + } + + printf("Example_Exc create Success!\r\n"); + + /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ + LOS_TaskUnlock(); + + return LOS_OK; + } + ``` + + +1. 上述代码串口终端输出异常信息如下: + + ``` + entering kernel init... + LOS_TaskLock() Success! + Example_Exc create Success! + Entering scheduler + Enter Example_Exc Handler. + *************Exception Information************** + Type = 10 + ThrdPid = 4 + Phase = exc in task + FaultAddr = 0xabababab + Current task info: + Task name = Example_Exc + Task ID = 4 + Task SP = 0x200051ac + Task ST = 0x20004ff0 + Task SS = 0x200 + Exception reg dump: + PC = 0x80037da + LR = 0x80037fe + SP = 0x20005190 + R0 = 0x4 + R1 = 0x40 + R2 = 0x4 + R3 = 0x0 + R4 = 0x4040404 + R5 = 0x5050505 + R6 = 0x6060606 + R7 = 0x20005190 + R8 = 0x8080808 + R9 = 0x9090909 + R10 = 0x10101010 + R11 = 0x11111111 + R12 = 0x12121212 + PriMask = 0x0 + xPSR = 0x41000000 + ----- backtrace start ----- + backtrace 0 -- lr = 0x800381a + backtrace 1 -- lr = 0x8003836 + backtrace 2 -- lr = 0x8005a4e + backtrace 3 -- lr = 0x8000494 + backtrace 4 -- lr = 0x8008620 + backtrace 5 -- lr = 0x800282c + backtrace 6 -- lr = 0x80008a0 + backtrace 7 -- lr = 0x80099f8 + backtrace 8 -- lr = 0x800a01a + backtrace 9 -- lr = 0x800282c + backtrace 10 -- lr = 0x80008a0 + backtrace 11 -- lr = 0x80099f8 + backtrace 12 -- lr = 0x8009bf0 + backtrace 13 -- lr = 0x8009c52 + backtrace 14 -- lr = 0x80099aa + ----- backtrace end ----- + + TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID name + --- -------- -------- --------- ---------- ---------- ---------- --------- ----- ---- + 0 0 Pend 0x2d0 0x104 0x200029bc 0x200027f0 0x0 0xffff Swt_Task + 1 31 Ready 0x500 0x44 0x20002f84 0x20002ac8 0x0 0xffff IdleCore000 + 2 6 Ready 0x1000 0x44 0x20003f94 0x20002fd8 0x0 0xffff TaskSampleEntry1 + 3 7 Ready 0x1000 0x44 0x20004f9c 0x20003fe0 0x0 0xffff TaskSampleEntry2 + 4 4 Running 0x200 0xec 0x200051ac 0x20004ff0 0x0 0xffff Example_Exc + + OS exception NVIC dump: + interrupt enable register, base address: 0xe000e100, size: 0x20 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt pending register, base address: 0xe000e200, size: 0x20 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt active register, base address: 0xe000e300, size: 0x20 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt priority register, base address: 0xe000e400, size: 0xf0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 + interrupt exception register, base address: 0xe000ed18, size: 0xc + 0x0 0x0 0xf0f00000 + interrupt shcsr register, base address: 0xe000ed24, size: 0x4 + 0x70008 + interrupt control register, base address: 0xe000ed04, size: 0x4 + 0x400f806 + + memory pools check: + system heap memcheck over, all passed! + memory pool check end! + ``` + + +### 定位流程 + +异常接管一般的定位步骤如下: + +1. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为: + + ``` + arm-none-eabi-objdump -S -l XXX.elf + ``` + + +1. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。 + + PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x80037da,找到当前CPU正在执行的指令行,反汇编如下所示: + + ``` + UINT32 Get_Result_Exception_0(UINT16 dividend){ + 80037c8: b480 push {r7} + 80037ca: b085 sub sp, #20 + 80037cc: af00 add r7, sp, #0 + 80037ce: 4603 mov r3, r0 + 80037d0: 80fb strh r3, [r7, #6] + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:10 + UINT32 divisor = 0; + 80037d2: 2300 movs r3, #0 + 80037d4: 60fb str r3, [r7, #12] + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:11 + UINT32 result = dividend / divisor; + 80037d6: 88fa ldrh r2, [r7, #6] + 80037d8: 68fb ldr r3, [r7, #12] + 80037da: fbb2 f3f3 udiv r3, r2, r3 + 80037de: 60bb str r3, [r7, #8] + ``` + + +1. 可以看到: + 1. 异常时CPU正在执行的指令是udiv r3, r2, r3,其中r3取值为0,导致发生除零异常。 + 2. 异常发生在函数Get\_Result\_Exception\_0中。 + +2. 根据LR值查找异常函数的父函数。 + + 包含LR值0x80037fe的反汇编如下所示: + + ``` + 080037ec : + Get_Result_Exception_1(): + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:15 + UINT32 Get_Result_Exception_1(UINT16 dividend){ + 80037ec: b580 push {r7, lr} + 80037ee: b082 sub sp, #8 + 80037f0: af00 add r7, sp, #0 + 80037f2: 4603 mov r3, r0 + 80037f4: 80fb strh r3, [r7, #6] + kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:16 + return Get_Result_Exception_0(dividend); + 80037f6: 88fb ldrh r3, [r7, #6] + 80037f8: 4618 mov r0, r3 + 80037fa: f7ff ffe5 bl 80037c8 + 80037fe: 4603 mov r3, r0 + ``` + + +1. LR值80037fe上一行是bl 80037c8 ,此处调用了异常函数,调用异常函数的父函数为Get\_Result\_Exception\_1\(\)。 +2. 重复步骤3,解析异常信息中backtrace start至backtrace end之间的LR值,得到调用产生异常的函数调用栈关系,找到异常原因。 + diff --git "a/zh-cn/device-dev/kernel/Trace\350\260\203\346\265\213.md" b/zh-cn/device-dev/kernel/kernel-lite-mini-inner-trace.md similarity index 100% rename from "zh-cn/device-dev/kernel/Trace\350\260\203\346\265\213.md" rename to zh-cn/device-dev/kernel/kernel-lite-mini-inner-trace.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-inner.md b/zh-cn/device-dev/kernel/kernel-lite-mini-inner.md new file mode 100644 index 0000000000000000000000000000000000000000..63cd8f58de79e139b236f5ce8c56b2ca5df8c260 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-inner.md @@ -0,0 +1,9 @@ +# 内核调测 + +- **[内存调测](kernel-lite-mini-inner-debug.md)** + +- **[异常调测](kernel-lite-mini-inner-exception.md)** + +- **[Trace调测](kernel-lite-mini-inner-trace.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-m.md b/zh-cn/device-dev/kernel/kernel-lite-mini-m.md new file mode 100644 index 0000000000000000000000000000000000000000..3548ae04b61c2ea2c20c5f024694568f9099ea74 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-m.md @@ -0,0 +1,62 @@ +# 内核概述 + +- [内核简介](#section1429342661510) + - [cpu体系架构支持](#section48891456112819) + - [运行机制](#section4599142312817) + + +## 内核简介 + +OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。其代码结构简单,主要包括内核最小功能集、内核抽象层、可选组件以及工程目录等。OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中Kernel Arch模块属于硬件相关层,该模块按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;Components等其他模块属于硬件无关层,其中Kernel Task等内核模块提供基础能力,Components模块提供网络、文件系统等组件能力,Utils模块提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。 + +**图 1** 内核架构图 +![](figure/内核架构图.png "内核架构图") + +### cpu体系架构支持 + +CPU体系架构分为通用架构定义和特定架构定义两层,通用架构定义层为所有体系架构都需要支持和实现的接口,特定架构定义层为特定体系架构所特有的部分。在新增一个体系架构的时候,必须需要实现通用架构定义层,如果该体系架构还有特有的功能,可以在特定架构定义层来实现。 + +**表 1** CPU体系架构规则 + + + + + + + + + + + + + + + + + + + + +

规则

+

通用体系架构层

+

特定体系架构层

+

头文件位置

+

kernel/arch/include

+

kernel/arch/<arch>/<arch>/<toolchain>/

+

头文件命名

+

los_<function>.h

+

los_arch_<function>.h

+

函数命名

+

Halxxxx

+

Halxxxx

+
+ +LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M33、RISC-V等主流架构,如果需要扩展CPU体系架构,请参考[芯片架构适配点](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0.md#%E8%8A%AF%E7%89%87%E6%9E%B6%E6%9E%84%E9%80%82%E9%85%8D%E7%82%B9)。 + +### 运行机制 + +在开发板配置文件target\_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程图。 + +**图 2** 内核启动流程 +![](figure/内核启动流程.png "内核启动流程") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini-start.md b/zh-cn/device-dev/kernel/kernel-lite-mini-start.md new file mode 100644 index 0000000000000000000000000000000000000000..13cd49841e858d07c4d6d15e197d2902b9183b51 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini-start.md @@ -0,0 +1,47 @@ +# 快速入门 + +- [搭建开发环境](#section157851447151716) +- [获取OpenHarmony源码](#section381985201816) +- [获取示例工程源码](#section204717216181) +- [编译运行](#section9772514181917) + +OpenHarmony LiteOS-M内核的编译构建系统是一个基于gn和ninja的组件化构建系统,支持按组件配置、裁剪和拼装,按需构建出定制化的产品。编译构建系统的详细信息可以参考[考编译构建概](../subsystems/subsys-build-mini-lite.md#section10958256161119)。本文主要介绍如何基于gn和ninja编译LiteOS-M工程。 + +## 搭建开发环境 + +在搭建各个开发板环境前,需要完成OpenHarmony系统基础环境搭建。系统基础环境主要是指OpenHarmony的编译环境和开发环境,详细介绍请参考官方站点[搭建系统基础环境](../quick-start/quickstart-lite-env-setup-des.md)。开发者需要根据环境搭建文档,完成下述软件的安装:Python3.7+、gn、ninja、hb。对于LiteOS-M内核,还需要安装ARM GCC编译工具链。 + +## 获取OpenHarmony源码 + +开发者需要在Linux服务器上通过Git克隆获取OpenHarmony最新源码,详细的源码获取方式,请见[源码获取](../get-code/sourcecode-acquire.md)。获取OpenHarmony完整仓代码后,假设克隆目录为\~/openHarmony。 + +## 获取示例工程源码 + +以开发板Nucleo-F767Zi为例,演示如何编译运行OpenHarmony LiteOS-M内核工程。在本地目录,执行下述命令克隆示例代码。 + +``` +git clone https://gitee.com/harylee/nucleo_f767zi.git +``` + +假设克隆到的代码目录为\~/nucleo\_f767zi。 执行如下命令把代码目录的device、vendor目录复制到openHarmony工程的相应目录。 + +``` +cp -r ~/nucleo_f767zi/device/st ~/openHarmony/device/st +cp -r ~/nucleo_f767zi/vendor/st ~/openHarmony/vendor/st +``` + +关于示例代码目录的说明,可以参考资料站点[板级目录规范](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0-0.md#section6204129143013)。如果需要自行移植开发板,请参考[板级系统移植](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E6%9D%BF%E7%BA%A7%E7%B3%BB%E7%BB%9F%E7%A7%BB%E6%A4%8D.md)。 + +## 编译运行 + +编译运行前,把交叉编译工具链bin目录配置到PATH环境变量中或者在device/st/nucleo\_f767zi/liteos\_m/config.gni文件中把board\_toolchain\_path配置项设置为交叉编译工具链bin目录。 在OpenHarmony根目录,执行hb set设置产品路径,选择nucleo\_f767zi产品,然后执行hb build开启编译。如下: + +``` +user@dev:~/OpenHarmony$ hb set +[OHOS INFO] Input code path: # 直接按回车,然后选择nucleo_f767zi产品即可 +OHOS Which product do you need? nucleo_f767zi@st +user@dev:~/OpenHarmony$ hb build +``` + +最终的镜像生成在\~/openHarmony/out/nucleo\_f767zi/目录中,通过STM32 ST-LINK Utility软件将镜像文件下载至单板查看运行效果。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-mini.md b/zh-cn/device-dev/kernel/kernel-lite-mini.md new file mode 100644 index 0000000000000000000000000000000000000000..f531579ddb9a8bb0962474d074255d56cd3f9958 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-mini.md @@ -0,0 +1,13 @@ +# 轻量系统内核 + +- **[内核概述](kernel-lite-mini-m.md)** + +- **[基础内核](kernel-lite-mini-basic.md)** + +- **[扩展组件](kernel-lite-mini-extend.md)** + +- **[内核调测](kernel-lite-mini-inner.md)** + +- **[附录](kernel-lite-mini-app.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-basic.md b/zh-cn/device-dev/kernel/kernel-lite-small-basic.md new file mode 100644 index 0000000000000000000000000000000000000000..d9cac957f9948081206b93faba73c481d99474e9 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-basic.md @@ -0,0 +1,11 @@ +# 基础内核 + +- **[进程](kernel-lite-small-process.md)** + +- **[线程](kernel-lite-small-thread.md)** + +- **[内存](kernel-lite-small-memory.md)** + +- **[网络](kernel-lite-small-net.md)** + + diff --git a/zh-cn/device-dev/kernel/FAT.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-fat.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/FAT.md rename to zh-cn/device-dev/kernel/kernel-lite-small-file-fat.md diff --git a/zh-cn/device-dev/kernel/JFFS2.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-jffs.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/JFFS2.md rename to zh-cn/device-dev/kernel/kernel-lite-small-file-jffs.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md new file mode 100644 index 0000000000000000000000000000000000000000..dec5a7023b1d9dcb34d1367fa7446129bfd76ee9 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-file-nfs.md @@ -0,0 +1,163 @@ +# NFS + +- [概述](#section18322139164413) +- [注意事项](#section532912331467) +- [开发指导](#section166873374711) + +## 概述 + +NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。因此,用户可以简单地将它看做是一个文件系统服务,在一定程度上相当于Windows环境下的共享文件夹。 + +NFS客户端用户,能够将网络远程的NFS服务端分享的目录挂载到本地端的机器中,运行程序和共享文件,但不占用当前的系统资源,所以,在本地端的机器看起来,远程服务端的目录就好像是自己的一个磁盘一样。 + +## 注意事项 + +- 当前NFS文件不支持权限控制,请在创建NFS目录和文件时使用777权限。 + +- 当前NFS文件不支读阻塞和写阻塞。 + +- 当前NFS文件不支持信号功能。 + +- 当前NFS文件系统mount路径长度(不包含IP的长度)不超过255个字符,超过时返回ENAMETOOLONG错误。 + +- 当前NFS文件支持的操作有:open, close, read, write, seek, dup, dup2, sync, opendir, closedir, readdir, readdir\_r, rewinddir, scandir, statfs, remove, unlink, mkdir, rmdir, rename, stat, stat64, seek64, mmap, mount, umount。 + +- 当前NFS支持TCP和UDP两种传输层协议,默认使用TCP。 + +- open打开一个文件,参数有O\_TRUNC时,必须同时拥有写的权限,才会将文件中的内容清空。 + +- 在文件未关闭的情况下,rename\(\)函数重命名A为B之后,不会改变文件fd。 + +- NFS功能目前处于beta测试阶段,可能存在功能不稳定的情况,建议您不要用于正式商用产品当中。 + + +## 开发指导 + +1. **搭建NFS服务器**。 + + 这里以Ubuntu操作系统为例,说明服务器端设置步骤。 + + 1. 安装NFS服务器软件。 + + 设置好Ubuntu系统的下载源,保证网络连接好的情况下执行: + + ``` + sudo apt-get install nfs-kernel-server + ``` + + 2. 创建用于挂载的目录并设置完全权限 + + ``` + mkdir /home/sqbin/nfs + sudo chmod 777 /home/sqbin/nfs + ``` + + 3. 设置和启动NFS server。 + + 修改NFS配置文件/etc/exports,添加如下一行: + + ``` + /home/sqbin/nfs *(rw,no_root_squash,async) + ``` + + 其中/home/sqbin/nfs是NFS共享的根目录。 + + 执行以下命令启动NFS server: + + ``` + sudo /etc/init.d/nfs-kernel-server start + ``` + + 执行以下命令重启NFS server: + + ``` + sudo /etc/init.d/nfs-kernel-server restart + ``` + + +2. **设置单板为NFS客户端**。 + + 本指导中的NFS客户端指运行OpenHarmony内核的设备。 + + 1. 硬件连接设置。 + + OpenHarmony内核设备连接到NFS服务器的网络。设置两者IP,使其处于同一网段。比如,设置NFS服务器的IP为10.67.212.178/24,设置OpenHarmony内核设备IP为10.67.212.3/24,注意:此IP为内网私有IP地址,用户使用时有差异,以用户实际IP为准。 + + OpenHarmony内核设备上的IP信息可通过ifconfig命令查看。 + + 2. 启动网络,确保单板到NFS服务器之间的网络通畅。 + + 启动以太网或者其他类型网络,使用ping命令检查到服务器的网络是否通畅。 + + ``` + OHOS # ping 10.67.212.178 + [0]Reply from 10.67.212.178: time=1ms TTL=63 + [1]Reply from 10.67.212.178: time=0ms TTL=63 + [2]Reply from 10.67.212.178: time=1ms TTL=63 + [3]Reply from 10.67.212.178: time=1ms TTL=63 + --- 10.67.212.178 ping statistics --- + 4 packets transmitted, 4 received, 0 loss + ``` + + 客户端NFS初始化,运行命令: + + ``` + OHOS # mkdir /nfs + OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 + ``` + + 将从串口得到如下回应信息,表明初始化NFS客户端成功。 + + ``` + OHOS # mount 10.67.212.178:/home/sqbin/nfs /nfs nfs 1011 1000 + Mount nfs on 10.67.212.178:/home/sqbin/nfs, uid:1011, gid:1000 + Mount nfs finished. + ``` + + 该命令将服务器10.67.212.178上的/home/sqbin/nfs目录mount在OpenHarmony内核设备上的/nfs上。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >本例默认nfs server已经配置可用,即示例中服务器10.67.212.178上的/home/sqbin/nfs已配置可访问。 + + mount命令的格式为: + + ``` + mount nfs + ``` + + 其中“SERVER\_IP“表示服务器的IP地址;“SERVER\_PATH“表示服务器端NFS共享目录路径;“CLIENT\_PATH“表示设备上的NFS路径。 + + 如果不想有NFS访问权限限制,请在Linux命令行将NFS根目录权限设置成777: + + ``` + chmod -R 777 /home/sqbin/nfs + ``` + + 至此,NFS客户端设置完毕。NFS文件系统已成功挂载。 + + +3. **利用NFS共享文件**。 + + 在NFS服务器下新建目录dir,并保存。在OpenHarmony内核下运行ls命令: + + ``` + OHOS # ls /nfs + ``` + + 则可从串口得到如下回应: + + ``` + OHOS # ls /nfs + Directory /nfs: + drwxr-xr-x 0 u:0 g:0 dir + ``` + + 可见,刚刚在NFS服务器上新建的dir目录已同步到客户端\(OpenHarmony内核系统\)的/nfs目录,两者保持同步。 + + 同样地,在客户端\(OpenHarmony内核系统\)上创建文件和目录,在NFS服务器上也可以访问,读者可自行体验。 + + **平台差异性:** + + 目前,NFS客户端仅支持NFS v3部分规范要求,因此对于规范支持不全的服务器,无法完全兼容。在开发测试过程中,建议使用Linux的NFS server,因为其对NFS支持很完善。 + + diff --git a/zh-cn/device-dev/kernel/RAMFS.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-ramfs.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/RAMFS.md rename to zh-cn/device-dev/kernel/kernel-lite-small-file-ramfs.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md b/zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md new file mode 100644 index 0000000000000000000000000000000000000000..c7d197be36132aa914eaa399d9e16945e6f11ccd --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-file-vfs.md @@ -0,0 +1,171 @@ +# VFS + +- [概述](#section132540468341) +- [基本概念](#section229417111227) +- [运作机制](#section18114182834215) +- [注意事项](#section18311145173712) +- [开发指导](#section422619258380) +- [编程实例](#section180311121420) +- [结果验证](#section16772334714) + +## 概述 + +## 基本概念 + +VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。 + +由于不同类型的文件系统接口不统一,若系统中有多个文件系统类型,访问不同的文件系统就需要使用不同的非标准接口。而通过在系统中添加VFS层,提供统一的抽象接口,屏蔽了底层异构类型的文件系统的差异,使得访问文件系统的系统调用不用关心底层的存储介质和文件系统类型,提高开发效率。VFS和各个具体文件系统的关系如下: + +**图 1** VFS和各个文件系统的关系 +![](figure/VFS和各个文件系统的关系.png "VFS和各个文件系统的关系") + +OpenHarmony内核中,VFS框架是通过在内存中的树结构来实现的,树的每个结点都是一个inode结构体。设备注册和文件系统挂载后会根据路径在树中生成相应的结点。VFS最主要是两个功能: + +- 查找节点。 +- 统一调用(标准)。 + +## 运作机制 + +通过VFS层,可以使用标准的Unix文件操作函数(如open、read、write等)来实现对不同介质上不同文件系统的访问。 + +VFS框架内存中的inode树结点有三种类型: + +- 虚拟结点:作为VFS框架的虚拟文件,保持树的连续性,如/usr、/usr/bin。 +- 设备结点:/dev目录下,对应一个设备,如/dev/mmcblk0。 +- 挂载点:挂载具体文件系统,如/vs/sd、/mnt。 + +**图 2** 文件系统树形结构 +![](figure/文件系统树形结构.png "文件系统树形结构") + +## 注意事项 + +- VFS下的所有文件系统,创建的目录名和文件名最多只可以有255个字节,能支持的全路径长度最长为259字节,超过这个路径长度的文件和目录无法创建。 + +- 目前仅有jffs2文件系统支持完整的权限控制。 + +- inode\_find\(\)函数调用后会使查找到的inode节点连接数+1,调用完成后需要调用inode\_release\(\)使连接数-1,所以一般inode\_find\(\)要和inode\_release\(\)配套使用。 + +- 设备分为字符设备和块设备,为了块设备上的文件系统系统数据安全,需挂载相应文件系统后通过文件系统接口操作数据。 + +- los\_vfs\_init\(\)只能调用一次,多次调用将会造成文件系统异常。 + +- 目前OpenHarmony内核所有的文件系统中的文件名和目录名中只可以出现“-” 与“\_”两种特殊字符,使用其他特殊字符可能造成的后果不可预知,请谨慎为之。 + +- OpenHarmony内核支持open\(\)+O\_DIRECTORY的方法获取目录数据信息。 + +- 挂载点必须为空目录,不能重复挂载至同一挂载点或挂载至其他挂载点下的目录或文件,错误挂载可能损坏设备及系统。 + +- open打开一个文件时,参数O\_RDWR、O\_WRONLY、O\_RDONLY互斥,只能出现一个,若出现2个或以上作为open的参数,文件读写操作会被拒绝,并返回EACCESS错误码,禁止使用。 + +- OpenHarmony内核文件系统在umount操作之前,需确保所有目录及文件全部关闭,否则umount会失败。如果强制umount,可能导致包括但不限于文件系统损坏、设备损坏等问题。 + +- SD卡移除前,需确保所有目录及文件全部关闭,并进行umount操作。如果强制拔卡,可能导致包括但不限于SD数据丢失、SD卡损坏等问题。 + + +## 开发指导 + +**开发流程** + +推荐驱动开发人员使用VFS框架来注册/卸载设备,即调用register\_driver\(\)、register\_blockdriver\(\)接口生成设备结点,应用层使用open\(\)、read\(\)操作设备(字符设备)文件来调用驱动。 + +**文件描述符** + +本系统中,进程的文件描述符最多有256个(File和Socket描述符合并统计),系统文件描述符共640个,系统文件描述符规格: + +- File描述符,普通文件描述符,系统总规格为512。 + +- Socket描述符,系统总规格为128。 + + +**VFS支持的操作** + +open, close, read, write, seek, ioctl, fcntl, mmap, sync, dup, dup2, truncate, opendir, closedir, readdir, rewinddir, mount, umount, statfs, unlink, remove, mkdir, rmdir, rename, stat, utime, seek64, fallocate, fallocate64, truncate64, chmod, chown。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 当前只提供修改jffs2文件以及vfs设备节点属性的接口,各个系统对只读等属性有各自的处理方式。 +>- 在OpenHarmony内核中属性并不冲突(可以任意修改)。 +>- 在OpenHarmony内核中只读属性文件/目录不允许被删除。 +>- 在OpenHarmony内核中只读属性文件/目录允许rename。 +>- 只读文件不允许以O\_CREAT、O\_TRUNC,以及有含有写的权限的方式打开。 +>- 在OpenHarmony内核中设置的系统文件加上隐藏属性,在Windows中只能通过命令行找到(在显示,不显示隐藏文件的属性情况下都不能看到)。 + +## 编程实例 + +``` +/* 说明:展示创建目录,和遍历目录的操作 */ +#include +#include +#include +#include +#include +#include + +int main() +{ + int ret; + char *dirname = "/test"; + char *pathname0 = "/test/test0"; + char *pathname1 = "/test/test1"; + char *pathname2 = "/test/test2"; + struct dirent **namelist; + int num; + + ret = mkdir(dirname, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", dirname, errno); + goto EXIT; + } + + ret = mkdir(pathname0, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", pathname0, errno); + goto EXIT0; + } + + ret = mkdir(pathname1, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", pathname1, errno); + goto EXIT1; + } + + ret = mkdir(pathname2, 0777); + if ((ret < 0) && (errno != EEXIST)) { + printf("mkdir failed. path=%s, errno=%d\n", pathname2, errno); + goto EXIT2; + } + + num = scandir(dirname, &namelist, NULL, alphasort); + if (num < 0) { + perror("scandir"); + } else { + while (num--) { + printf("%s\n", namelist[num]->d_name); + free(namelist[num]); + } + free(namelist); + } + + printf("fs_demo exit.\n"); + return 0; + +EXIT2: + remove(pathname2); +EXIT1: + remove(pathname1); +EXIT0: + remove(pathname0); +EXIT: + remove(dirname); + return 0; +} +``` + +## 结果验证 + +``` +OHOS # test2 +test1 +test0 +fs_demo exit. +``` + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-file.md b/zh-cn/device-dev/kernel/kernel-lite-small-file.md new file mode 100644 index 0000000000000000000000000000000000000000..e88e5dd77b3a3a41c0d9fc63e0c52cf09d75205b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-file.md @@ -0,0 +1,54 @@ +# 文件系统 + +OpenHarmony轻内核支持的文件系统有:VFS(虚拟文件系统)、NFS、RAMFS、FAT、JFFS2。 + +**各个文件系统功能概述:** + +**表 1** 文件系统功能概述 + + + + + + + + + + + + + + + + + + + + + + +

文件系统

+

功能特点概述

+

VFS

+

VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。

+

NFS

+

NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。

+

RAMFS

+

RAMFS是一种基于RAM的文件系统。RAMFS文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,避免了对存储器的读写损耗,也提高了数据读写速度。RAMFS是基于RAM的动态文件系统的一种存储缓冲机制。

+

FAT

+

FAT文件系统是File Allocation Table(文件配置表)的简称,有FAT12、FAT16、FAT32。在可移动存储介质(U盘、SD卡、移动硬盘等)上多使用FAT文件系统,使设备与Windows、Linux等桌面系统之间保持很好的兼容性。

+

JFFS2

+

JFFS2是Journalling Flash File System Version 2(日志文件系统)的缩写,是MTD设备上的日志型文件系统。主要应用于对NOR_FLASH闪存的文件管理。OpenHarmony内核的JFFS2支持多分区。

+
+ +- **[VFS](kernel-lite-small-file-vfs.md)** + +- **[NFS](kernel-lite-small-file-nfs.md)** + +- **[RAMFS](kernel-lite-small-file-ramfs.md)** + +- **[FAT](kernel-lite-small-file-fat.md)** + +- **[JFFS2](kernel-lite-small-file-jffs.md)** + + diff --git "a/zh-cn/device-dev/kernel/\344\270\216Linux\346\240\207\345\207\206\345\272\223\347\232\204\345\267\256\345\274\202.md" b/zh-cn/device-dev/kernel/kernel-lite-small-lib-differ.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/\344\270\216Linux\346\240\207\345\207\206\345\272\223\347\232\204\345\267\256\345\274\202.md" rename to zh-cn/device-dev/kernel/kernel-lite-small-lib-differ.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md b/zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md new file mode 100644 index 0000000000000000000000000000000000000000..9af746232e7fec8dc578856a3d16335453b22dfd --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-lib-standard.md @@ -0,0 +1,197 @@ +# 标准库 + +- [框架流程](#section1247343413257) +- [操作实例](#section4807125622614) +- [常见问题](#section1219455217277) + +OpenHarmony内核使用**musl libc**库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。 + +## 框架流程 + +**图 1** POSIX接口框架 +![](figure/POSIX接口框架.png "POSIX接口框架") + +**musl libc**库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony内核适配支持 ,以满足接口对外描述的功能要求。 + +标准库支持接口的详细情况请参考C库的API文档,其中也涵盖了与POSIX标准之间的差异说明。 + +## 操作实例 + +在本示例中,主线程创建了THREAD\_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread\_join方法等待所有线程执行结束。 + +``` +#include +#include +#include + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif /* __cplusplus */ +#endif /* __cplusplus */ + +#define THREAD_NUM 3 +int g_startNum = 0; /* 启动的线程数 */ +int g_wakenNum = 0; /* 唤醒的线程数 */ + +struct testdata { + pthread_mutex_t mutex; + pthread_cond_t cond; +} g_td; + +/* + * 子线程入口函数 + */ +static void *ChildThreadFunc(void *arg) +{ + int rc; + pthread_t self = pthread_self(); + + /* 获取mutex锁 */ + rc = pthread_mutex_lock(&g_td.mutex); + if (rc != 0) { + printf("ERROR:take mutex lock failed, error code is %d!\n", rc); + goto EXIT; + } + + /* g_startNum计数加一,用于统计已经获得mutex锁的子线程个数 */ + g_startNum++; + + /* 等待cond条件变量 */ + rc = pthread_cond_wait(&g_td.cond, &g_td.mutex); + if (rc != 0) { + printf("ERROR: pthread condition wait failed, error code is %d!\n", rc); + (void)pthread_mutex_unlock(&g_td.mutex); + goto EXIT; + } + + /* 尝试获取mutex锁,正常场景,此处无法获取锁 */ + rc = pthread_mutex_trylock(&g_td.mutex); + if (rc == 0) { + printf("ERROR: mutex gets an abnormal lock!\n"); + goto EXIT; + } + + /* g_wakenNum计数加一,用于统计已经被cond条件变量唤醒的子线程个数 */ + g_wakenNum++; + + /* 释放mutex锁 */ + rc = pthread_mutex_unlock(&g_td.mutex); + if (rc != 0) { + printf("ERROR: mutex release failed, error code is %d!\n", rc); + goto EXIT; + } +EXIT: + return NULL; +} + +static int testcase(void) +{ + int i, rc; + pthread_t thread[THREAD_NUM]; + + /* 初始化mutex锁 */ + rc = pthread_mutex_init(&g_td.mutex, NULL); + if (rc != 0) { + printf("ERROR: mutex init failed, error code is %d!\n", rc); + goto ERROROUT; + } + + /* 初始化cond条件变量 */ + rc = pthread_cond_init(&g_td.cond, NULL); + if (rc != 0) { + printf("ERROR: pthread condition init failed, error code is %d!\n", rc); + goto ERROROUT; + } + + /* 批量创建THREAD_NUM个子线程 */ + for (i = 0; i < THREAD_NUM; i++) { + rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL); + if (rc != 0) { + printf("ERROR: pthread create failed, error code is %d!\n", rc); + goto ERROROUT; + } + } + + /* 等待所有子线程都完成mutex锁的获取 */ + while (g_startNum < THREAD_NUM) { + usleep(100); + } + + /* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */ + rc = pthread_mutex_lock(&g_td.mutex); + if (rc != 0) { + printf("ERROR: mutex lock failed, error code is %d\n", rc); + goto ERROROUT; + } + + /* 释放mutex锁 */ + rc = pthread_mutex_unlock(&g_td.mutex); + if (rc != 0) { + printf("ERROR: mutex unlock failed, error code is %d!\n", rc); + goto ERROROUT; + } + + for (int j = 0; j < THREAD_NUM; j++) { + /* 在cond条件变量上广播信号 */ + rc = pthread_cond_signal(&g_td.cond); + if (rc != 0) { + printf("ERROR: pthread condition failed, error code is %d!\n", rc); + goto ERROROUT; + } + } + + sleep(1); + + /* 检查是否所有子线程都已被唤醒 */ + if (g_wakenNum != THREAD_NUM) { + printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum); + goto ERROROUT; + } + + /* join所有子线程,即等待其结束 */ + for (i = 0; i < THREAD_NUM; i++) { + rc = pthread_join(thread[i], NULL); + if (rc != 0) { + printf("ERROR: pthread join failed, error code is %d!\n", rc); + goto ERROROUT; + } + } + + /* 销毁cond条件变量 */ + rc = pthread_cond_destroy(&g_td.cond); + if (rc != 0) { + printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc); + goto ERROROUT; + } + return 0; +ERROROUT: + return -1; +} + +/* + * 示例代码主函数 + */ +int main(int argc, char *argv[]) +{ + int rc; + + /* 启动测试函数 */ + rc = testcase(); + if (rc != 0) { + printf("ERROR: testcase failed!\n"); + } + + return 0; +} +#ifdef __cplusplus +#if __cplusplus +} +#endif /* __cplusplus */ +#endif /* __cplusplus */ +``` + +## 常见问题 + +无。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-lib.md b/zh-cn/device-dev/kernel/kernel-lite-small-lib.md new file mode 100644 index 0000000000000000000000000000000000000000..849c9823bb4d63fab462824146e779ab635cbd4e --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-lib.md @@ -0,0 +1,7 @@ +# 标准库 + +- **[标准库](kernel-lite-small-lib-standard.md)** + +- **[与Linux标准库的差异](kernel-lite-small-lib-differ.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-memory.md b/zh-cn/device-dev/kernel/kernel-lite-small-memory.md new file mode 100644 index 0000000000000000000000000000000000000000..5f97c5705ac4715be205c81f29469ebf13d750c8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-memory.md @@ -0,0 +1,353 @@ +# 内存 + +- [基本概念](#section1392116583424) +- [使用场景](#section159581619194319) +- [接口说明](#section114001032104317) + +## 基本概念 + +内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。 + +良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。 + +## 使用场景 + +针对用户态开发,OpenHarmony内核提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。 + +## 接口说明 + +**表 1** 标准C库相关接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口

+

功能

+

strings.h

+

int bcmp(const void *s1, const void *s2, size_t n)

+

比较字节序列。

+

strings.h

+

void bcopy(const void *src, void *dest, size_t n)

+

拷贝字节序列。

+

strings.h

+

void bzero(void *s, size_t n)

+

写入零值字节。

+

string.h

+

void *memccpy(void *dest, const void *src, int c, size_t n)

+

拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。复制时检查参数c 是否出现,若是则返回dest 中值为c 的下一个字节地址。

+

string.h

+

void *memchr(const void *s, int c, size_t n)

+

在s所指内存的前n个字节中查找c。

+

string.h

+

int memcmp(const void *s1, const void *s2, size_t n)

+

内存比较。

+

string.h

+

void *memcpy(void *dest, const void *src, size_t n)

+

内存拷贝。

+

string.h

+

void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)

+

找到一个子串。

+

string.h

+

void *memmove(void *dest, const void *src, size_t n)

+

内存移动。

+

string.h

+

void *mempcpy(void *dest, const void *src, size_t n)

+

拷贝内存区域。

+

string.h

+

void *memset(void *s, int c, size_t n)

+

内存初始化。

+

stdlib.h

+

void *malloc(size_t size)

+

申请内存。

+

stdlib.h

+

void *calloc(size_t nmemb, size_t size)

+

申请内存并清零。

+

stdlib.h

+

void *realloc(void *ptr, size_t size)

+

重分配内存。

+

stdlib.h/malloc.h

+

void *valloc(size_t size)

+

分配以页对齐的内存。

+

stdlib.h

+

void free(void *ptr)

+

释放内存。

+

malloc.h

+

size_t malloc_usable_size(void *ptr)

+

获取从堆分配的内存块的大小。

+

unistd.h

+

int getpagesize(void)

+

获取页面大小。

+

unistd.h

+

void *sbrk(intptr_t increment)

+

更改数据段大小。

+
+ +差异接口详细说明: + +- **mmap** + + **函数原型:** + + void \*mmap\(void \*addr, size\_t length, int prot, int flags, int fd, off\_t offset\); + + **函数功能:**申请虚拟内存。 + + **参数说明:** + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

描述

+

addr

+

用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。

+

length

+

内存段的大小。

+

prot

+

用于设置内存段的访问权限,有如下权限:

+
  • PROT_READ:允许读该内存段。
  • PROT_WRITE:允许写该内存段。
  • PROT_EXEC:允许执行该内存段。
  • PROT_NONE:不能访问。
+

flags

+

控制程序对内存段的改变所造成的影响,有如下属性:

+
  • MAP_PRIVATE:内存段私有,对它的修改值仅对本进程有效。
  • MAP_SHARED:把对该内存段的修改保存到磁盘文件中。
+

fd

+

打开的文件描述符。

+

offset

+

用以改变经共享内存段访问的文件中数据的起始偏移值。

+
+ + >![](../public_sys-resources/icon-note.gif) **说明:** + >mmap与Linux实现差异详见[与Linux标准库的差异](kernel-lite-small-lib-differ.md)章节。 + + **返回值:** + + - 成功返回:虚拟内存地址,这地址是页对齐。 + - 失败返回:\(void \*\)-1。 + + +- **munmap接口** + + **函数原型:** + + int munmap\(void \*addr, size\_t length\); + + **函数功能:**释放虚拟内存。 + + **参数说明:** + + + + + + + + + + + + + +

参数

+

描述

+

addr

+

虚拟内存起始位置。

+

length

+

内存段的大小。

+
+ + **返回值:** + + - 成功返回0。 + - 失败返回-1。 + + +- **mprotect接口** + + **函数原型:** + + int mprotect\(void \*addr, size\_t length, int prot\); + + **函数功能:**修改内存段的访问权限。 + + **参数说明:** + + + + + + + + + + + + + + + + +

参数

+

描述

+

addr

+

内存段起始地址,必须页对齐;访问权限异常,内核将直接抛异常并且kill该进程,而不会产生SIGSEGV信号给当前进程。

+

length

+

内存段的大小。

+

prot

+

内存段的访问权限,有如下定义:

+
  • PROT_READ:允许读该内存段。
  • PROT_WRITE:允许写该内存段。
  • PROT_EXEC:允许执行该内存段。
  • PROT_NONE:不能访问。
+
+ + **返回值:** + + - 成功返回0。 + - 失败返回-1。 + + +- **mremap接口** + + **函数原型:** + + void \*mremap\(void \*old\_address, size\_t old\_size, size\_t new\_size, int flags, void new\_address\); + + **函数功能:**重新映射虚拟内存地址。 + + **参数说明:** + + + + + + + + + + + + + + + + + + + +

参数

+

描述

+

old_address

+

需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。

+

old_size

+

内存段的原始大小。

+

new_size

+

新内存段的大小。

+

flags

+

如果没有足够的空间在当前位置展开映射,则返回失败

+
  • MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
  • MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE。
+
+ + **返回值:** + + - 成功返回:重新映射后的虚拟内存地址。 + - 失败返回:\(\(void \*\)-1\)。 + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-net.md b/zh-cn/device-dev/kernel/kernel-lite-small-net.md new file mode 100644 index 0000000000000000000000000000000000000000..8aa33611c312c90c33556691ff5460883c51f3d8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-net.md @@ -0,0 +1,303 @@ +# 网络 + +- [基本概念](#section9840143083510) +- [使用场景](#section1575885183516) +- [接口说明](#section16351198193614) + +## 基本概念 + +网络模块实现了TCP/IP协议栈基本功能,提供标准的POSIX socket接口。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前系统使用**lwIP**提供网络能力。 + +## 使用场景 + +针对用户态开发,OpenHarmony内核提供了一套网络功能系统调用接口,支持socket的创建关闭、数据收发、网络属性的设置等,通过C库提供标准的POSIX socket函数供开发者使用。 + +## 接口说明 + +**表 1** 标准C库相关接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

接口

+

功能

+

sys/socket.h

+

int accept(int socket, struct sockaddr *address, socklen_t *address_len)

+

接受连接。

+

sys/socket.h

+

int bind(int s, const struct sockaddr *name, socklen_t namelen)

+

socket与IP地址绑定。

+

sys/socket.h

+

int shutdown(int socket, int how)

+

关闭连接。

+

sys/socket.h

+

int getpeername(int s, struct sockaddr *name, socklen_t *namelen)

+

获取对端地址。

+

sys/socket.h

+

int getsockname(int s, struct sockaddr *name, socklen_t *namelen)

+

获取本地地址。

+

sys/socket.h

+

int getsockopt(int s, struct sockaddr *name, socklen_t *namelen)

+

获取socket属性信息。

+

sys/socket.h

+

int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)

+

配置socket属性。

+

unistd.h

+

int close(int s)

+

关闭socket。

+

sys/socket.h

+

int connect(int s, const struct sockaddr *name, socklen_t namelen)

+

连接到指定的目的IP。

+

sys/socket.h

+

int listen(int sockfd, int backlog)

+

聆听连接本socket的请求。

+

sys/socket.h

+

ssize_t recv(int socket, void *buffer, size_t length, int flags)

+

接收socket上收到的数据。

+

sys/socket.h

+

ssize_t recvmsg(int s, struct msghdr *message, int flags)

+

接收socket上收到的数据,可使用更丰富的参数。

+

sys/socket.h

+

ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len)

+

接收socket上收到的数据,可同时获得数据来源IP地址。

+

sys/socket.h

+

ssize_t send(int s, const void *dataptr, size_t size, int flags)

+

通过socket发送数据。

+

sys/socket.h

+

ssize_t sendmsg(int s, const struct msghdr *message, int flags)

+

通过socket发送数据,可使用更丰富的参数。

+

sys/socket.h

+

ssize_t sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)

+

通过socket发送数据,可指定发送的目的IP地址。

+

sys/socket.h

+

int socket(int domain, int type, int protocol)

+

创建socket。

+

sys/select.h

+

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

+

多路复用。

+

sys/ioctl.h

+

int ioctl(int s, int request, ...)

+

socket属性获取、设置。

+

arpa/inet.h

+

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)

+

网络地址格式转换:将二进制格式IP地址转换为字符串格式。

+

arpa/inet.h

+

int inet_pton(int af, const char *src, void *dst)

+

网络地址格式转换:将字符串格式IP地址转换为二进制格式。

+
+ +与标准接口差异详细说明: + +- **sendmsg** + + **函数原型:** + + ssize\_t sendmsg\(int s, const struct msghdr \*message, int flags\) + + **函数功能:**发送消息。 + + **参数说明:** + + + + + + + + + + + + + + + + +

参数

+

描述

+

s

+

套接字描述符。

+

message

+

待发送的消息,不支持发送ancillary消息。

+

flags

+

用于指定发送消息时行为特性,有如下行为特性:

+
  • MSG_MORE:允许将多次发送的消息进行拼包发送。
  • MSG_DONTWAIT:非阻塞操作。
+
+ + **返回值:** + + - 成功返回:已发送的消息长度(字节数)。 + - 失败返回:-1,并设置errno。 + + +- **recvmsg** + + **函数原型:** + + ssize\_t recvmsg\(int s, struct msghdr \*message, int flags\) + + **函数功能:**接收消息。 + + **参数说明:** + + + + + + + + + + + + + + + + +

参数

+

描述

+

s

+

套接字描述符。

+

message

+

存放接收的消息,不支持接收ancillary消息。

+

flags

+

用于指定接收消息时行为特性,有如下行为特性:

+
  • MSG_PEEK:允许预读消息而不取走。
  • MSG_DONTWAIT:非阻塞操作。
+
+ + **返回值:** + + - 成功返回:已接收的消息长度(字节数)。 + - 失败返回:-1,并设置errno。 + + +- **ioctl** + + **函数原型:** + + int ioctl\(int s, int request, ...\) + + **函数功能:**获取或设置socket属性。 + + **参数说明:** + + + + + + + + + + + + + +

参数

+

描述

+

s

+

套接字描述符。

+

request

+

对socket属性要进行的操作,当前支持如下操作:

+
  • FIONREAD:获取socket当前可读取的数据大小(字节数)。
  • FIONBIO:设置socket是否非阻塞。
+
+ + **返回值:** + + - 成功返回:0。 + - 失败返回:-1,并设置errno。 + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-process.md b/zh-cn/device-dev/kernel/kernel-lite-small-process.md new file mode 100644 index 0000000000000000000000000000000000000000..d6b9ca0377b4a57c3e6663468ddfba4f7a6d930c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-process.md @@ -0,0 +1,301 @@ +# 进程 + +- [基本概念](#section29197338383) +- [使用场景](#section85513272398) +- [接口说明](#section4517119124015) + +## 基本概念 + +从系统的角度看,进程是资源管理单元。进程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它进程运行。 + +OpenHarmony内核的进程模块可以给用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。这样用户可以将更多的精力投入到业务功能的实现中。 + +OpenHarmony内核中的进程采用抢占式调度机制,支持时间片轮转调度方式。 + +OpenHarmony内核的进程一共有32个优先级\(0-31\),用户进程可配置的优先级有22个\(10-31\),最高优先级为10,最低优先级为31。 + +高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。 + +每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。 + +用户态根进程init由内核态创建,其它用户态进程均由init进程fork而来。 + +**进程状态说明:** + +- 初始化(Init):该进程正在被创建。 + +- 就绪(Ready):该进程在就绪列表中,等待CPU调度。 + +- 运行(Running):该进程正在运行。 + +- 阻塞(Pending):该进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。 + +- 僵尸态(Zombies):该进程运行结束,等待父进程回收其控制块资源。 + + +**图 1** 进程状态迁移示意图 +![](figure/进程状态迁移示意图.png "进程状态迁移示意图") + +**进程状态迁移说明:** + +- Init→Ready: + + 进程创建或fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程插入调度队列,此时进程进入就绪状态。 + +- Ready→Running: + + 进程创建后进入就绪态,发生进程切换时,就绪列表中最高优先级的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则该进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存。 + +- Running→Pending: + + 进程内所有的线程均处于阻塞态时,进程在最后一个线程转为阻塞态时,同步进入阻塞态,然后发生进程切换。 + +- Pending→Ready: + + 阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。 + +- Ready→Pending: + + 进程内的最后一个就绪态线程处于阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。 + +- Running→Ready: + + 进程由运行态转为就绪态的情况有以下两种: + + 1. 有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。 + 2. 若进程的调度策略为SCHED\_RR,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。 + +- Running→Zombies: + + 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。 + + +## 使用场景 + +进程创建后,用户只能操作自己进程空间的资源,无法操作其它进程的资源(共享资源除外)。 用户态允许进程挂起,恢复,延时等操作,同时也可以设置用户态进程调度优先级和调度策略,获取进程调度优先级和调度策略。进程结束的时候,进程会主动释放持有的进程资源,但持有的进程pid资源需要父进程通过wait/waitpid或父进程退出时回收。 + +## 接口说明 + +OpenHarmony内核系统中的进程管理模块为用户提供下面几种功能: + +**表 1** 进程管理模块功能 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

功能分类

+

接口名

+

描述

+

备注

+

进程

+

fork

+

创建一个新进程。

+

-

+

exit

+

终止进程。

+

-

+

atexit

+

注册正常进程终止的回调函数。

+

-

+

abort

+

中止进程执行。

+

-

+

getpid

+

获取进程ID。

+

-

+

getppid

+

获取父进程ID。

+

-

+

getpgrp

+

获取调用进程的进程组ID。

+

-

+

getpgid

+

获取进程的进程组ID。

+

-

+

setpgrp

+

设置调用进程的进程组ID。

+

-

+

setpgid

+

设置进程的进程组ID。

+

-

+

kill

+

给进程发送信号。

+
  • 仅支持1-30号信号的发送。
  • 信号的默认行为不支持STOP及CONTINUE,无COREDUMP功能。
  • 不能屏蔽SIGSTOP、SIGKILL、SIGCONT。
  • 异步信号,发送信号给某进程后,直到该进程被调度后才会执行信号回调(为安全起见,杀死进程的动作是进程自己执行的,内核不能通过信号强制杀死对方)。
  • 进程消亡会发送SIGCHLD给父进程,发送动作无法取消。
  • 无法通过信号唤醒正在睡眠的进程。
+

wait

+

等待任意子进程结束并回收子进程资源。

+

status的值可以由以下宏定义解析:

+
  • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
  • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
  • WTERMSIG(status) 仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
  • 不支持的操作: WIFSTOPPED、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
+

waitpid

+

等待子进程结束并回收子进程资源。

+

options:不支持WUNTRACED,WCONTINUED;

+

status的值可以由以下宏定义解析:

+
  • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
  • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
  • WTERMSIG(status)仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
  • 不支持:WIFSTOPPED 、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
+

调度

+

getpriority

+

获取指定ID的静态优先级。

+
  • 不支持:PRIO_PGRP、PRIO_USER。
+
  • 无动态优先级概念,用于设置静态优先级。
+

setpriority

+

设置指定ID的静态优先级。

+

sched_rr_get_interval

+

获取执行时间限制。

+

-

+

sched_yield

+

系统调用运行进程主动让出执行权。

+

-

+

sched_get_priority_max

+

获取进程静态优先级取值范围的最大值。

+

调度策略只支持:SCHED_RR。

+

sched_get_priority_min

+

获取进程静态优先级取值范围的最小值。

+

sched_getscheduler

+

获取调度策略。

+

sched_setscheduler

+

设置调度策略。

+

sched_getparam

+

获取调度参数。

+

-

+

sched_setparam

+

设置调度参数。

+

-

+

exec

+

execl

+

执行指定的elf格式的用户程序文件。

+

-

+

execle

+

执行指定的elf格式的用户程序文件。

+

-

+

execlp

+

执行指定的elf格式的用户程序文件。

+

-

+

execv

+

执行指定的elf格式的用户程序文件。

+

-

+

execve

+

执行指定的elf格式的用户程序文件。

+

-

+

execvp

+

执行指定的elf格式的用户程序文件。

+

-

+
+ diff --git "a/zh-cn/device-dev/kernel/\347\224\250\346\210\267\346\200\201\345\274\202\345\270\270\344\277\241\346\201\257\350\257\264\346\230\216.md" b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-abn.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/\347\224\250\346\210\267\346\200\201\345\274\202\345\270\270\344\277\241\346\201\257\350\257\264\346\230\216.md" rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-abn.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md new file mode 100644 index 0000000000000000000000000000000000000000..89f4a35b9f4980a853899a6db9cb91fe205291ed --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cat.md @@ -0,0 +1,53 @@ +# cat + +- [命令功能](#section16710153391315) +- [命令格式](#section1699392313158) +- [参数说明](#section1677217374136) +- [使用指南](#section186772414131) +- [使用实例](#section12158131814561) +- [输出说明](#section183926225561) + +## 命令功能 + +cat用于显示文本文件的内容。 + +## 命令格式 + +cat \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

pathname

+

文件路径。

+

已存在的文件。

+
+ +## 使用指南 + +cat用于显示文本文件的内容。 + +## 使用实例 + +举例:cat hello-harmony.txt + +## 输出说明 + +**图 1** 查看 hello-harmony.txt 文件的信息 +![](figure/查看-hello-harmony-txt-文件的信息.png "查看-hello-harmony-txt-文件的信息") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md new file mode 100644 index 0000000000000000000000000000000000000000..61247bfba2e28f771398d9a561063eea382984c8 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cd.md @@ -0,0 +1,57 @@ +# cd + +- [命令功能](#section11690184921316) +- [命令格式](#section75695409569) +- [参数说明](#section71961353181311) +- [使用指南](#section3629759111317) +- [使用实例](#section211620301412) +- [输出说明](#section1968117214577) + +## 命令功能 + +cd命令用来改变当前目录。 + +## 命令格式 + +cd \[_path_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

path

+

文件路径。

+

用户必须具有指定目录中的执行(搜索)许可权。

+
+ +## 使用指南 + +- 未指定目录参数时,会跳转至根目录。 +- cd后加路径名时,跳转至该路径。 +- 路径名以 /(斜杠)开头时,表示根目录。 +- .(点)表示当前目录。 +- ..(点点)表示父目录。 + +## 使用实例 + +举例:cd .. + +## 输出说明 + +**图 1** 显示结果如下 +![](figure/显示结果如下.png "显示结果如下") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md new file mode 100644 index 0000000000000000000000000000000000000000..efeccc336faaf14bcab8c01256026cd5e437722c --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chgrp.md @@ -0,0 +1,60 @@ +# chgrp + +- [命令功能](#section6103119161418) +- [命令格式](#section186958132141) +- [参数说明](#section81796174141) +- [使用指南](#section14330152417140) +- [使用实例](#section951823119149) +- [输出说明](#section14271133125715) + +## 命令功能 + +chgrp用于修改文件的群组。 + +## 命令格式 + +chgrp \[_group_\] \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

group

+

文件群组。

+

[0,0xFFFFFFFF]

+

pathname

+

文件路径。

+

已存在的文件。

+
+ +## 使用指南 + +在需要修改的文件名前加上文件群组值就可以修改该文件的所属组。 + +## 使用实例 + +举例:chgrp 100 hello-harmony.txt + +## 输出说明 + +**图 1** 修改 hello-harmony.txt 文件的群组为100 +![](figure/修改-hello-harmony-txt-文件的群组为100.png "修改-hello-harmony-txt-文件的群组为100") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md new file mode 100644 index 0000000000000000000000000000000000000000..296ab1e3d3890571360162d88a0b139c6c3d00e4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chmod.md @@ -0,0 +1,60 @@ +# chmod + +- [命令功能](#section13992936121418) +- [命令格式](#section63342439147) +- [参数说明](#section894414671411) +- [使用指南](#section182415221419) +- [使用实例](#section8518195718147) +- [输出说明](#section127391818158) + +## 命令功能 + +chmod用于修改文件操作权限。 + +## 命令格式 + +chmod \[_mode_\] \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

mode

+

文件或文件夹权限,用8进制表示对应User、Group、及Other(拥有者、群组、其他组)的权限。

+

[0,777]

+

pathname

+

文件路径。

+

已存在的文件。

+
+ +## 使用指南 + +在需要修改的文件名前加上文件权限值就可以修改该文件的权限值。 + +## 使用实例 + +举例:chmod 666 hello-harmony.txt + +## 输出说明 + +**图 1** 修改 hello-harmony.txt 文件的权限为666 +![](figure/修改-hello-harmony-txt-文件的权限为666.png "修改-hello-harmony-txt-文件的权限为666") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md new file mode 100644 index 0000000000000000000000000000000000000000..4e63051ec9c9aa6e4e6fea52278e0b9905c08f45 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-chown.md @@ -0,0 +1,70 @@ +# chown + +- [命令功能](#section247414691513) +- [命令格式](#section14773151018159) +- [参数说明](#section598731391517) +- [使用指南](#section16524152071510) +- [使用实例](#section17901152561510) +- [输出说明](#section15513163115816) + +## 命令功能 + +chmod用于将指定文件的拥有者改为指定的用户或组。 + +## 命令格式 + +chown \[_owner_\] \[_group_\] \[_pathname_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

owner

+

文件拥有者。

+

[0,0xFFFFFFFF]

+

group

+

文件群组。

+

1、为空。

+

2、[0,0xFFFFFFFF]

+

pathname

+

文件路径。

+

已存在的文件。

+
+ +## 使用指南 + +- 在需要修改的文件名前加上文件拥有者和文件群组就可以分别修改该文件的拥有者和群组。 +- 当owner或group值为-1时则表示对应的owner或group不修改。 +- group参数可以为空。 + +## 使用实例 + +举例:chown 100 200 hello-harmony.txt + +## 输出说明 + +**图 1** 修改 hello-harmony.txt 文件的uid为100,gid为200 +![](figure/修改-hello-harmony-txt-文件的uid为100-gid为200.png "修改-hello-harmony-txt-文件的uid为100-gid为200") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md new file mode 100644 index 0000000000000000000000000000000000000000..299beb065c72efb62c4d54ae5a675b6e0ae7ec20 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-cp.md @@ -0,0 +1,68 @@ +# cp + +- [命令功能](#section6841203041513) +- [命令格式](#section24286359150) +- [参数说明](#section558617385152) +- [使用指南](#section16128156162) +- [使用实例](#section19354171211618) +- [输出说明](#section16754183195914) + +## 命令功能 + +拷贝文件,创建一份副本。 + +## 命令格式 + +cp \[_SOURCEFILE_\] \[_DESTFILE_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

SOURCEFILE

+

源文件路径。

+

目前只支持文件,不支持目录。

+

DESTFILE

+

目的文件路径。

+

支持目录以及文件。

+
+ +## 使用指南 + +- 同一路径下,源文件与目的文件不能重名。 +- 源文件必须存在,且不为目录。 +- 源文件路径支持“\*”和“?”通配符,“\*”代表任意多个字符,“?”代表任意单个字符。目的路径不支持通配符。当源路径可匹配多个文件时,目的路径必须为目录。 +- 目的路径为目录时,该目录必须存在。此时目的文件以源文件命名。 +- 目的路径为文件时,所在目录必须存在。此时拷贝文件的同时为副本重命名。 +- 目前不支持多文件拷贝。参数大于2个时,只对前2个参数进行操作。 +- 目的文件不存在时创建新文件,已存在则覆盖。 + +拷贝系统重要资源时,会对系统造成死机等重大未知影响,如用于拷贝/dev/uartdev-0 文件时,会产生系统卡死现象。 + +## 使用实例 + +举例:cp hello-harmony.txt ./tmp/ + +## 输出说明 + +**图 1** 显示结果如下 +![](figure/显示结果如下-17.png "显示结果如下-17") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md new file mode 100644 index 0000000000000000000000000000000000000000..200ddb4fe65b114791341707ba5bea5649f85255 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-format.md @@ -0,0 +1,69 @@ +# format + +- [命令功能](#section1922331919169) +- [命令格式](#section249226169) +- [参数说明](#section985173416177) +- [使用指南](#section1510162714162) +- [使用实例](#section25691431161611) +- [输出说明](#section17368112365920) + +## 命令功能 + +format指令用于格式化磁盘。 + +## 命令格式 + +format <_dev\_inodename_\> <_sectors_\> <_option_\> \[_label_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

dev_inodename

+

设备名。

+

sectors

+

分配的单元内存或扇区大小,如果输入0表示参数为空。(取值必须为0或2的幂,fat32下最大值为128,取值0表示自动选择合适的簇大小,不同size的分区,可用的簇大小范围不同,错误的簇大小指定可能导致格式化失败)。

+

option

+
格式化选项,用来选择文件系统的类型,有如下几种参数选择:
  • 0x01:FMT_FAT
  • 0x02:FMT_FAT32
  • 0x07:FMT_ANY
  • 0x08:FMT_ERASE (USB不支持该选项)
+
+

传入其他值皆为非法值,将由系统自动选择格式化方式。若格式化U盘时低格位为 1,会出现错误打印。

+

label

+

该参数为可选参数,输入值应为字符串,用来指定卷标名。当输入字符串"null"时,则把之前设置的卷标名清空。

+
+ +## 使用指南 + +- format指令用于格式化磁盘,设备名可以在dev目录下查找。format时必须安装存储卡。 +- format只能格式化U盘、sd和mmc卡,对Nand flash和Nor flash格式化不起作用。 +- sectors参数必须传入合法值,传入非法参数可能引发异常。 + +## 使用实例 + +举例:输入format /dev/mmcblk0 128 2 + +## 输出说明 + +结果如下 + +![](figure/zh-cn_image_0000001052370307.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md new file mode 100644 index 0000000000000000000000000000000000000000..0a1823804e0adc769a94d7dbe961d129310da288 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-is.md @@ -0,0 +1,59 @@ +# ls + +- [命令功能](#section6538163771614) +- [命令格式](#section45881743111616) +- [参数说明](#section17528148171617) +- [使用指南](#section041212533166) +- [使用实例](#section986105716167) +- [输出说明](#section2036124918592) + +## 命令功能 + +ls命令用来显示当前目录的内容。 + +## 命令格式 + +ls \[_path_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

path

+

path为空时,显示当前目录的内容。

+

path为无效文件名时,显示失败,提示:

+

ls error: No such directory。

+

path为有效目录路径时,会显示对应目录下的内容。

+

1.为空。

+

2.有效的目录路径。

+
+ +## 使用指南 + +- ls命令显示当前目录的内容。 +- ls可以显示文件的大小。 +- proc下ls无法统计文件大小,显示为0。 + +## 使用实例 + +举例:输入ls + +## 输出说明 + +**图 1** 查看当前系统路径下的目录,显示的内容如下 +![](figure/查看当前系统路径下的目录-显示的内容如下.png "查看当前系统路径下的目录-显示的内容如下") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md new file mode 100644 index 0000000000000000000000000000000000000000..e1fb8007c539895e4551e5ef6a8d229beba38e93 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-isfd.md @@ -0,0 +1,29 @@ +# lsfd + +- [命令功能](#section2053406181716) +- [命令格式](#section523771017172) +- [使用指南](#section27241213201719) +- [使用实例](#section442617197173) +- [输出说明](#section42491639151813) + +## 命令功能 + +lsfd命令用来显示当前已经打开的文件描述符及对应的文件名。 + +## 命令格式 + +lsfd + +## 使用指南 + +lsfd命令显示当前已经打开文件的fd号以及文件的名字。 + +## 使用实例 + +举例:输入lsfd + +## 输出说明 + +**图 1** lsfd输出说明 +![](figure/lsfd输出说明.png "lsfd输出说明") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md new file mode 100644 index 0000000000000000000000000000000000000000..c261ebdca3e37218fb3646c90c3e3a78c854e337 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mkdir.md @@ -0,0 +1,54 @@ +# mkdir + +- [命令功能](#section1083613274175) +- [命令格式](#section820913118178) +- [参数说明](#section1256834121718) +- [使用指南](#section1294234115172) +- [使用实例](#section1113345211713) +- [输出说明](#section10142201012) + +## 命令功能 + +mkdir命令用来创建一个目录。 + +## 命令格式 + +mkdir \[_directory_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

directory

+

需要创建的目录。

+

N/A

+
+ +## 使用指南 + +- mkdir后加所需要创建的目录名会在当前目录下创建目录。 +- mkdir后加路径,再加上需要创建的目录名,即在指定目录下创建目录。 + +## 使用实例 + +举例:mkdir share + +## 输出说明 + +**图 1** 创建 share 目录 +![](figure/创建-share-目录.png "创建-share-目录") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md new file mode 100644 index 0000000000000000000000000000000000000000..103a5d29c4ed79b4ffc4b5b812e07c3ce414e87d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-mount.md @@ -0,0 +1,78 @@ +# mount + +- [命令功能](#section11631837182) +- [命令格式](#section1697638111820) +- [参数说明](#section1650151221819) +- [使用指南](#section124541520171912) +- [使用实例](#section7424625171917) +- [输出说明](#section14757018116) + +## 命令功能 + +mount命令用来将设备挂载到指定目录。 + +## 命令格式 + +mount <_device_\> <_path_\> <_name_\> \[_uid gid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

device

+

要挂载的设备(格式为设备所在路径)。

+

系统拥有的设备。

+

path

+

指定目录。

+

用户必须具有指定目录中的执行(搜索)许可权。

+

N/A

+

name

+

文件系统的种类。

+

vfat, yaffs, jffs, ramfs, nfs,procfs, romfs.

+

uid gid

+

uid是指用户ID。

+

gid是指组ID。

+

可选参数,缺省值uid:0,gid:0。

+

N/A

+
+ +## 使用指南 + +mount后加需要挂载的设备信息、指定目录以及设备文件格式,就能成功挂载文件系统到指定目录。 + +## 使用实例 + +举例:mount /dev/mmcblk0p0 /bin1/vs/sd vfat + +## 输出说明 + +将/dev/mmcblk0p0 挂载到/bin1/vs/sd目录 + +![](figure/zh-cn_image_0000001051690323.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md new file mode 100644 index 0000000000000000000000000000000000000000..52ba25e101848e6463d1da65c5b0131059584496 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-part.md @@ -0,0 +1,52 @@ +# partinfo + +- [命令功能](#section1777503617199) +- [命令格式](#section185501447132114) +- [参数说明](#section1304151212252) +- [使用指南](#section4566131982520) +- [使用实例](#section4351134942514) +- [输出说明](#section66689331412) + +## 命令功能 + +partinfo命令用于查看系统识别的硬盘,SD卡多分区信息。 + +## 命令格式 + +partinfo <_dev\_inodename_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

dev_inodename

+

要查看的分区名字。

+

合法的分区名。

+
+ +## 使用指南 + +无 + +## 使用实例 + +partinfo /dev/mmcblk0p0 + +## 输出说明 + +![](figure/zh-cn_image_0000001052370303.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md new file mode 100644 index 0000000000000000000000000000000000000000..458f7f05ef470e91f3813b8bcf8a532aa71b0e99 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-partion.md @@ -0,0 +1,62 @@ +# partition + +- [命令功能](#section255095212257) +- [命令格式](#section10258056122515) +- [参数说明](#section177200581256) +- [使用指南](#section17866411262) +- [使用实例](#section1927174202610) +- [输出说明](#section11321011223) + +## 命令功能 + +partition命令用来查看flash分区信息。 + +## 命令格式 + +partition \[_nand / spinor_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

nand

+

显示nand flash分区信息。

+

N/A

+

spinor

+

显示spinor flash分区信息。

+

N/A

+
+ +## 使用指南 + +- partition命令用来查看flash分区信息。 +- 仅当使能yaffs文件系统时才可以查看nand flash分区信息,使能jffs或romfs文件系统时可以查看spinor flash分区信息。 + +## 使用实例 + +举例:partition spinor + +## 输出说明 + +查看spinor flash分区信息 + +![](figure/zh-cn_image_0000001052810300.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md new file mode 100644 index 0000000000000000000000000000000000000000..c9d526fc07d50b00ec756a43ebc42a59cd55e531 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-pwd.md @@ -0,0 +1,34 @@ +# pwd + +- [命令功能](#section197737712267) +- [命令格式](#section1544061016267) +- [参数说明](#section599112120262) +- [使用指南](#section66901116152615) +- [使用实例](#section7427181922612) +- [输出说明](#section116313389418) + +## 命令功能 + +pwd命令用来显示当前路径。 + +## 命令格式 + +pwd + +## 参数说明 + +无。 + +## 使用指南 + +pwd 命令将当前目录的全路径名称(从根目录)写入标准输出。全部目录使用 / (斜线)分隔。第一个 / 表示根目录, 最后一个目录是当前目录。 + +## 使用实例 + +举例:输入pwd + +## 输出说明 + +**图 1** 查看当前路径 +![](figure/查看当前路径.png "查看当前路径") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md new file mode 100644 index 0000000000000000000000000000000000000000..b9eb4d90a0a88fc19697f3a7a006b2c957bba948 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rm.md @@ -0,0 +1,67 @@ +# rm + +- [命令功能](#section181141523142613) +- [命令格式](#section8800926132619) +- [参数说明](#section15476229152617) +- [使用指南](#section10578163215262) +- [使用实例](#section18548133511263) +- [输出说明](#section1565323814265) + +## 命令功能 + +rm命令用来删除文件或文件夹。 + +## 命令格式 + +rm \[_-r_\] \[_dirname / filename_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

-r

+

可选参数,若是删除目录则需要该参数。

+

N/A

+

dirname/filename

+

要删除文件或文件夹的名称,支持输入路径。

+

N/A

+
+ +## 使用指南 + +- rm命令一次只能删除一个文件或文件夹。 +- rm -r命令可以删除非空目录。 + +## 使用实例 + +举例: + +1. 输入rm log1.txt +2. 输入rm -r sd + +## 输出说明 + +**图 1** 用 rm 命令删除文件 log1.txt +![](figure/用-rm-命令删除文件-log1-txt.png "用-rm-命令删除文件-log1-txt") + +**图 2** 用 rm -r 删除目录 sd +![](figure/用-rm--r-删除目录-sd.png "用-rm--r-删除目录-sd") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md new file mode 100644 index 0000000000000000000000000000000000000000..c37bbea17c0fd6264888cc1272511434198e54a5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-rmdir.md @@ -0,0 +1,55 @@ +# rmdir + +- [命令功能](#section1839611420266) +- [命令格式](#section329574512266) +- [参数说明](#section15865747102620) +- [使用指南](#section107857508261) +- [使用实例](#section11196165315262) +- [输出说明](#section1073811415613) + +## 命令功能 + +rmdir命令用来删除一个目录。 + +## 命令格式 + +rmdir \[_dir_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

dir

+

需要删除目录的名称,删除目录必须为空,支持输入路径。

+

N/A

+
+ +## 使用指南 + +- rmdir命令只能用来删除目录。 +- rmdir一次只能删除一个目录。 +- rmdir只能删除空目录。 + +## 使用实例 + +举例:输入rmdir dir + +## 输出说明 + +**图 1** 删除一个名为 dir 的目录 +![](figure/删除一个名为-dir-的目录.png "删除一个名为-dir-的目录") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md new file mode 100644 index 0000000000000000000000000000000000000000..2373311252bb249b17dba03132d8c6fdaf234cc2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sta.md @@ -0,0 +1,52 @@ +# statfs + +- [命令功能](#section153921657152613) +- [命令格式](#section135391102717) +- [参数说明](#section074312314279) +- [使用指南](#section133816772712) +- [使用实例](#section526149182717) + +## 命令功能 + +statfs命令用来打印文件系统的信息,如该文件系统类型、总大小、可用大小等信息。 + +## 命令格式 + +statfs \[_directory_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

directory

+

文件系统的路径。

+

必须是存在的文件系统,并且其支持statfs命令,当前支持的文件系统有:JFFS2,FAT,NFS。

+
+ +## 使用指南 + +打印信息因文件系统而异。 + +## 使用实例 + +以nfs文件系统为例: + +statfs /nfs + +**图 1** statfs输出说明 +![](figure/statfs输出说明.png "statfs输出说明") + diff --git a/zh-cn/device-dev/kernel/sync.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sync.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/sync.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-sync.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md new file mode 100644 index 0000000000000000000000000000000000000000..1ec96315b5f0fcd4ae5b92f8b9dc2951dc729128 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-touch.md @@ -0,0 +1,59 @@ +# touch + +- [命令功能](#section17541924112716) +- [命令格式](#section866182711274) +- [参数说明](#section268912296270) +- [使用指南](#section412093332714) +- [使用实例](#section414434814354) +- [输出说明](#section1028419515711) + +## 命令功能 + +- touch命令用来在指定的目录下创建一个不存在的空文件。 +- touch命令操作已存在的文件会成功,不会更新时间戳。 + +## 命令格式 + +touch \[_filename_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

filename

+

需要创建文件的名称。

+

N/A

+
+ +## 使用指南 + +- touch命令用来创建一个空文件,该文件可读写。 +- 使用touch命令一次只能创建一个文件。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >在系统重要资源路径下使用touch命令创建文件,会对系统造成死机等未知影响,如在/dev路径下执行touch uartdev-0,会产生系统卡死现象。 + + +## 使用实例 + +举例:输入touch file.c 输出说明 + +## 输出说明 + +**图 1** 创建一个名为 file.c 的文件 +![](figure/创建一个名为-file-c-的文件.png "创建一个名为-file-c-的文件") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md new file mode 100644 index 0000000000000000000000000000000000000000..def6e2f84bd6f1c8b214ecbfa88ea3dfc4289c56 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-umount.md @@ -0,0 +1,55 @@ +# umount + +- [命令功能](#section365125133520) +- [命令格式](#section9615254123512) +- [参数说明](#section63446577355) +- [使用指南](#section92931509368) +- [使用实例](#section144311323616) +- [输出说明](#section360525113611) + +## 命令功能 + +umount命令用来卸载指定文件系统。 + +## 命令格式 + +umount \[_dir_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

dir

+

需要卸载文件系统对应的目录。

+

系统已挂载的文件系统的目录。

+
+ +## 使用指南 + +umount后加上需要卸载的指定文件系统的目录,即将指定文件系统卸载。 + +## 使用实例 + +举例:umount /bin1/vs/sd + +## 输出说明 + +将已在/bin1/vs/sd挂载的文件系统卸载 + +**图 1** umount输出示例 +![](figure/umount输出示例.png "umount输出示例") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md new file mode 100644 index 0000000000000000000000000000000000000000..c94ac15b6a2074c51948a04bfe0e53181359c7a1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file-write.md @@ -0,0 +1,69 @@ +# writeproc + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +proc fs支持传入字符串参数,需要每个文件实现自己的写方法。 + +## 命令格式 + +writeproc <_data_\> \>\> /proc/<_filename_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

data

+

要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。

+

N/A

+

filename

+

data要传入的proc文件。

+

N/A

+
+ +## 使用指南 + +proc文件实现自身的write函数,调用writeproc命令后会将入参传入write函数。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>procfs不支持多线程访问。 + +## 使用实例 + +举例:writeproc test \>\> /proc/uptime + +## 输出说明 + +OHOS \# writeproc test \>\> /proc/uptime + +\[INFO\]write buf is: test + +test \>\> /proc/uptime + +>![](../public_sys-resources/icon-note.gif) **说明:** +>uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md new file mode 100644 index 0000000000000000000000000000000000000000..f2d8302ca40447c34683eec77ec1d78c9275fcc6 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-file.md @@ -0,0 +1,45 @@ +# 文件命令 + +- **[cat](kernel-lite-small-shell-cmd-file-cat.md)** + +- **[cd](kernel-lite-small-shell-cmd-file-cd.md)** + +- **[chgrp](kernel-lite-small-shell-cmd-file-chgrp.md)** + +- **[chmod](kernel-lite-small-shell-cmd-file-chmod.md)** + +- **[chown](kernel-lite-small-shell-cmd-file-chown.md)** + +- **[cp](kernel-lite-small-shell-cmd-file-cp.md)** + +- **[format](kernel-lite-small-shell-cmd-file-format.md)** + +- **[ls](kernel-lite-small-shell-cmd-file-is.md)** + +- **[lsfd](kernel-lite-small-shell-cmd-file-isfd.md)** + +- **[mkdir](kernel-lite-small-shell-cmd-file-mkdir.md)** + +- **[mount](kernel-lite-small-shell-cmd-file-mount.md)** + +- **[partinfo](kernel-lite-small-shell-cmd-file-part.md)** + +- **[partition](kernel-lite-small-shell-cmd-file-partion.md)** + +- **[pwd](kernel-lite-small-shell-cmd-file-pwd.md)** + +- **[rm](kernel-lite-small-shell-cmd-file-rm.md)** + +- **[rmdir](kernel-lite-small-shell-cmd-file-rmdir.md)** + +- **[statfs](kernel-lite-small-shell-cmd-file-sta.md)** + +- **[sync](kernel-lite-small-shell-cmd-file-sync.md)** + +- **[touch](kernel-lite-small-shell-cmd-file-touch.md)** + +- **[writeproc](kernel-lite-small-shell-cmd-file-write.md)** + +- **[umount](kernel-lite-small-shell-cmd-file-umount.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md new file mode 100644 index 0000000000000000000000000000000000000000..bc083f86ce0e71e81429707cec8f586d39243d92 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-mag.md @@ -0,0 +1,38 @@ +# 魔法键使用方法 + +- [使用场景](#section2350114718546) +- [使用方法](#section3305151511559) + +## 使用场景 + +在系统运行出现无响应等情况时,可以通过魔法键功能确定系统是否被锁中断(魔法键也无响应)或者查看系统任务运行状态等信息。 + +在中断有响应的情况下,可以通过魔法键查看task信息中 cpup(CPU占用率)看是哪个任务长时间占用CPU导致系统其他任务无响应(一般为比较高优先级任务一直抢占CPU,导致低优先级任务无响应)。 + +## 使用方法 + +1. 配置宏LOSCFG\_ENABLE\_MAGICKEY。 + +魔法键依赖于宏LOSCFG\_ENABLE\_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”: + +Debug ---\> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>1. 可以在menuconfig中,将光标移动到LOSCFG\_ENABLE\_MAGICKEY上,输入“?”,查看帮助信息。 + +2. 输入“ctrl + r”键,打开魔法键检测功能。 + +在连接UART或者USB转虚拟串口的情况下,输入“ctrl + r” 键,打开魔法键检测功能,输出 “Magic key on”;再输入一次后,则关闭魔法键检测功能,输出“Magic key off”。魔法键功能如下: + +- ctrl + z:帮助键,输出相关魔法键简单介绍; + +- ctrl + t:输出任务相关信息; + +- ctrl + p:系统主动进入panic,输出panic相关信息后,系统会挂住; + +- ctrl + e:系统进行简单完整性内存池检查,检查出错会输出相关错误信息,检查正常会输出“system memcheck over, all passed!”。 + + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>魔法键检测功能打开情况下,如果需要通过UART或者USB转虚拟串口输入特殊字符需避免与魔法键值重复,否则魔法键会被误触发,而原有设计功能可能出现错误。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md new file mode 100644 index 0000000000000000000000000000000000000000..7ff926b41044eafc1ce54354c4c1dabefd753468 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-arp.md @@ -0,0 +1,114 @@ +# arp + +- [命令功能](#section201149459368) +- [命令格式](#section579813484364) +- [参数说明](#section168065311366) +- [使用指南](#section19190125723612) +- [使用实例](#section10383416372) + +## 命令功能 + +在以太网中,主机之间的通信是直接使用MAC地址(非IP地址)来通信的,所以,对于使用IP通信的协议,必须能够将IP地址转换成MAC地址,才能在局域网(以太网)内通信。解决这个问题的方法就是主机存储一张IP和MAC地址对应的表,即ARP缓存,主机要往一个局域网内的目的IP地址发送IP包时,就可以从ARP缓存表中查询到目的MAC地址。ARP缓存是由TCP/IP协议栈维护的,用户可通过ARP命令查看和修改ARP表。 + +## 命令格式 + +arp + +arp \[_-i IF_\] -s _IPADDR HWADDR_ + +arp \[_-i IF_\] -d _IPADDR_ + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

+

打印整个ARP缓存的内容。

+

N/A

+

-i IF

+

指定的网络接口(可选参数)。

+

N/A

+

-s IPADDR

+

HWADDR

+

增加一条ARP表项,后面的参数是局域网中另一台主机的IP地址及其对应的MAC地址。

+

N/A

+

-d IPADDR

+

删除一条ARP表项。

+

N/A

+
+ +## 使用指南 + +- arp命令用来查询和修改TCP/IP协议栈的ARP缓存表,增加非同一子网内的IP地址的ARP表项是没有意义的,协议栈会返回失败。 +- 命令需要启动TCP/IP协议栈后才能使用。 + +## 使用实例 + +举例: + +1. 输入arp + + **图 1** 打印整个 ARP 缓存表 + + + ![](figure/Snipaste_2021-01-26_10-38-58.png) + + **表 2** 参数说明 + + + + + + + + + + + + + + + + + + + +

参数

+

说明

+

Address

+

表示网络设备的IPv4地址。

+

HWaddress

+

表示网络设备的MAC地址。

+

Iface

+

表示该ARP表项使用的接口名。

+

Type

+

表示该ARP表项是动态的还是静态的,动态是指ARP表项由协议栈自动创建,静态是指ARP表项是由用户增加的。

+
+ + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md new file mode 100644 index 0000000000000000000000000000000000000000..05d883c72b22b3a4500af3b13cb9cae3bb5a3f47 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dh.md @@ -0,0 +1,138 @@ +# dhclient + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +设置和查看dhclient的参数。 + +## 命令格式 + +dhclient <_netif name_\> + +dhclient -x <_netif name_\> + +dhclient -gb <_netif name_\> + +dhclient -sv <_vendor_\> + +dhclient -gv + +dhclient -gd <_index_\> + +dhclient -sd <_dns\_ip_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

<netif name>

+

启动对应网卡的dhcp请求。

+

网卡名字,eth0。

+

-x <netif name>

+

关闭对应网卡的dhcp功能。

+

网卡名字,eth0。

+

-gb <netif name>

+

查看对应网卡的dhcp请求是否完成。

+

网卡名字,eth0。

+

-sv <vendor>

+

设置dhcp请求的厂商信息。

+

厂商信息,长度是32个字符。

+

-gv

+

查看dhcp请求的厂商信息。

+

N/A

+

-gd <index>

+

获取第index个dns server的信息。

+

index,0或者1。

+

-sd <dns_ip>

+

设置主dns server的ip。

+

dns的ip地址。

+
+ +## 使用指南 + +dhclient eth0 + +dhclient -x eth0 + +dhclient -gb eth0 + +dhclient -sv MFSI + +dhclient -gv + +dhclient -gd 0 + +dhclient -sd 8.8.8.8 + +## 使用实例 + +![](figure/zh-cn_image_0000001053224218.png) + +## 输出说明 + +**表 2** 输出说明 + + + + + + + + + + + + + +

输出

+

说明

+

dhclient: set vendor info [MFSI] success

+

设置厂商信息MFSI信息成功。

+

dns[0]: 192.168.1.100

+

dns server ip地址为192.168.1.100。

+
+ diff --git a/zh-cn/device-dev/kernel/dns.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dns.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/dns.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-dns.md diff --git a/zh-cn/device-dev/kernel/ifconfig.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipc.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ifconfig.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipc.md diff --git a/zh-cn/device-dev/kernel/ipdebug.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipd.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ipdebug.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ipd.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md new file mode 100644 index 0000000000000000000000000000000000000000..b35a6494a18a56fe021cab3206b146565794c382 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-net.md @@ -0,0 +1,83 @@ +# netstat + +- [命令功能](#section13469162113816) +- [命令格式](#section795712373812) +- [参数说明](#section17629431193817) +- [使用指南](#section5277153519380) +- [使用实例](#section108141437163820) +- [输出说明](#section1357015107117) + +## 命令功能 + +netstat是控制台命令,是一个监测TCP/IP网络的非常有用的工具,它可以显示实际的网络连接以及每一个网络接口设备的状态信息。netstat用于显示与TCP、UDP协议相关的统计数据,一般用于检验本设备(单板)各端口的网络连接情况。 + +## 命令格式 + +netstat + +## 参数说明 + +无 + +## 使用指南 + +直接输入命令。 + +## 使用实例 + +举例:输入netstat + +**图 1** netstat 打印信息 + + +![](figure/Snipaste_2021-01-26_10-38-58-18.png) + +## 输出说明 + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

Proto

+

协议类型。

+

Recv-Q

+

未被用户读取的数据量。

+

对于Listen TCP,此值为已完成三次握手,但是未被用户accept的TCP连接的数量。

+

Send-Q

+

对TCP连接,已发送但未确认的数据量。

+

对UDP连接,由于IP地址解析未完成而缓存的数据量。

+

Local Address

+

本地地址和端口。

+

Foreign Address

+

远程地址和端口。

+

State

+

TCP连接状态,UDP此项无意义。

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 + diff --git a/zh-cn/device-dev/kernel/ntpdate.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ntp.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ntpdate.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ntp.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md new file mode 100644 index 0000000000000000000000000000000000000000..e1792bc92dd3871588ca67e12a7b56fdc6434230 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping.md @@ -0,0 +1,99 @@ +# ping + +- [命令功能](#section119672573385) +- [命令格式](#section869419010390) +- [参数说明](#section9877183173918) +- [使用指南](#section1097046193914) +- [使用实例](#section14564129113911) +- [输出说明](#section1621732891215) + +## 命令功能 + +ping命令用于测试网络连接是否正常。 + +## 命令格式 + +ping_ _\[_-n cnt_\] \[_-w interval_\] \[_-l data\_len_\]_ _ + +ping \[_-t_\] \[_-w interval_\] __ + +ping _-k_ + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

IP

+

要测试是否网络连通的IPv4地址。

+

N/A

+

-n cnt

+

执行的次数,不带本参数则默认为4次。

+

1-65535

+

-w interval

+

发送两次ping包的时间间隔,单位毫秒。

+

>0

+

-l data_len

+

ping包,即ICMP echo request报文的数据长

+

度,不包含ICMP包头。

+

0-65500

+

-t

+

表示永久ping,直到使用ping -k杀死ping线

+

程。

+

N/A

+

-k

+

杀死ping线程,停止ping。

+

N/A

+
+ +## 使用指南 + +- ping命令用来测试到目的IP的网络连接是否正常,参数为目的IP地址。 +- 如果目的IP不可达,会显示请求超时。 +- 如果显示发送错误,说明没有到目的IP的路由。 +- 命令需要启动TCP/IP协议栈后才能使用。 + +## 使用实例 + +举例:输入ping 192.168.1.10 + +## 输出说明 + +**图 1** ping tftp 服务器地址 + + +![](figure/Snipaste_2021-01-26_10-38-58-19.png) + diff --git a/zh-cn/device-dev/kernel/ping6.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping6.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/ping6.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-ping6.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md new file mode 100644 index 0000000000000000000000000000000000000000..95e8083c8022da0e67f3e192e8e1fbcb1655c4ce --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tel.md @@ -0,0 +1,65 @@ +# telnet + +- [命令功能](#section3551830123913) +- [命令格式](#section14897133233918) +- [参数说明](#section977718353392) +- [使用指南](#section134991538183916) +- [使用实例](#section1097414426398) +- [输出说明](#section11846624191310) + +## 命令功能 + +本命令用于启动或关闭telnet server服务。 + +## 命令格式 + +telnet \[_on | off_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

on

+

启动telnet server服务。

+

N/A

+

off

+

关闭telnet server服务。

+

N/A

+
+ +## 使用指南 + +- telnet启动要确保网络驱动及网络协议栈已经初始化完成,且板子的网卡是link up状态。 +- 暂时无法支持多个客户端(telnet + IP)同时连接开发板。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >telnet属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 + + +## 使用实例 + +举例:输入telnet on + +## 输出说明 + +**图 1** 输入 telnet on +![](figure/输入-telnet-on.png "输入-telnet-on") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md new file mode 100644 index 0000000000000000000000000000000000000000..d0a864992ff0d8fe6fb95c5b408eaf9e0b17fc4b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net-tftp.md @@ -0,0 +1,87 @@ +# tftp + +- [命令功能](#section15142134573911) +- [命令格式](#section20958174917394) +- [参数说明](#section576613532395) +- [使用指南](#section149795134408) +- [使用实例](#section148921918114015) +- [输出说明](#section7872155631313) + +## 命令功能 + +TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供简单、低开销的文件传输服务。端口号为69。 + +tftp命令可以从TFTP服务器上下载文件。 + +## 命令格式 + +./bin/tftp _<-g/-p\>_ _-l_ _\[FullPathLocalFile\] -r \[RemoteFile\] \[Host\]_ + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

-g/-p

+

文件传输方向:

+
  • -g 从TFTP服务器获取文件。
  • -p 上传文件到TFTP服务器。
+

N/A

+

-l FullPathLocalFile

+

本地文件完整路径。

+

N/A

+

-r RemoteFile

+

服务端文件名。

+

N/A

+

Host

+

服务端IP。

+

N/A

+
+ +## 使用指南 + +1. 在服务器端搭建TFTP服务器,并进行正确配置。 +2. OpenHarmony单板使用tftp命令上传、下载文件。 +3. 传输的文件大小是有限制的不能大于32M。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >tftp属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 + + +## 使用实例 + +举例:从服务器下载out文件。 + +## 输出说明 + +``` +OHOS # ./bin/tftp -g -l /nfs/out -r out 192.168.1.2 +TFTP transfer finish +``` + +tftp命令执行后,传输正常完成会显示TFTP transfer finish, 失败的话会显示其他的打印信息帮助定位问题。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md new file mode 100644 index 0000000000000000000000000000000000000000..6695d35058d5c51b722eeb73330d33d312861002 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-net.md @@ -0,0 +1,25 @@ +# 网络命令 + +- **[arp](kernel-lite-small-shell-cmd-net-arp.md)** + +- **[dhclient](kernel-lite-small-shell-cmd-net-dh.md)** + +- **[dns](kernel-lite-small-shell-cmd-net-dns.md)** + +- **[ifconfig](kernel-lite-small-shell-cmd-net-ipc.md)** + +- **[ipdebug](kernel-lite-small-shell-cmd-net-ipd.md)** + +- **[netstat](kernel-lite-small-shell-cmd-net-net.md)** + +- **[ntpdate](kernel-lite-small-shell-cmd-net-ntp.md)** + +- **[ping](kernel-lite-small-shell-cmd-net-ping.md)** + +- **[ping6](kernel-lite-small-shell-cmd-net-ping6.md)** + +- **[telnet](kernel-lite-small-shell-cmd-net-tel.md)** + +- **[tftp](kernel-lite-small-shell-cmd-net-tftp.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md new file mode 100644 index 0000000000000000000000000000000000000000..5d9bf1de8a7e21bf2e07681ba275a02ff007c638 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-cpup.md @@ -0,0 +1,65 @@ +# cpup + +- [命令功能](#section1842161614217) +- [命令格式](#section5629527427) +- [参数说明](#section133651361023) +- [使用指南](#section156611948521) +- [使用实例](#section68501605319) +- [输出说明](#section19871522144219) + +## 命令功能 + +cpup命令用于查询系统CPU的占用率。 + +## 命令格式 + +cpup \[_mode_\] \[_taskID_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

mode

+

● 缺省:显示系统最近10s内的CPU占用率。

+

● 0:显示系统最近10s内的CPU占用率。

+

● 1:显示系统最近1s内的CPU占用率。

+

● 其他数字:显示系统启动至今总的CPU 占用率。

+

[0,0xFFFFFFFF]

+

taskID

+

任务ID号

+

[0,0xFFFFFFFF]

+
+ +## 使用指南 + +- 参数缺省时,显示系统10s前的CPU占用率。 +- 只有一个参数时,该参数为mode,显示系统相应时间前的CPU占用率。 +- 输入两个参数时,第一个参数为mode,第二个参数为taskID,显示对应ID号任务的相应时间前的CPU占用率。 + +## 使用实例 + +举例:输入cpup 1 5 + +## 输出说明 + +**图 1** 指令输出结果 +![](figure/指令输出结果.png "指令输出结果") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md new file mode 100644 index 0000000000000000000000000000000000000000..0ee6698e2fc9e1960b5a7a45474570e80633eb9d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-date.md @@ -0,0 +1,94 @@ +# date + +- [命令功能](#section56472016338) +- [命令格式](#section16635112512316) +- [参数说明](#section15896030039) +- [使用指南](#section116361036636) +- [使用实例](#section021711411237) +- [输出说明](#section17950184414312) + +## 命令功能 + +date命令用于查询及设置系统日期和时间。 + +## 命令格式 + +date + +date --help + +date +\[_Format_\] + +date -s_ _\[_YY/MM/DD_\] + +date_ _-s_ _\[_hh:mm:ss_\]__ + +date -r \[_Filename_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

--help

+

使用帮助。

+

N/A

+

+Format

+

根据Format格式打印日期和时间。

+

--help中列出的占位符。

+

-s YY/MM/DD

+

设置系统时间,用“/”分割的年月日。

+

>= 1970/01/01

+

-s hh:mm:ss

+

设置系统时间,用“:”分割的时分秒。

+

N/A

+

-r Filename

+

查询Filename文件的修改时间。

+

N/A

+
+ +## 使用指南 + +- date参数缺省时,默认显示当前系统日期和时间。 +- --help、+Format、-s、-r不能混合使用。 + +## 使用实例 + +举例: + +输入date +%Y--%m--%d。 + +## 输出说明 + +**图 1** 按指定格式打印系统日期 +![](figure/按指定格式打印系统日期.png "按指定格式打印系统日期") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md new file mode 100644 index 0000000000000000000000000000000000000000..b4e1bbd9eea0c4955f75c2d309474e0ee5a9accf --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-demsg.md @@ -0,0 +1,113 @@ +# dmesg + +- [命令功能](#section4643204919313) +- [命令格式](#section6553153635) +- [参数说明](#section208971157532) +- [使用指南](#section213115219413) +- [使用实例](#section13736564418) +- [输出说明](#section194005101413) + +## 命令功能 + +dmesg命令用于控制内核dmesg缓存区。 + +## 命令格式 + +dmesg + +dmesg \[_-c/-C/-D/-E/-L/-U_\] + +dmesg -s \[_size_\] + +dmesg -l \[_level_\] + +dmesg \> \[_fileA_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

-c

+

打印缓存区内容并清空缓存区。

+

N/A

+

-C

+

清空缓存区。

+

N/A

+

-D/-E

+

关闭/开启控制台打印。

+

N/A

+

-L/-U

+

关闭/开启串口打印。

+

N/A

+

-s size

+

设置缓存区大小 size是要设置的大小。

+

N/A

+

-l level

+

设置缓存等级。

+

0 - 5

+

> fileA

+

将缓存区内容写入文件。

+

N/A

+
+ +## 使用指南 + +- 该命令依赖于LOSCFG\_SHELL\_DMESG,使用时通过menuconfig在配置项中开启"Enable Shell dmesg": + + Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell dmesg + +- dmesg参数缺省时,默认打印缓存区内容。 +- 各“ - ”选项不能混合使用。 + 1. 写入文件需确保已挂载文件系统。 + 2. 关闭串口打印会影响shell使用,建议先连接telnet再尝试关闭串口。 + + +## 使用实例 + +举例: + +输入dmesg \> /usr/dmesg.log。 + +## 输出说明 + +**图 1** dmesg重定向到文件。 +![](figure/dmesg重定向到文件.png "dmesg重定向到文件") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md new file mode 100644 index 0000000000000000000000000000000000000000..c5e437ad7ce79baac800f459b108e50f1c5e9fc2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-exec.md @@ -0,0 +1,60 @@ +# exec + +- [命令功能](#section4643204919313) +- [命令格式](#section6553153635) +- [参数说明](#section208971157532) +- [使用指南](#section213115219413) +- [使用实例](#section13736564418) +- [输出说明](#section194005101413) + +## 命令功能 + +exec命令属于shell内置命令,目前实现最基础的执行用户态程序的功能。 + +## 命令格式 + +exec <_executable-file_\> + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

executable-file

+

有效的可执行文件。

+

N/A

+
+ +## 使用指南 + +该命令当前仅支持执行有效的二进制程序,程序成功执行,默认后台运行,但与Shell共用终端,可能会导致程序打印输出与Shell输出交错显示。 + +## 使用实例 + +举例: + +输入exec helloworld。 + +## 输出说明 + +``` +OHOS # exec helloworld +OHOS # hello world! +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>可执行文件执行后,先打印“OHOS \#”提示符原因:目前Shell “exec”命令执行均为后台执行,结果可能导致提示符提前打印。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md new file mode 100644 index 0000000000000000000000000000000000000000..dcfdc363829fad59170e29da6a16c06a523d86c1 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-free.md @@ -0,0 +1,119 @@ +# free + +- [命令功能](#section175151514841) +- [命令格式](#section8488721749) +- [参数说明](#section27272181949) +- [使用指南](#section148661259410) +- [使用实例](#section68081530242) +- [输出说明](#section171235517543) + +## 命令功能 + +free命令可显示系统内存的使用情况,同时显示系统的text段、data段、rodata段、bss段大小。 + +## 命令格式 + +free \[_-k | -m_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

无参数

+

以Byte为单位显示。

+

N/A

+

-k

+

以KB为单位显示。

+

N/A

+

-m

+

以MB为单位显示。

+

N/A

+
+ +## 使用指南 + +无。 + +## 使用实例 + +举例:分别输入free、free -k、free -m. + +## 输出说明 + +**图 1** 以三种方式显示内存使用情况 +![](figure/以三种方式显示内存使用情况.png "以三种方式显示内存使用情况") + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

total

+

表示系统动态内存池总量。

+

used

+

表示已使用内存总量。

+

free

+

表示未被分配的内存大小。

+

heap

+

表示已分配堆大小。

+

text

+

表示代码段大小。

+

data

+

表示数据段大小。

+

rodata

+

表示只读数据段大小。

+

bss

+

表示未初始化全局变量占用内存大小。

+
+ diff --git a/zh-cn/device-dev/kernel/help.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-help.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/help.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-help.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md new file mode 100644 index 0000000000000000000000000000000000000000..9414e1f74464147595229f46315a108d4b531eb5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-hwi.md @@ -0,0 +1,94 @@ +# hwi + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +hwi命令查询当前中断信息 + +## 命令格式 + +hwi + +## 参数说明 + +无。 + +## 使用指南 + +- 输入hwi即显示当前中断号、中断次数及注册中断名称。 +- 若开关LOSCFG\_CPUP\_INCLUDE\_IRQ打开,则还会显示各个中断的处理时间(cycles)、CPU占用率以及中断类型。 + +## 使用实例 + +举例:输入hwi + +## 输出说明 + +1. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ关闭) + + ![](figure/zh-cn_image_0000001053826366.png) + +2. 显示中断信息(LOSCFG\_CPUP\_INCLUDE\_IRQ打开) + + ![](figure/zh-cn_image_0000001052810304.png) + + **表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

InterruptNo

+

中断号。

+

Count

+

中断次数。

+

Name

+

注册中断名称。

+

CYCLECOST

+

中断的处理时间(cycles)。

+

CPUUSE

+

CPU占用率。

+

CPUUSE10s

+

最近10s CPU占用率。

+

CPUUSE1s

+

最近1s CPU占用率。

+

mode

+

中断类型:

+
  • normal: 非共享中断。
  • shared: 共享中断。
+
+ + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md new file mode 100644 index 0000000000000000000000000000000000000000..6f1447fbdaa40653977a87780e2d690f953945b5 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-kill.md @@ -0,0 +1,82 @@ +# kill + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +命令用于发送特定信号给指定进程。 + +## 命令格式 + +kill \[_signo_ | _-signo_\] \[_pid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

signo

+

信号ID。

+

[1,30]

+

pid

+

进程ID。

+

[1,MAX_INT]

+
+ +>![](../public_sys-resources/icon-notice.gif) **须知:** +>signo有效范围为\[0,64\],建议取值范围为\[1,30\],其余为保留内容。 + +## 使用指南 + +必须指定发送的信号编号及进程号。 + +进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为\[1-256\]。 + +## 使用实例 + +1. 查看当前进程列表,查看需要杀死的进程PID(7)。 + +**图 1** 查看进程PID +![](figure/查看进程PID.png "查看进程PID") + +2. 发送信号14(SIGALRM默认行为为进程终止)给7号进程**helloworld\_d**(用户态进程):**kill 14 7**(kill -14 7效果相同),并查看当前进程列表,7号进程已终止。 + +**图 2** 信号发送结果图 +![](figure/信号发送结果图.png "信号发送结果图") + +## 输出说明 + +发送成功或失败输出结果如下。 + +**图 3** 发送信号给指定进程 +![](figure/发送信号给指定进程.png "发送信号给指定进程") + +信号发送会显示发送记录,未报错表示信号发送成功。 + +**图 4** 信号发送失败 +![](figure/信号发送失败.png "信号发送失败") + +信号发送失败,上图所示原因为信号发送命令参数无效,请排查信号编号及进程编号是否无效。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md new file mode 100644 index 0000000000000000000000000000000000000000..cdadf9859311d2840f490852045b69d409458ad7 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-log.md @@ -0,0 +1,74 @@ +# log + +- [命令功能](#section128219131856) +- [命令格式](#section3894181710519) +- [参数说明](#section7693122310515) +- [使用指南](#section1982111281512) +- [使用实例](#section176301333259) +- [输出说明](#section14354765415) + +## 命令功能 + +log命令用于修改&查询日志配置。 + +## 命令格式 + +log level \[_levelNum_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

levelNum

+

配置日志打印等级。

+

[0x0,0x5]

+
+ +## 使用指南 + +- 该命令依赖于LOSCFG\_SHELL\_LK,使用时通过menuconfig在配置项中开启"Enable Shell lk": + + Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell lK。 + +- log level命令用于配置日志的打印等级,包括6个等级 + + TRACE\_EMG = 0, + + TRACE\_COMMON = 1, + + TRACE\_ERROR = 2, + + TRACE\_WARN = 3, + + TRACE\_INFO = 4, + + TRACE\_DEBUG = 5 + + 若level不在有效范围内,会打印提示信息。 + +- 若log level命令不加\[levelNum\]参数,则默认查看当前打印等级,并且提示使用方法。 + +## 使用实例 + +举例: + +输入log level 4 + +## 输出说明 + +![](figure/zh-cn_image_0000001052530298.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md new file mode 100644 index 0000000000000000000000000000000000000000..8ff0289bcde30ca0918de0c07ef25194ec5db461 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-mem.md @@ -0,0 +1,38 @@ +# memcheck + +- [命令功能](#section191633812516) +- [命令格式](#section428816435510) +- [参数说明](#section1939943304411) +- [使用指南](#section228914491951) +- [使用实例](#section17373205314515) +- [输出说明](#section13406205385413) + +## 命令功能 + +检查动态申请的内存块是否完整,是否存在内存越界造成节点损坏。 + +## 命令格式 + +memcheck + +## 参数说明 + +无。 + +## 使用指南 + +- 当内存池所有节点完整时,输出"system memcheck over, all passed!"。 +- 当内存池存在节点不完整时,输出被损坏节点的内存块信息。 + +## 使用实例 + +举例:输入memcheck + +## 输出说明 + +**图 1** 当前没有内存越界 +![](figure/当前没有内存越界.png "当前没有内存越界") + +**图 2** 出现内存越界 +![](figure/出现内存越界.png "出现内存越界") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md new file mode 100644 index 0000000000000000000000000000000000000000..e21772b94ea31d1251aa05fcf421ae668bcd6643 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-oom.md @@ -0,0 +1,120 @@ +# oom + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section12742311179) + +## 命令功能 + +查看和设置低内存阈值以及pagecache内存回收阈值。 + +## 命令格式 + +oom + +oom -i \[_interval_\] + +oom -m \[_mem byte_\] + +oom -r \[_mem byte_\] + +oom -h | --help + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

-i [interval]

+

设置oom线程任务检查的时间间隔。

+

100ms ~ 10000ms

+

-m [mem byte]

+

设置低内存阈值。

+

0MB ~ 1MB,0MB表示不做低内存阈值检查。

+

-r [mem byte]

+

设置pagecache内存回收阈值。

+

低内存阈值 ~ 系统可用最大内存。

+

-h | --help

+

使用帮助。

+

N/A

+
+ +## 使用指南 + +- 参数缺省时,显示oom功能当前配置信息。 + +## 使用实例 + +当系统内存不足时,会打印出内存不足的提示信息。 + +## 输出说明 + +![](figure/zh-cn_image_0000001053710680.png) + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

[oom] OS is in low memory state

+

total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte), free: 0x7f000(byte), low memory threshold: 0x80000(byte)

+

操作系统处于低内存状态。

+

整个系统可用物理内存为0x1bcf000 byte,已经使用了 0x1b50000 byte, 还剩0x7f000 byte,当前设置的低内存阈值为0x80000 byte。

+

[oom] candidate victim process init pid: 1, actual phy mem byte: 82602

+

打印当前各个进程的内存使用情况,init进程实际使用82602byte,其中共享内存按照比例算的。

+

[oom] candidate victim process UserProcess12 pid: 12, actual phy mem byte: 25951558

+

UserProcess12进程实际使用25951558byte内存。

+

[oom] max phy mem used process UserProcess12 pid: 12, actual phy mem: 25951558

+

当前使用内存最多的进程是UserProcess12。

+

excFrom: User!

+

当系统处于低内存的情况下,UserProcess12进程再去申请内存时失败退出。

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md new file mode 100644 index 0000000000000000000000000000000000000000..067433a0b8361351014f52bbe6cb02c523cc1489 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-pmm.md @@ -0,0 +1,91 @@ +# pmm + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +查看系统内存物理页及pagecache物理页使用情况。 + +## 命令格式 + +pmm + +## 参数说明 + +无 + +## 使用指南 + +Debug版本才具备的命令。 + +## 使用实例 + +输入pmm + +## 输出说明 + +**图 1** 查看物理页使用情况 +![](figure/查看物理页使用情况.png "查看物理页使用情况") + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

phys_seg

+

物理页控制块地址信息

+

base

+

第一个物理页地址,即物理页内存起始地址

+

size

+

物理页内存大小

+

free_pages

+

空闲物理页数量

+

active anon

+

pagecache中,活跃的匿名页数量

+

inactive anon

+

pagecache中,不活跃的匿名页数量

+

active file

+

pagecache中,活跃的文件页数量

+

inactive file

+

pagecache中,不活跃的文件页数量

+

pmm pages

+

total:总的物理页数,used:已使用的物理页数,free:空闲的物理页数

+
+ diff --git a/zh-cn/device-dev/kernel/reset.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-reset.md old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/kernel/reset.md rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-reset.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md new file mode 100644 index 0000000000000000000000000000000000000000..4a27c8d10ba557d0821195e56b5d1c930fe1c627 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sem.md @@ -0,0 +1,91 @@ +# sem + +- [命令功能](#section366714216619) +- [命令格式](#section8833164614615) +- [参数说明](#section12809111019453) +- [使用指南](#section15935131220717) +- [使用实例](#section79281818476) +- [输出说明](#section1975118519456) + +## 命令功能 + +sem命令用于查询系统内核信号量相关信息。 + +## 命令格式 + +sem \[_ID__ / fulldata_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

ID

+

信号ID号。

+

[0, 0xFFFFFFFF]

+

fulldata

+

查询所有在用的信号量信息,打印信息包括如下:SemID, Count, Original Count, Creater TaskEntry, Last Access Time。

+

N/A

+
+ +## 使用指南 + +- 参数缺省时,显示所有的信号量的使用数及信号量总数。 +- sem后加ID,显示对应ID信号量的使用数。 +- 参数fulldata依赖于LOSCFG\_DEBUG\_SEMAPHORE,使用时通过menuconfig在配置项中开启"Enable Semaphore Debugging": + + Debug ---\> Enable a Debug Version ---\> Enable Debug LiteOS Kernel Resource ---\> Enable Semaphore Debugging + + +## 使用实例 + +举例1:输入 sem fulldata + +## 输出说明 + +**图 1** 查询所有在用的信号量信息 +![](figure/查询所有在用的信号量信息.png "查询所有在用的信号量信息") + +**表 2** 输出说明 + + + + + + + + + + + + + +

输出

+

说明

+

SemID

+

信号量ID。

+

Count

+

信号量使用数。

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>● sem命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 +>● sem命令的ID参数在\[0, 1023\]范围内时,返回对应ID的信号量的状态(如果对应ID的信号量未被使用则进行提示);其他取值时返回参数错误的提示。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md new file mode 100644 index 0000000000000000000000000000000000000000..8f2904a4b88d28fed4d39423b8ed85de468fb5be --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-stack.md @@ -0,0 +1,73 @@ +# stack + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +查看系统各堆栈使用情况。 + +## 命令格式 + +stack + +## 参数说明 + +无。 + +## 使用指南 + +无。 + +## 使用实例 + +输入:stack + +## 输出说明 + +**图 1** 系统堆栈使用情况 + + +![](figure/zh-cn_image_0000001054624363.png) + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

stack name

+

系统堆栈名

+

cpu id

+

cpu 号

+

stack addr

+

栈地址

+

total size

+

堆栈大小

+

used size

+

堆栈实际使用大小

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md new file mode 100644 index 0000000000000000000000000000000000000000..a8536a0e4d713453a9cb71b85ad1adb692bfd0b2 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-su.md @@ -0,0 +1,62 @@ +# su + +- [命令功能](#section297810431676) +- [命令格式](#section157131147876) +- [参数说明](#section04145521671) +- [使用指南](#section14615155610719) +- [使用实例](#section13338150985) +- [输出说明](#section125021924194613) + +## 命令功能 + +su用于变更为其他使用者的身份。 + +## 命令格式 + +su \[_uid_\] \[_gid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

uid

+

目标用户的用户id值。

+
  • 为空。
  • [0,60000]
+

gid

+

目标用户的群组id值。

+
  • 为空。
  • [0,60000]
+
+ +## 使用指南 + +- su命令缺省切换到root用户,uid默认为0,gid为0。 +- 在su命令后的输入参数uid和gid就可以切换到该uid和gid的用户。 +- 输入参数超出范围时,会打印提醒输入正确范围参数。 + +## 使用实例 + +举例:su 1000 1000 + +## 输出说明 + +**图 1** **切换到**为uid为1000,gid为1000的用户 +![](figure/切换到为uid为1000-gid为1000的用户.png "切换到为uid为1000-gid为1000的用户") + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md new file mode 100644 index 0000000000000000000000000000000000000000..07b2b1b04293f87baa0cb9d47448d2913b594b12 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-swymr.md @@ -0,0 +1,110 @@ +# swtmr + +- [命令功能](#section166171064814) +- [命令格式](#section424011111682) +- [参数说明](#section1268410459465) +- [使用指南](#section169806213815) +- [使用实例](#section16676026389) +- [输出说明](#section1541991614710) + +## 命令功能 + +swtmr命令用于查询系统软件定时器相关信息。 + +## 命令格式 + +swtmr \[_ID_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

ID

+

软件定时器ID号。

+

[0,0xFFFFFFFF]

+
+ +## 使用指南 + +- 参数缺省时,默认显示所有软件定时器的相关信息。 +- swtmr后加ID号时,显示ID对应的软件定时器相关信息。 + +## 使用实例 + +举例:输入swtmr和swtmr 1 + +## 输出说明 + +**图 1** 查询所有软件定时器相关信息 +![](figure/查询所有软件定时器相关信息.png "查询所有软件定时器相关信息") + +**图 2** 查询对应 ID 的软件定时器信息 +![](figure/查询对应-ID-的软件定时器信息.png "查询对应-ID-的软件定时器信息") + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

SwTmrID

+

软件定时器ID。

+

State

+

软件定时器状态。

+

状态可能为:"UnUsed", "Created", "Ticking"。

+

Mode

+

软件定时器模式。

+

模式可能为:"Once", "Period", "NSD(单次定时器,定时结束后不会自动删除)"。

+

Interval

+

软件定时器使用的Tick数。

+

Count

+

软件定时器已经工作的次数。

+

Arg

+

传入的参数。

+

handlerAddr

+

回调函数的地址。

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>- swtmr命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 +>- swtmr命令的ID参数在\[0, 当前软件定时器个数 - 1\]范围内时,返回对应ID的软件定时器的状态;其他取值时返回错误提示。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md new file mode 100644 index 0000000000000000000000000000000000000000..8b59757af0093680a9f16f986e0f3bd864aa6fba --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-sys.md @@ -0,0 +1,91 @@ +# systeminfo + +- [命令功能](#section863016434820) +- [命令格式](#section139791817795) +- [参数说明](#section19472339164813) +- [使用指南](#section285522592) +- [使用实例](#section9471171015105) +- [输出说明](#section1657011114915) + +## 命令功能 + +systeminfo命令用于显示当前操作系统内资源使用情况,包括任务、信号量、互斥量、队列、定时器等。 + +## 命令格式 + +systeminfo + +## 参数说明 + +无。 + +## 使用指南 + +无。 + +## 使用实例 + +举例:输入systeminfo + +## 输出说明 + +**图 1** 查看系统资源使用情况 +![](figure/查看系统资源使用情况.png "查看系统资源使用情况") + +**表 1** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

Module

+

模块名称。

+

Used

+

当前使用量。

+

Total

+

最大可用量。

+

Enabled

+

模块是否开启。

+

Task

+

任务。

+

Sem

+

信号量。

+

Mutex

+

互斥量。

+

Queue

+

队列。

+

SwTmr

+

定时器。

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md new file mode 100644 index 0000000000000000000000000000000000000000..4fb2b3e3f8fcd34a9f102e4a2c75b00ff018445b --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-task.md @@ -0,0 +1,125 @@ +# task + +- [命令功能](#section0533181714106) +- [命令格式](#section1014412308101) +- [参数说明](#section116057158506) +- [使用指南](#section2053502951112) +- [使用实例](#section12629113381116) +- [输出说明](#section19299103465015) + +## 命令功能 + +task命令用于查询进程及线程信息。 + +## 命令格式 + +task/task -a + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

-a

+

查看更多信息。

+

N/A

+
+ +## 使用指南 + +- 参数缺省时默认打印部分任务信息。 + +## 使用实例 + +举例:输入task + +## 输出说明 + +**图 1** 查询任务部分信息 +![](figure/查询任务部分信息.png "查询任务部分信息") + +**表 2** 输出说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

PID

+

进程ID。

+

PPID

+

父进程ID。

+

PGID

+

进程组ID。

+

UID

+

用户ID。

+

Status

+

任务当前的状态。

+

CPUUSE10s

+

10秒内CPU使用率。

+

PName

+

进程名。

+

TID

+

任务ID。

+

StackSize

+

任务堆栈的大小。

+

WaterLine

+

栈使用的峰值。

+

MEMUSE

+

内存使用量。

+

TaskName

+

任务名。

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md new file mode 100644 index 0000000000000000000000000000000000000000..ff2c1b7a3db2ee050c384be9216102e3d8d30eeb --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-uname.md @@ -0,0 +1,72 @@ +# uname + +- [命令功能](#section107697383115) +- [命令格式](#section162824341116) +- [使用指南](#section2652124861114) +- [使用实例](#section0107995132) +- [输出说明](#section1215113245511) + +## 命令功能 + +uname命令用于显示当前操作系统的名称,版本创建时间,系统名称,版本信息等。 + +## 命令格式 + +uname \[_-a | -s | -t | -v | --help_\] + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

无参数

+

默认显示操作系统名称。

+

-a

+

显示全部信息。

+

-t

+

显示版本创建的时间。

+

-s

+

显示操作系统名称。

+

-v

+

显示版本信息。

+

--help

+

显示uname指令格式提示。

+
+ +## 使用指南 + +uname用于显示当前操作系统名称。语法uname -a | -t| -s| -v 描述uname 命令将正在使用的操作系统名写到标准输出中,这几个参数不能混合使用。 + +## 使用实例 + +举例:输入uname -a + +## 输出说明 + +查看系统信息 + +![](figure/zh-cn_image_0000001052370305.png) + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md new file mode 100644 index 0000000000000000000000000000000000000000..35f4ada41e1f7043ea60d584065662facf59f88a --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-vmm.md @@ -0,0 +1,158 @@ +# vmm + +- [命令功能](#section445335110416) +- [命令格式](#section1795712553416) +- [参数说明](#section92544592410) +- [使用指南](#section104151141252) +- [使用实例](#section11545171957) +- [输出说明](#section075617368542) + +## 命令功能 + +查看进程的虚拟内存使用情况。 + +## 命令格式 + +vmm \[_-a / -h / --help_\] + +vmm \[_pid_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

取值范围

+

-a

+

输出所有进程的虚拟内存使用情况

+

N/A

+

-h | --help

+

命令格式说明

+

N/A

+

pid

+

进程ID,说明指定进程的虚拟内存使用情况

+

[0,63]

+
+ +## 使用指南 + +命令缺省输出所有进程的虚拟内存使用情况。 + +## 使用实例 + +输入vmm 3 + +## 输出说明 + +**图 1** PID为3的进程虚拟内存使用信息 +![](figure/PID为3的进程虚拟内存使用信息.png "PID为3的进程虚拟内存使用信息") + +**表 2** 进程基本信息 + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

PID

+

进程ID

+

aspace

+

进程虚拟内存控制块地址信息

+

name

+

进程名

+

base

+

虚拟内存起始地址

+

size

+

虚拟内存大小

+

pages

+

已使用的物理页数量

+
+ +**表 3** 虚拟内存区间信息 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

输出

+

说明

+

region

+

虚拟区间控制块地址信息

+

name

+

虚拟区间类型

+

base

+

虚拟区间起始地址

+

size

+

虚拟区间大小

+

mmu_flags

+

虚拟区间mmu映射属性

+

pages

+

已使用的物理页数量(包括共享内存部分)

+

pg/ref

+

已使用的物理页数量

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md new file mode 100644 index 0000000000000000000000000000000000000000..c3adf787bbca3f7deb8165ed2c1d8e15204dd168 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys-watch.md @@ -0,0 +1,100 @@ +# watch + +- [命令功能](#section20643141481314) +- [命令格式](#section1075441721316) +- [参数说明](#section1472810220135) +- [使用指南](#section186772414131) +- [使用实例](#section4764192791314) +- [输出说明](#section5791253155517) + +## 命令功能 + +watch命令用于周期性的监视一个命令的运行结果。 + +## 命令格式 + +watch + +watch \[_-c/-n/-t/--count/--interval/-no-title/--over_\] \[_command_\] + +## 参数说明 + +**表 1** 参数说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

缺省值

+

取值范围

+

-c / --count

+

命令执行的总次数。

+

0xFFFFFF

+

(0,0xFFFFFF]

+

-n / --interval

+

命令周期性执行的时间间隔(s)。

+

1s

+

(0,0xFFFFFF]

+

-t / -no-title

+

关闭顶端的时间显示。

+

N/A

+

N/A

+

command

+

需要监测的命令。

+

N/A

+

N/A

+

--over

+

关闭当前监测指令。

+

N/A

+

N/A

+
+ +## 使用指南 + +watch运行过程中可以执行**watch --over**结束本次watch命令。 + +## 使用实例 + +输入举例: + +watch -n 2 -c 6 task + +## 输出说明 + +**图 1** watch task 结果 +![](figure/watch-task-结果.png "watch-task-结果") + +>![](../public_sys-resources/icon-note.gif) **说明:** +>示例中,总共有6次task命令打印,每次间隔2秒,截图为最后一次打印详情。 + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md new file mode 100644 index 0000000000000000000000000000000000000000..8bccc06e167edac3be5d99cf37d1aeb81427c730 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd-sys.md @@ -0,0 +1,47 @@ +# 系统命令 + +- **[cpup](kernel-lite-small-shell-cmd-sys-cpup.md)** + +- **[date](kernel-lite-small-shell-cmd-sys-date.md)** + +- **[dmesg](kernel-lite-small-shell-cmd-sys-demsg.md)** + +- **[exec](kernel-lite-small-shell-cmd-sys-exec.md)** + +- **[free](kernel-lite-small-shell-cmd-sys-free.md)** + +- **[help](kernel-lite-small-shell-cmd-sys-help.md)** + +- **[hwi](kernel-lite-small-shell-cmd-sys-hwi.md)** + +- **[kill](kernel-lite-small-shell-cmd-sys-kill.md)** + +- **[log](kernel-lite-small-shell-cmd-sys-log.md)** + +- **[memcheck](kernel-lite-small-shell-cmd-sys-mem.md)** + +- **[oom](kernel-lite-small-shell-cmd-sys-oom.md)** + +- **[pmm](kernel-lite-small-shell-cmd-sys-pmm.md)** + +- **[reset](kernel-lite-small-shell-cmd-sys-reset.md)** + +- **[sem](kernel-lite-small-shell-cmd-sys-sem.md)** + +- **[stack](kernel-lite-small-shell-cmd-sys-stack.md)** + +- **[su](kernel-lite-small-shell-cmd-sys-su.md)** + +- **[swtmr](kernel-lite-small-shell-cmd-sys-swymr.md)** + +- **[systeminfo](kernel-lite-small-shell-cmd-sys-sys.md)** + +- **[task](kernel-lite-small-shell-cmd-sys-task.md)** + +- **[uname](kernel-lite-small-shell-cmd-sys-uname.md)** + +- **[vmm](kernel-lite-small-shell-cmd-sys-vmm.md)** + +- **[watch](kernel-lite-small-shell-cmd-sys-watch.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md new file mode 100644 index 0000000000000000000000000000000000000000..95d4b92cffc8d087d40831a981d3f3f7828399a9 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-cmd.md @@ -0,0 +1,13 @@ +# Shell命令使用详解 + +本章节介绍了系统关键命令的功能、格式、参数范围、使用指南和使用实例。 + +不在本文档范围内的命令,详见[help](kernel-lite-small-shell-cmd-sys-help.md)命令的输出内容,也可以通过命令的“-h | --help”选项,查看该命令的使用帮助。 + +- **[系统命令](kernel-lite-small-shell-cmd-sys.md)** + +- **[文件命令](kernel-lite-small-shell-cmd-file.md)** + +- **[网络命令](kernel-lite-small-shell-cmd-net.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md new file mode 100644 index 0000000000000000000000000000000000000000..8b7909db2079b4225c6253fee4318d83c3afa16d --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-des.md @@ -0,0 +1,36 @@ +# Shell介绍 + +- [注意事项](#section12298165312328) + +OpenHarmony内核提供的Shell支持调试常用的基本功能,包含系统、文件、网络和动态加载相关命令。同时OpenHarmony内核的Shell支持添加新的命令,可以根据需求来进行定制。 + +- 系统相关命令:提供查询系统任务、内核信号量、系统软件定时器、CPU占用率、当前中断等相关信息的能力。 + +- 文件相关命令:支持基本的ls、cd等功能。 + +- 网络相关命令:支持查询接到开发板的其他设备的IP、查询本机IP、测试网络连接、设置开发板的AP和station模式等相关功能。 + + 新增命令的详细流程可参见[开发指导](kernel-lite-small-shell-guide.md)和[编程实例](kernel-lite-small-shell-sample.md)。 + + +## 注意事项 + +在使用Shell功能的过程中,需要注意以下几点: + +- Shell功能支持使用exec命令来运行可执行文件。 +- Shell功能支持默认模式下英文输入。如果出现用户在UTF-8格式下输入了中文字符的情况,只能通过回退三次来删除。 + +- Shell功能支持shell命令、文件名及目录名的Tab键联想补全。若有多个匹配项,则根据共同字符, 打印多个匹配项。对于过多的匹配项(打印多于24行),将会进行打印询问(Display all num possibilities?(y/n)),用户可输入y选择全部打印,或输入n退出打印,选择全部打印并打印超过24行后,会进行--More--提示,此时按回车键继续打印,按q键退出(支持Ctrl+c退出\)。 + +- Shell端工作目录与系统工作目录是分开的,即通过Shell端cd pwd等命令是对Shell端工作目录进行操作,通过chdir getcwd等命令是对系统工作目录进行操作,两个工作目录相互之间没有联系。当文件系统操作命令入参是相对路径时要格外注意。 + +- 在使用网络Shell指令前,需要先调用tcpip\_init函数完成网络初始化并完成telnet连接后才能起作用,内核默认不初始化tcpip\_init。 + +- 不建议使用Shell命令对/dev目录下的设备文件进行操作,这可能会引起不可预知的结果。 + +- Shell功能不符合POSIX标准,仅供调试使用。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >Shell功能仅供调试使用,在Debug版本中开启(使用时通过menuconfig在配置项中开启"LOSCFG\_DEBUG\_VERSION"编译开关进行相关控制),商用产品中禁止包含该功能。 + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..7f7327f6b2899440de2152975b099e6127d3d134 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell-guide.md @@ -0,0 +1,167 @@ +# Shell命令开发指导 + +- [开发指导](#section22071515161018) + +## 开发指导 + +新增Shell命令的典型开发流程如下: + +1. 包含如下头文件: + + ``` + #include "shell.h" + #include "shcmd.h" + ``` + +2. 注册命令。用户可以选择静态注册命令方式和系统运行时动态注册命令方式,静态注册命令方式一般用在系统常用命令注册,动态注册命令方式一般用在用户命令注册。 + + 1. 静态注册命令方式: + + 1. 通过宏的方式注册。 + + 这个宏的原型为: + + ``` + SHELLCMD_ENTRY(l, cmdType, cmdKey, paraNum, cmdHook) + ``` + + **表 1** SHELLCMD\_ENTRY参数详解 + + + + + + + + + + + + + + + + + + + + + + +

参数

+

描述

+

l

+

静态注册全局变量名(注意:不与系统中其他symbol重名)。

+

cmdType

+

命令类型:

+
  • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

    +
  • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

    +
+

cmdKey

+

命令关键字,函数在Shell中访问的名称。

+

paraNum

+

调用的执行函数的入参最大个数,暂不支持。

+

cmdHook

+

命令执行函数地址,即命令实际执行函数。

+
+ + 如: + + ``` + SHELLCMD_ENTRY(ls_shellcmd, CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) + ``` + + 2. 在build/mk/liteos\_tables\_ldflags.mk中添加相应选项: + + 如:上述“ls”命令注册时,需在build/mk/liteos\_tables\_ldflags.mk中添加“-uls\_shellcmd”。其中-u后面跟SHELLCMD\_ENTRY的第一个参数。 + + + 2. 动态注册命令方式: + + 注册函数原型: + + ``` + UINT32 osCmdReg(CmdT ype cmdType, CHAR *cmdKey, UINT32 paraNum, CmdCallBackFunc cmdProc) + ``` + + **表 2** UINT32 osCmdReg参数详解 + + + + + + + + + + + + + + + + + + + +

参数

+

描述

+

cmdType

+

命令类型:

+
  • CMD_TYPE_EX:不支持标准命令参数输入,会把用户填写的命令关键字屏蔽掉,例如:输入ls /ramfs,传入给注册函数的参数只有/ramfs,而ls命令关键字并不会被传入。

    +
  • CMD_TYPE_STD:支持的标准命令参数输入,所有输入的字符都会通过命令解析后被传入。

    +
+

cmdKey

+

命令关键字,函数在Shell中访问的名称。

+

paraNum

+

调用的执行函数的入参最大个数,暂不支持该参数;当前为默认值XARGS(0xFFFFFFFF)。

+

cmdHook

+

命令执行函数地址,即命令实际执行函数。

+
+ + 如: + + ``` + osCmdReg(CMD_TYPE_EX, "ls", XARGS, (CMD_CBK_FUNC)osShellCmdLs) + ``` + + + >![](../public_sys-resources/icon-note.gif) **说明:** + >命令关键字必须是唯一的,也即两个不同的命令项不能拥有相同的命令关键字,否则只会执行其中一个。 + >Shell在执行用户命令时,如果存在多个命令关键字相同的命令,只会执行其中在"help"命令中排序在最前面的一个。 + +3. 添加内置命令函数原型。 + + ``` + UINT32 osShellCmdLs(UINT32 argc, CHAR **argv) + ``` + + **表 3** osShellCmdLs参数说明 + + + + + + + + + + + + + +

参数

+

参数描述

+

argc

+

Shell命令中,参数个数。

+

argv

+

为指针数组,每个元素指向一个字符串,可以根据选择命令类型,决定是否要把命令关键字传入给注册函数。

+
+ +4. 输入Shell命令,有两种输入方式: + - 在串口工具中直接输入Shell命令。 + + - 在telnet工具中输入Shell命令(telnet使用方式详见[telnet](kernel-lite-small-shell-cmd-net-tel.md))。 + + + diff --git "a/zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\347\274\226\347\250\213\345\256\236\344\276\213.md" b/zh-cn/device-dev/kernel/kernel-lite-small-shell-sample.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/Shell\345\221\275\344\273\244\347\274\226\347\250\213\345\256\236\344\276\213.md" rename to zh-cn/device-dev/kernel/kernel-lite-small-shell-sample.md diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-shell.md b/zh-cn/device-dev/kernel/kernel-lite-small-shell.md new file mode 100644 index 0000000000000000000000000000000000000000..edc56c8c73e6e879e3dac5813fc5e4d502b940e6 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-shell.md @@ -0,0 +1,15 @@ +# 调测 + +- **[Shell介绍](kernel-lite-small-shell-des.md)** + +- **[Shell命令开发指导](kernel-lite-small-shell-guide.md)** + +- **[Shell命令编程实例](kernel-lite-small-shell-sample.md)** + +- **[Shell命令使用详解](kernel-lite-small-shell-cmd.md)** + +- **[魔法键使用方法](kernel-lite-small-shell-cmd-mag.md)** + +- **[用户态异常信息说明](kernel-lite-small-shell-cmd-abn.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite-small-thread.md b/zh-cn/device-dev/kernel/kernel-lite-small-thread.md new file mode 100644 index 0000000000000000000000000000000000000000..b758c77877f7f426c10d031f9c68d6b3c310cb8f --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small-thread.md @@ -0,0 +1,702 @@ +# 线程 + +- [基本概念](#section1179311337405) +- [使用场景](#section44877547404) +- [接口说明](#section2069477134115) + +## 基本概念 + +从系统的角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它线程运行。 + +OpenHarmony内核每个进程内的线程独立运行、独立调度,当前进程内线程的调度不受其它进程内线程的影响。 + +OpenHarmony内核中的线程采用抢占式调度机制,同时支持时间片轮转调度和FIFO调度方式。 + +OpenHarmony内核的线程一共有32个优先级\(0-31\),最高优先级为0,最低优先级为31。 + +当前进程内高优先级的线程可抢占当前进程内低优先级线程,当前进程内低优先级线程必须在当前进程内高优先级线程阻塞或结束后才能得到调度。 + +**线程状态说明:** + +- 初始化(Init):该线程正在被创建。 + +- 就绪(Ready):该线程在就绪列表中,等待CPU调度。 + +- 运行(Running):该线程正在运行。 + +- 阻塞(Blocked):该线程被阻塞挂起。Blocked状态包括:pending\(因为锁、事件、信号量等阻塞\)、suspended(主动pend)、delay\(延时阻塞\)、pendtime\(因为锁、事件、信号量时间等超时等待\)。 + +- 退出(Exit):该线程运行结束,等待父线程回收其控制块资源。 + + +**图 1** 线程状态迁移示意图 +![](figure/线程状态迁移示意图.png "线程状态迁移示意图") + +**线程状态迁移说明:** + +- Init→Ready: + + 线程创建拿到控制块后为Init状态,处于线程初始化阶段,当线程初始化完成将线程插入调度队列,此时线程进入就绪状态。 + +- Ready→Running: + + 线程创建后进入就绪态,发生线程切换时,就绪列表中最高优先级的线程被执行,从而进入运行态,但此刻该线程会从就绪列表中删除。 + +- Running→Blocked: + + 正在运行的线程发生阻塞(挂起、延时、读信号量等)时,线程状态由运行态变成阻塞态,然后发生线程切换,运行就绪列表中剩余最高优先级线程。 + +- Blocked→Ready : + + 阻塞的线程被恢复后(线程恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的线程会被加入就绪列表,从而由阻塞态变成就绪态。 + +- Ready→Blocked: + + 线程也有可能在就绪态时被阻塞(挂起),此时线程状态会由就绪态转变为阻塞态,该线程从就绪列表中删除,不会参与线程调度,直到该线程被恢复。 + +- Running→Ready: + + 有更高优先级线程创建或者恢复后,会发生线程调度,此刻就绪列表中最高优先级线程变为运行态,那么原先运行的线程由运行态变为就绪态,并加入就绪列表中。 + +- Running→Exit: + + 运行中的线程运行结束,线程状态由运行态变为退出态。若未设置分离属性(PTHREAD\_CREATE\_DETACHED)的线程,运行结束后对外呈现的是Exit状态,即退出态。 + + +## 使用场景 + +线程创建后,用户态可以执行线程调度、挂起、恢复、延时等操作,同时也可以设置线程优先级和调度策略,获取线程优先级和调度策略。 + +## 接口说明 + +OpenHarmony内核系统中的线程管理模块,线程间通信为用户提供下面几种功能: + +**表 1** 线程管理模块功能 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

头文件

+

名称

+

说明

+

备注

+

pthread.h

+

pthread_attr_destroy

+

销毁线程属性对象。

+

-

+

pthread.h

+

pthread_attr_getinheritsched

+

获取线程属性对象的调度属性。

+

-

+

pthread.h

+

pthread_attr_getschedparam

+

获取线程属性对象的调度参数属性。

+

-

+

pthread.h

+

pthread_attr_getschedpolicy

+

获取线程属性对象的调度策略属性。

+

OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

+

pthread.h

+

pthread_attr_getstacksize

+

获取线程属性对象的堆栈大小。

+

-

+

pthread.h

+

pthread_attr_init

+

初始化线程属性对象。

+

-

+

pthread.h

+

pthread_attr_setdetachstate

+

设置线程属性对象的分离状态。

+

-

+

pthread.h

+

pthread_attr_setinheritsched

+

设置线程属性对象的继承调度属性。

+

-

+

pthread.h

+

pthread_attr_setschedparam

+

设置线程属性对象的调度参数属性。

+

OpenHarmony:设置线程优先级的参数值越小,线程在系统中的优先级越高;设置参数值越大,优先级越低。

+

注意:需要将pthread_attr_t线程属性的inheritsched字段设置为PTHREAD_EXPLICIT_SCHED,否则设置的线程调度优先级将不会生效,系统默认设置为PTHREAD_INHERIT_SCHED。

+

pthread.h

+

pthread_attr_setschedpolicy

+

设置线程属性对象的调度策略属性。

+

OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

+

pthread.h

+

pthread_attr_setstacksize

+

设置线程属性对象的堆栈大小。

+

-

+

pthread.h

+

pthread_getattr_np

+

获取已创建线程的属性。

+

-

+

pthread.h

+

pthread_cancel

+

向线程发送取消请求。

+

-

+

pthread.h

+

pthread_testcancel

+

请求交付任何未决的取请求。

+

-

+

pthread.h

+

pthread_setcanceltype

+

设置线程可取消类型。

+

-

+

pthread.h

+

pthread_setcancelstate

+

设置线程可取消状态。

+

-

+

pthread.h

+

pthread_create

+

创建一个新的线程。

+

-

+

pthread.h

+

pthread_detach

+

分离一个线程。

+

-

+

pthread.h

+

pthread_equal

+

比较两个线程ID是否相等。

+

-

+

pthread.h

+

pthread_exit

+

终止正在调用的线程。

+

-

+

pthread.h

+

pthread_getschedparam

+

获取线程的调度策略和参数。

+

OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

+

pthread.h

+

pthread_join

+

等待指定的线程结束。

+

-

+

pthread.h

+

pthread_self

+

获取当前线程的ID。

+

-

+

pthread.h

+

pthread_setschedprio

+

设置线程的调度静态优先级。

+

-

+

pthread.h

+

pthread_kill

+

向线程发送信号。

+

-

+

pthread.h

+

pthread_once

+

使函数调用只能执行一次。

+

-

+

pthread.h

+

pthread_atfork

+

注册fork的处理程序。

+

-

+

pthread.h

+

pthread_cleanup_pop

+

删除位于清理处理程序堆栈顶部的例程。

+

-

+

pthread.h

+

pthread_cleanup_push

+

将例程推送到清理处理程序堆栈的顶部。

+

-

+

pthread.h

+

pthread_barrier_destroy

+

销毁屏障对象(高级实时线程)

+

-

+

pthread.h

+

pthread_barrier_init

+

初始化屏障对象(高级实时线程)

+

-

+

pthread.h

+

pthread_barrier_wait

+

屏障同步(高级实时线程)

+

-

+

pthread.h

+

pthread_barrierattr_destroy

+

销毁屏障属性对象。

+

-

+

pthread.h

+

pthread_barrierattr_init

+

初始化屏障属性对象。

+

-

+

pthread.h

+

pthread_mutex_destroy

+

销毁互斥锁。

+

-

+

pthread.h

+

pthread_mutex_init

+

初始化互斥锁。

+

-

+

pthread.h

+

pthread_mutex_lock

+

互斥锁加锁操作。

+

-

+

pthread.h

+

pthread_mutex_trylock

+

互斥锁尝试加锁操作。

+

-

+

pthread.h

+

pthread_mutex_unlock

+

互斥锁解锁操作。

+

-

+

pthread.h

+

pthread_mutexattr_destroy

+

销毁互斥锁属性对象。

+

-

+

pthread.h

+

pthread_mutexattr_gettype

+

获取互斥锁类型属性。

+

-

+

pthread.h

+

pthread_mutexattr_init

+

初始化互斥锁属性对象。

+

-

+

pthread.h

+

pthread_mutexattr_settype

+

设置互斥锁类型属性。

+

-

+

pthread.h

+

pthread_mutex_timedlock

+

使用超时锁定互斥锁。

+

-

+

pthread.h

+

pthread_rwlock_destroy

+

销毁读写锁。

+

-

+

pthread.h

+

pthread_rwlock_init

+

初始化读写锁。

+

-

+

pthread.h

+

pthread_rwlock_rdlock

+

获取读写锁读锁操作。

+

-

+

pthread.h

+

pthread_rwlock_timedrdlock

+

使用超时锁定读写锁读锁。

+

-

+

pthread.h

+

pthread_rwlock_timedwrlock

+

使用超时锁定读写锁写锁。

+

-

+

pthread.h

+

pthread_rwlock_tryrdlock

+

尝试获取读写锁读锁操作。

+

-

+

pthread.h

+

pthread_rwlock_trywrlock

+

尝试获取读写锁写锁操作。

+

-

+

pthread.h

+

pthread_rwlock_unlock

+

读写锁解锁操作。

+

-

+

pthread.h

+

pthread_rwlock_wrlock

+

获取读写锁写锁操作。

+

-

+

pthread.h

+

pthread_rwlockattr_destroy

+

销毁读写锁属性对象。

+

-

+

pthread.h

+

pthread_rwlockattr_init

+

初始化读写锁属性对象。

+

-

+

pthread.h

+

pthread_cond_broadcast

+

解除若干已被等待条件阻塞的线程。

+

-

+

pthread.h

+

pthread_cond_destroy

+

销毁条件变量。

+

-

+

pthread.h

+

pthread_cond_init

+

初始化条件变量。

+

-

+

pthread.h

+

pthread_cond_signal

+

解除被阻塞的线程。

+

-

+

pthread.h

+

pthread_cond_timedwait

+

定时等待条件。

+

-

+

pthread.h

+

pthread_cond_wait

+

等待条件。

+

-

+

semaphore.h

+

sem_destroy

+

销毁指定的无名信号量。

+

-

+

semaphore.h

+

sem_getvalue

+

获得指定信号量计数值。

+

-

+

semaphore.h

+

sem_init

+

创建并初始化一个无名信号量。

+

-

+

semaphore.h

+

sem_post

+

增加信号量计数。

+

-

+

semaphore.h

+

sem_timedwait

+

获取信号量,且有超时返回功能。

+

-

+

semaphore.h

+

sem_trywait

+

尝试获取信号量。

+

-

+

semaphore.h

+

sem_wait

+

获取信号量。

+

-

+
+ diff --git a/zh-cn/device-dev/kernel/kernel-lite-small.md b/zh-cn/device-dev/kernel/kernel-lite-small.md new file mode 100644 index 0000000000000000000000000000000000000000..a435da97d4b79e35ab0c7e8526a5df706569f215 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite-small.md @@ -0,0 +1,11 @@ +# 小型系统内核 + +- **[基础内核](kernel-lite-small-basic.md)** + +- **[文件系统](kernel-lite-small-file.md)** + +- **[标准库](kernel-lite-small-lib.md)** + +- **[调测](kernel-lite-small-shell.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-lite.md b/zh-cn/device-dev/kernel/kernel-lite.md new file mode 100644 index 0000000000000000000000000000000000000000..f6fcf22c8ec9b834dde5bf84d5b6a13b26c477be --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-lite.md @@ -0,0 +1,7 @@ +# 轻量和小型系统内核 + +- **[轻量系统内核](kernel-lite-mini.md)** + +- **[小型系统内核](kernel-lite-small.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel-standard-build.md b/zh-cn/device-dev/kernel/kernel-standard-build.md new file mode 100644 index 0000000000000000000000000000000000000000..1b52ac7b1f6ef75cb9c1e29e611e54ab24831d79 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-standard-build.md @@ -0,0 +1,47 @@ +# Linux内核编译与构建指导 + +- [开发示例1](#section19369206113115) + - [场景1:版本级编译原生方式](#section1025111193220) + - [场景2:单独编译修改后的内核](#section17446652173211) + + +## 开发示例1 + +以hi3516dv300开源开发板+ubuntu x86主机开发环境为例。 + +### 场景1:版本级编译原生方式 + +使用工程的全量编译命令,编译生成uImage内核镜像 + +``` +./build.sh --product-name Hi3516DV300 # 编译hi3516dv300的uImage内核镜像 +``` + +### 场景2:单独编译修改后的内核 + +1. 准备工作 + + 1. 按[开发板Patch使用指导](kernel-standard-patch.md)打入所需补丁。 + 2. 准备编译环境,可以使用开源arm clang/gcc编译器。 + + 进入工程主目录配置环境变量: + + ``` + export PATH=`pwd`/prebuilts/clang/host/linux-x86/clang-r353983c/bin:`pwd`/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/:$PATH # 配置编译环境 + MAKE_OPTIONES="ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CC=clang HOSTCC=clang" # 使用工程项目自带的clang环境 + ``` + +2. 修改内核代码或内核config (OpenHarmony提供对应平台的defconfig供参考)。 +3. 创建编译目录及生成内核.config。 + + ``` + make ${MAKE_OPTIONES} hi3516dv300_emmc_smp_hos_l2_defconfig # 使用自带的默认config 构建内核 + ``` + +4. 编译生成对应的内核Image。 + + ``` + make ${MAKE_OPTIONES} -j32 uImage # 编译uImage内核镜像 + ``` + + diff --git "a/zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\346\246\202\350\277\260.md" b/zh-cn/device-dev/kernel/kernel-standard-des.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/kernel/Linux\345\206\205\346\240\270\346\246\202\350\277\260.md" rename to zh-cn/device-dev/kernel/kernel-standard-des.md diff --git a/zh-cn/device-dev/kernel/kernel-standard-patch.md b/zh-cn/device-dev/kernel/kernel-standard-patch.md new file mode 100644 index 0000000000000000000000000000000000000000..87b3fea376cbb44d0f082ffdc2bc87c59fbda1d3 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-standard-patch.md @@ -0,0 +1,17 @@ +# OpenHarmony开发板Patch使用指导 + +Patch文件位于工程项目源码路径:kernel/linux/patches/linux-4.19,存放特定芯片架构驱动补丁。 + +如需使用特定芯片平台驱动的Patch,需要在内核仓代码完成对芯片平台驱动补丁合入。 + +合入芯片平台驱动补丁,针对不同芯片平台合入对应的patch: + +以Hi3516dv300为例: + +``` +patch -p1 < device/hisilicon/hi3516dv300/sdk_linux/open_source/linux/hisi_linux-4.19_hos_l2.patch +``` + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>由于OpenHarmony的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用OpenHarmony的版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 + diff --git a/zh-cn/device-dev/kernel/kernel-standard.md b/zh-cn/device-dev/kernel/kernel-standard.md new file mode 100644 index 0000000000000000000000000000000000000000..67af7b81d0828a100373e0ab9de0d5b4dee9cd92 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel-standard.md @@ -0,0 +1,9 @@ +# 标准系统内核 + +- **[Linux内核概述](kernel-standard-des.md)** + +- **[OpenHarmony开发板Patch使用指导](kernel-standard-patch.md)** + +- **[Linux内核编译与构建指导](kernel-standard-build.md)** + + diff --git a/zh-cn/device-dev/kernel/kernel.md b/zh-cn/device-dev/kernel/kernel.md new file mode 100644 index 0000000000000000000000000000000000000000..05e683e74b37a2999709a58946b4377b4175feb4 --- /dev/null +++ b/zh-cn/device-dev/kernel/kernel.md @@ -0,0 +1,7 @@ +# 内核 + +- **[轻量和小型系统内核](kernel-lite.md)** + +- **[标准系统内核](kernel-standard.md)** + + diff --git a/zh-cn/device-dev/kernel/kill.md b/zh-cn/device-dev/kernel/kill.md deleted file mode 100755 index c88e6abc63e0eba88eaa6881366b88de3ab290f6..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/kill.md +++ /dev/null @@ -1,82 +0,0 @@ -# kill - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -命令用于发送特定信号给指定进程。 - -## 命令格式 - -kill \[_signo_ | _-signo_\] \[_pid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

signo

-

信号ID。

-

[1,30]

-

pid

-

进程ID。

-

[1,MAX_INT]

-
- ->![](public_sys-resources/icon-notice.gif) **须知:** ->signo有效范围为\[0,64\],建议取值范围为\[1,30\],其余为保留内容。 - -## 使用指南 - -必须指定发送的信号编号及进程号。 - -进程编号取值范围根据系统配置变化,例如系统最大支持pid为256,则取值范围缩小为\[1-256\]。 - -## 使用实例 - -1. 查看当前进程列表,查看需要杀死的进程PID(7)。 - -**图 1** 查看进程PID -![](figures/查看进程PID.png "查看进程PID") - -2. 发送信号14(SIGALRM默认行为为进程终止)给7号进程**helloworld\_d**(用户态进程):**kill 14 7**(kill -14 7效果相同),并查看当前进程列表,7号进程已终止。 - -**图 2** 信号发送结果图 -![](figures/信号发送结果图.png "信号发送结果图") - -## 输出说明 - -发送成功或失败输出结果如下。 - -**图 3** 发送信号给指定进程 -![](figures/发送信号给指定进程.png "发送信号给指定进程") - -信号发送会显示发送记录,未报错表示信号发送成功。 - -**图 4** 信号发送失败 -![](figures/信号发送失败.png "信号发送失败") - -信号发送失败,上图所示原因为信号发送命令参数无效,请排查信号编号及进程编号是否无效。 - diff --git a/zh-cn/device-dev/kernel/log.md b/zh-cn/device-dev/kernel/log.md deleted file mode 100755 index d6972d55512d7cddf07d2791e586fbe4b00494a8..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/log.md +++ /dev/null @@ -1,74 +0,0 @@ -# log - -- [命令功能](#section128219131856) -- [命令格式](#section3894181710519) -- [参数说明](#section7693122310515) -- [使用指南](#section1982111281512) -- [使用实例](#section176301333259) -- [输出说明](#section14354765415) - -## 命令功能 - -log命令用于修改&查询日志配置。 - -## 命令格式 - -log level \[_levelNum_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

levelNum

-

配置日志打印等级。

-

[0x0,0x5]

-
- -## 使用指南 - -- 该命令依赖于LOSCFG\_SHELL\_LK,使用时通过menuconfig在配置项中开启"Enable Shell lk": - - Debug ---\> Enable a Debug Version ---\> Enable Shell ---\> Enable Shell lK。 - -- log level命令用于配置日志的打印等级,包括6个等级 - - TRACE\_EMG = 0, - - TRACE\_COMMON = 1, - - TRACE\_ERROR = 2, - - TRACE\_WARN = 3, - - TRACE\_INFO = 4, - - TRACE\_DEBUG = 5 - - 若level不在有效范围内,会打印提示信息。 - -- 若log level命令不加\[levelNum\]参数,则默认查看当前打印等级,并且提示使用方法。 - -## 使用实例 - -举例: - -输入log level 4 - -## 输出说明 - -![](figures/zh-cn_image_0000001052530298.png) - diff --git a/zh-cn/device-dev/kernel/ls.md b/zh-cn/device-dev/kernel/ls.md deleted file mode 100755 index fa17ee74660b045d3f3c0d4da8f78a21d517e2f1..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/ls.md +++ /dev/null @@ -1,59 +0,0 @@ -# ls - -- [命令功能](#section6538163771614) -- [命令格式](#section45881743111616) -- [参数说明](#section17528148171617) -- [使用指南](#section041212533166) -- [使用实例](#section986105716167) -- [输出说明](#section2036124918592) - -## 命令功能 - -ls命令用来显示当前目录的内容。 - -## 命令格式 - -ls \[_path_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

path

-

path为空时,显示当前目录的内容。

-

path为无效文件名时,显示失败,提示:

-

ls error: No such directory。

-

path为有效目录路径时,会显示对应目录下的内容。

-

1.为空。

-

2.有效的目录路径。

-
- -## 使用指南 - -- ls命令显示当前目录的内容。 -- ls可以显示文件的大小。 -- proc下ls无法统计文件大小,显示为0。 - -## 使用实例 - -举例:输入ls - -## 输出说明 - -**图 1** 查看当前系统路径下的目录,显示的内容如下 -![](figures/查看当前系统路径下的目录-显示的内容如下.png "查看当前系统路径下的目录-显示的内容如下") - diff --git a/zh-cn/device-dev/kernel/lsfd.md b/zh-cn/device-dev/kernel/lsfd.md deleted file mode 100755 index fe0ac75118286010d5496421fa463d2afc845794..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/lsfd.md +++ /dev/null @@ -1,29 +0,0 @@ -# lsfd - -- [命令功能](#section2053406181716) -- [命令格式](#section523771017172) -- [使用指南](#section27241213201719) -- [使用实例](#section442617197173) -- [输出说明](#section42491639151813) - -## 命令功能 - -lsfd命令用来显示当前已经打开的文件描述符及对应的文件名。 - -## 命令格式 - -lsfd - -## 使用指南 - -lsfd命令显示当前已经打开文件的fd号以及文件的名字。 - -## 使用实例 - -举例:输入lsfd - -## 输出说明 - -**图 1** lsfd输出说明 -![](figures/lsfd输出说明.png "lsfd输出说明") - diff --git a/zh-cn/device-dev/kernel/memcheck.md b/zh-cn/device-dev/kernel/memcheck.md deleted file mode 100755 index 5e6058dcf6025e9f6adaa0a2e04938763ba2eb1c..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/memcheck.md +++ /dev/null @@ -1,38 +0,0 @@ -# memcheck - -- [命令功能](#section191633812516) -- [命令格式](#section428816435510) -- [参数说明](#section1939943304411) -- [使用指南](#section228914491951) -- [使用实例](#section17373205314515) -- [输出说明](#section13406205385413) - -## 命令功能 - -检查动态申请的内存块是否完整,是否存在内存越界造成节点损坏。 - -## 命令格式 - -memcheck - -## 参数说明 - -无。 - -## 使用指南 - -- 当内存池所有节点完整时,输出"system memcheck over, all passed!"。 -- 当内存池存在节点不完整时,输出被损坏节点的内存块信息。 - -## 使用实例 - -举例:输入memcheck - -## 输出说明 - -**图 1** 当前没有内存越界 -![](figures/当前没有内存越界.png "当前没有内存越界") - -**图 2** 出现内存越界 -![](figures/出现内存越界.png "出现内存越界") - diff --git a/zh-cn/device-dev/kernel/mkdir.md b/zh-cn/device-dev/kernel/mkdir.md deleted file mode 100755 index 444d6a246b92fbc3b82dac6f190ad87ad883af46..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/mkdir.md +++ /dev/null @@ -1,54 +0,0 @@ -# mkdir - -- [命令功能](#section1083613274175) -- [命令格式](#section820913118178) -- [参数说明](#section1256834121718) -- [使用指南](#section1294234115172) -- [使用实例](#section1113345211713) -- [输出说明](#section10142201012) - -## 命令功能 - -mkdir命令用来创建一个目录。 - -## 命令格式 - -mkdir \[_directory_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

directory

-

需要创建的目录。

-

N/A

-
- -## 使用指南 - -- mkdir后加所需要创建的目录名会在当前目录下创建目录。 -- mkdir后加路径,再加上需要创建的目录名,即在指定目录下创建目录。 - -## 使用实例 - -举例:mkdir share - -## 输出说明 - -**图 1** 创建 share 目录 -![](figures/创建-share-目录.png "创建-share-目录") - diff --git a/zh-cn/device-dev/kernel/mount.md b/zh-cn/device-dev/kernel/mount.md deleted file mode 100755 index 5924e0ca5acaa6dc2d1379d3bfa9651175eff320..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/mount.md +++ /dev/null @@ -1,78 +0,0 @@ -# mount - -- [命令功能](#section11631837182) -- [命令格式](#section1697638111820) -- [参数说明](#section1650151221819) -- [使用指南](#section124541520171912) -- [使用实例](#section7424625171917) -- [输出说明](#section14757018116) - -## 命令功能 - -mount命令用来将设备挂载到指定目录。 - -## 命令格式 - -mount <_device_\> <_path_\> <_name_\> \[_uid gid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

device

-

要挂载的设备(格式为设备所在路径)。

-

系统拥有的设备。

-

path

-

指定目录。

-

用户必须具有指定目录中的执行(搜索)许可权。

-

N/A

-

name

-

文件系统的种类。

-

vfat, yaffs, jffs, ramfs, nfs,procfs, romfs.

-

uid gid

-

uid是指用户ID。

-

gid是指组ID。

-

可选参数,缺省值uid:0,gid:0。

-

N/A

-
- -## 使用指南 - -mount后加需要挂载的设备信息、指定目录以及设备文件格式,就能成功挂载文件系统到指定目录。 - -## 使用实例 - -举例:mount /dev/mmcblk0p0 /bin1/vs/sd vfat - -## 输出说明 - -将/dev/mmcblk0p0 挂载到/bin1/vs/sd目录 - -![](figures/zh-cn_image_0000001051690323.png) - diff --git a/zh-cn/device-dev/kernel/netstat.md b/zh-cn/device-dev/kernel/netstat.md deleted file mode 100755 index cca0b0dc9ae8fd60e21db1f7901804d5d33d330a..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/netstat.md +++ /dev/null @@ -1,83 +0,0 @@ -# netstat - -- [命令功能](#section13469162113816) -- [命令格式](#section795712373812) -- [参数说明](#section17629431193817) -- [使用指南](#section5277153519380) -- [使用实例](#section108141437163820) -- [输出说明](#section1357015107117) - -## 命令功能 - -netstat是控制台命令,是一个监测TCP/IP网络的非常有用的工具,它可以显示实际的网络连接以及每一个网络接口设备的状态信息。netstat用于显示与TCP、UDP协议相关的统计数据,一般用于检验本设备(单板)各端口的网络连接情况。 - -## 命令格式 - -netstat - -## 参数说明 - -无 - -## 使用指南 - -直接输入命令。 - -## 使用实例 - -举例:输入netstat - -**图 1** netstat 打印信息 - - -![](figures/Snipaste_2021-01-26_10-38-58-1.png) - -## 输出说明 - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

Proto

-

协议类型。

-

Recv-Q

-

未被用户读取的数据量。

-

对于Listen TCP,此值为已完成三次握手,但是未被用户accept的TCP连接的数量。

-

Send-Q

-

对TCP连接,已发送但未确认的数据量。

-

对UDP连接,由于IP地址解析未完成而缓存的数据量。

-

Local Address

-

本地地址和端口。

-

Foreign Address

-

远程地址和端口。

-

State

-

TCP连接状态,UDP此项无意义。

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->形如“========== total sockets 32 ====== unused sockets 22 BootTime 27 s ========== ”,表示一共32个套接字,未使用套接字22个,距系统启动已经过27秒。 - diff --git a/zh-cn/device-dev/kernel/oom.md b/zh-cn/device-dev/kernel/oom.md deleted file mode 100755 index 4590f61fedd7ff85e6596ca1bd5d711509d1bd6e..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/oom.md +++ /dev/null @@ -1,120 +0,0 @@ -# oom - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -查看和设置低内存阈值以及pagecache内存回收阈值。 - -## 命令格式 - -oom - -oom -i \[_interval_\] - -oom -m \[_mem byte_\] - -oom -r \[_mem byte_\] - -oom -h | --help - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-i [interval]

-

设置oom线程任务检查的时间间隔。

-

100ms ~ 10000ms

-

-m [mem byte]

-

设置低内存阈值。

-

0MB ~ 1MB,0MB表示不做低内存阈值检查。

-

-r [mem byte]

-

设置pagecache内存回收阈值。

-

低内存阈值 ~ 系统可用最大内存。

-

-h | --help

-

使用帮助。

-

N/A

-
- -## 使用指南 - -- 参数缺省时,显示oom功能当前配置信息。 - -## 使用实例 - -当系统内存不足时,会打印出内存不足的提示信息。 - -## 输出说明 - -![](figures/zh-cn_image_0000001053710680.png) - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

[oom] OS is in low memory state

-

total physical memory: 0x1bcf000(byte), used: 0x1b50000(byte), free: 0x7f000(byte), low memory threshold: 0x80000(byte)

-

操作系统处于低内存状态。

-

整个系统可用物理内存为0x1bcf000 byte,已经使用了 0x1b50000 byte, 还剩0x7f000 byte,当前设置的低内存阈值为0x80000 byte。

-

[oom] candidate victim process init pid: 1, actual phy mem byte: 82602

-

打印当前各个进程的内存使用情况,init进程实际使用82602byte,其中共享内存按照比例算的。

-

[oom] candidate victim process UserProcess12 pid: 12, actual phy mem byte: 25951558

-

UserProcess12进程实际使用25951558byte内存。

-

[oom] max phy mem used process UserProcess12 pid: 12, actual phy mem: 25951558

-

当前使用内存最多的进程是UserProcess12。

-

excFrom: User!

-

当系统处于低内存的情况下,UserProcess12进程再去申请内存时失败退出。

-
- diff --git a/zh-cn/device-dev/kernel/partinfo.md b/zh-cn/device-dev/kernel/partinfo.md deleted file mode 100755 index b8dc652e97d0bbf411bd53345e0c2aaf5bba72ab..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/partinfo.md +++ /dev/null @@ -1,52 +0,0 @@ -# partinfo - -- [命令功能](#section1777503617199) -- [命令格式](#section185501447132114) -- [参数说明](#section1304151212252) -- [使用指南](#section4566131982520) -- [使用实例](#section4351134942514) -- [输出说明](#section66689331412) - -## 命令功能 - -partinfo命令用于查看系统识别的硬盘,SD卡多分区信息。 - -## 命令格式 - -partinfo <_dev\_inodename_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

dev_inodename

-

要查看的分区名字。

-

合法的分区名。

-
- -## 使用指南 - -无 - -## 使用实例 - -partinfo /dev/mmcblk0p0 - -## 输出说明 - -![](figures/zh-cn_image_0000001052370303.png) - diff --git a/zh-cn/device-dev/kernel/partition.md b/zh-cn/device-dev/kernel/partition.md deleted file mode 100755 index 9a4b15684996b320979efc79eb34924b19cb8440..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/partition.md +++ /dev/null @@ -1,62 +0,0 @@ -# partition - -- [命令功能](#section255095212257) -- [命令格式](#section10258056122515) -- [参数说明](#section177200581256) -- [使用指南](#section17866411262) -- [使用实例](#section1927174202610) -- [输出说明](#section11321011223) - -## 命令功能 - -partition命令用来查看flash分区信息。 - -## 命令格式 - -partition \[_nand / spinor_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

nand

-

显示nand flash分区信息。

-

N/A

-

spinor

-

显示spinor flash分区信息。

-

N/A

-
- -## 使用指南 - -- partition命令用来查看flash分区信息。 -- 仅当使能yaffs文件系统时才可以查看nand flash分区信息,使能jffs或romfs文件系统时可以查看spinor flash分区信息。 - -## 使用实例 - -举例:partition spinor - -## 输出说明 - -查看spinor flash分区信息 - -![](figures/zh-cn_image_0000001052810300.png) - diff --git a/zh-cn/device-dev/kernel/ping.md b/zh-cn/device-dev/kernel/ping.md deleted file mode 100755 index c995f3c5ebd497b1876bb079e4c93b824dcd5ca4..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/ping.md +++ /dev/null @@ -1,99 +0,0 @@ -# ping - -- [命令功能](#section119672573385) -- [命令格式](#section869419010390) -- [参数说明](#section9877183173918) -- [使用指南](#section1097046193914) -- [使用实例](#section14564129113911) -- [输出说明](#section1621732891215) - -## 命令功能 - -ping命令用于测试网络连接是否正常。 - -## 命令格式 - -ping_ _\[_-n cnt_\] \[_-w interval_\] \[_-l data\_len_\]_ _ - -ping \[_-t_\] \[_-w interval_\] __ - -ping _-k_ - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

IP

-

要测试是否网络连通的IPv4地址。

-

N/A

-

-n cnt

-

执行的次数,不带本参数则默认为4次。

-

1-65535

-

-w interval

-

发送两次ping包的时间间隔,单位毫秒。

-

>0

-

-l data_len

-

ping包,即ICMP echo request报文的数据长

-

度,不包含ICMP包头。

-

0-65500

-

-t

-

表示永久ping,直到使用ping -k杀死ping线

-

程。

-

N/A

-

-k

-

杀死ping线程,停止ping。

-

N/A

-
- -## 使用指南 - -- ping命令用来测试到目的IP的网络连接是否正常,参数为目的IP地址。 -- 如果目的IP不可达,会显示请求超时。 -- 如果显示发送错误,说明没有到目的IP的路由。 -- 命令需要启动TCP/IP协议栈后才能使用。 - -## 使用实例 - -举例:输入ping 192.168.1.10 - -## 输出说明 - -**图 1** ping tftp 服务器地址 - - -![](figures/Snipaste_2021-01-26_10-38-58-2.png) - diff --git a/zh-cn/device-dev/kernel/pmm.md b/zh-cn/device-dev/kernel/pmm.md deleted file mode 100755 index 9ed393dfdd95811a140333837905c65263a65bd2..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/pmm.md +++ /dev/null @@ -1,91 +0,0 @@ -# pmm - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -查看系统内存物理页及pagecache物理页使用情况。 - -## 命令格式 - -pmm - -## 参数说明 - -无 - -## 使用指南 - -Debug版本才具备的命令。 - -## 使用实例 - -输入pmm - -## 输出说明 - -**图 1** 查看物理页使用情况 -![](figures/查看物理页使用情况.png "查看物理页使用情况") - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

phys_seg

-

物理页控制块地址信息

-

base

-

第一个物理页地址,即物理页内存起始地址

-

size

-

物理页内存大小

-

free_pages

-

空闲物理页数量

-

active anon

-

pagecache中,活跃的匿名页数量

-

inactive anon

-

pagecache中,不活跃的匿名页数量

-

active file

-

pagecache中,活跃的文件页数量

-

inactive file

-

pagecache中,不活跃的文件页数量

-

pmm pages

-

total:总的物理页数,used:已使用的物理页数,free:空闲的物理页数

-
- diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/kernel/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/kernel/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-note.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/kernel/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/kernel/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/kernel/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/kernel/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/kernel/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/kernel/public_sys-resources/icon-warning.gif and /dev/null differ diff --git a/zh-cn/device-dev/kernel/pwd.md b/zh-cn/device-dev/kernel/pwd.md deleted file mode 100755 index bff68160cecb23771496dd419583ba4c084c241e..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/pwd.md +++ /dev/null @@ -1,34 +0,0 @@ -# pwd - -- [命令功能](#section197737712267) -- [命令格式](#section1544061016267) -- [参数说明](#section599112120262) -- [使用指南](#section66901116152615) -- [使用实例](#section7427181922612) -- [输出说明](#section116313389418) - -## 命令功能 - -pwd命令用来显示当前路径。 - -## 命令格式 - -pwd - -## 参数说明 - -无。 - -## 使用指南 - -pwd 命令将当前目录的全路径名称(从根目录)写入标准输出。全部目录使用 / (斜线)分隔。第一个 / 表示根目录, 最后一个目录是当前目录。 - -## 使用实例 - -举例:输入pwd - -## 输出说明 - -**图 1** 查看当前路径 -![](figures/查看当前路径.png "查看当前路径") - diff --git a/zh-cn/device-dev/kernel/rm.md b/zh-cn/device-dev/kernel/rm.md deleted file mode 100755 index 2815b287a1d8bc385b9879727254d4726b8d266b..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/rm.md +++ /dev/null @@ -1,67 +0,0 @@ -# rm - -- [命令功能](#section181141523142613) -- [命令格式](#section8800926132619) -- [参数说明](#section15476229152617) -- [使用指南](#section10578163215262) -- [使用实例](#section18548133511263) -- [输出说明](#section1565323814265) - -## 命令功能 - -rm命令用来删除文件或文件夹。 - -## 命令格式 - -rm \[_-r_\] \[_dirname / filename_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-r

-

可选参数,若是删除目录则需要该参数。

-

N/A

-

dirname/filename

-

要删除文件或文件夹的名称,支持输入路径。

-

N/A

-
- -## 使用指南 - -- rm命令一次只能删除一个文件或文件夹。 -- rm -r命令可以删除非空目录。 - -## 使用实例 - -举例: - -1. 输入rm log1.txt -2. 输入rm -r sd - -## 输出说明 - -**图 1** 用 rm 命令删除文件 log1.txt -![](figures/用-rm-命令删除文件-log1-txt.png "用-rm-命令删除文件-log1-txt") - -**图 2** 用 rm -r 删除目录 sd -![](figures/用-rm--r-删除目录-sd.png "用-rm--r-删除目录-sd") - diff --git a/zh-cn/device-dev/kernel/rmdir.md b/zh-cn/device-dev/kernel/rmdir.md deleted file mode 100755 index 6a1e52eee3b2f6b21f802a4a144ee5fad3d554ab..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/rmdir.md +++ /dev/null @@ -1,55 +0,0 @@ -# rmdir - -- [命令功能](#section1839611420266) -- [命令格式](#section329574512266) -- [参数说明](#section15865747102620) -- [使用指南](#section107857508261) -- [使用实例](#section11196165315262) -- [输出说明](#section1073811415613) - -## 命令功能 - -rmdir命令用来删除一个目录。 - -## 命令格式 - -rmdir \[_dir_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

dir

-

需要删除目录的名称,删除目录必须为空,支持输入路径。

-

N/A

-
- -## 使用指南 - -- rmdir命令只能用来删除目录。 -- rmdir一次只能删除一个目录。 -- rmdir只能删除空目录。 - -## 使用实例 - -举例:输入rmdir dir - -## 输出说明 - -**图 1** 删除一个名为 dir 的目录 -![](figures/删除一个名为-dir-的目录.png "删除一个名为-dir-的目录") - diff --git a/zh-cn/device-dev/kernel/sem.md b/zh-cn/device-dev/kernel/sem.md deleted file mode 100755 index 14342e7531992cd0965a2b33eed6d840eaa0738c..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/sem.md +++ /dev/null @@ -1,91 +0,0 @@ -# sem - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section1975118519456) - -## 命令功能 - -sem命令用于查询系统内核信号量相关信息。 - -## 命令格式 - -sem \[_ID__ / fulldata_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

ID

-

信号ID号。

-

[0, 0xFFFFFFFF]

-

fulldata

-

查询所有在用的信号量信息,打印信息包括如下:SemID, Count, Original Count, Creater TaskEntry, Last Access Time。

-

N/A

-
- -## 使用指南 - -- 参数缺省时,显示所有的信号量的使用数及信号量总数。 -- sem后加ID,显示对应ID信号量的使用数。 -- 参数fulldata依赖于LOSCFG\_DEBUG\_SEMAPHORE,使用时通过menuconfig在配置项中开启"Enable Semaphore Debugging": - - Debug ---\> Enable a Debug Version ---\> Enable Debug LiteOS Kernel Resource ---\> Enable Semaphore Debugging - - -## 使用实例 - -举例1:输入 sem fulldata - -## 输出说明 - -**图 1** 查询所有在用的信号量信息 -![](figures/查询所有在用的信号量信息.png "查询所有在用的信号量信息") - -**表 2** 输出说明 - - - - - - - - - - - - - -

输出

-

说明

-

SemID

-

信号量ID。

-

Count

-

信号量使用数。

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->● sem命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 ->● sem命令的ID参数在\[0, 1023\]范围内时,返回对应ID的信号量的状态(如果对应ID的信号量未被使用则进行提示);其他取值时返回参数错误的提示。 - diff --git a/zh-cn/device-dev/kernel/stack.md b/zh-cn/device-dev/kernel/stack.md deleted file mode 100755 index 526ed83f4d872388224244d27aee8011f345f766..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/stack.md +++ /dev/null @@ -1,73 +0,0 @@ -# stack - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -查看系统各堆栈使用情况。 - -## 命令格式 - -stack - -## 参数说明 - -无。 - -## 使用指南 - -无。 - -## 使用实例 - -输入:stack - -## 输出说明 - -**图 1** 系统堆栈使用情况 - - -![](figures/zh-cn_image_0000001054624363.png) - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

stack name

-

系统堆栈名

-

cpu id

-

cpu 号

-

stack addr

-

栈地址

-

total size

-

堆栈大小

-

used size

-

堆栈实际使用大小

-
- diff --git a/zh-cn/device-dev/kernel/statfs.md b/zh-cn/device-dev/kernel/statfs.md deleted file mode 100755 index bc428c78b253e7c7dff60543c2f942db43756b0f..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/statfs.md +++ /dev/null @@ -1,52 +0,0 @@ -# statfs - -- [命令功能](#section153921657152613) -- [命令格式](#section135391102717) -- [参数说明](#section074312314279) -- [使用指南](#section133816772712) -- [使用实例](#section526149182717) - -## 命令功能 - -statfs命令用来打印文件系统的信息,如该文件系统类型、总大小、可用大小等信息。 - -## 命令格式 - -statfs \[_directory_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

directory

-

文件系统的路径。

-

必须是存在的文件系统,并且其支持statfs命令,当前支持的文件系统有:JFFS2,FAT,NFS。

-
- -## 使用指南 - -打印信息因文件系统而异。 - -## 使用实例 - -以nfs文件系统为例: - -statfs /nfs - -**图 1** statfs输出说明 -![](figures/statfs输出说明.png "statfs输出说明") - diff --git a/zh-cn/device-dev/kernel/su.md b/zh-cn/device-dev/kernel/su.md deleted file mode 100755 index a23b14445d1eabb3fc71242ebff588b937fe2c02..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/su.md +++ /dev/null @@ -1,62 +0,0 @@ -# su - -- [命令功能](#section297810431676) -- [命令格式](#section157131147876) -- [参数说明](#section04145521671) -- [使用指南](#section14615155610719) -- [使用实例](#section13338150985) -- [输出说明](#section125021924194613) - -## 命令功能 - -su用于变更为其他使用者的身份。 - -## 命令格式 - -su \[_uid_\] \[_gid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

uid

-

目标用户的用户id值。

-
  • 为空。
  • [0,60000]
-

gid

-

目标用户的群组id值。

-
  • 为空。
  • [0,60000]
-
- -## 使用指南 - -- su命令缺省切换到root用户,uid默认为0,gid为0。 -- 在su命令后的输入参数uid和gid就可以切换到该uid和gid的用户。 -- 输入参数超出范围时,会打印提醒输入正确范围参数。 - -## 使用实例 - -举例:su 1000 1000 - -## 输出说明 - -**图 1** **切换到**为uid为1000,gid为1000的用户 -![](figures/切换到为uid为1000-gid为1000的用户.png "切换到为uid为1000-gid为1000的用户") - diff --git a/zh-cn/device-dev/kernel/swtmr.md b/zh-cn/device-dev/kernel/swtmr.md deleted file mode 100755 index 7ab65604883876668fbc61ea7efc4c7fc6f1ed89..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/swtmr.md +++ /dev/null @@ -1,110 +0,0 @@ -# swtmr - -- [命令功能](#section166171064814) -- [命令格式](#section424011111682) -- [参数说明](#section1268410459465) -- [使用指南](#section169806213815) -- [使用实例](#section16676026389) -- [输出说明](#section1541991614710) - -## 命令功能 - -swtmr命令用于查询系统软件定时器相关信息。 - -## 命令格式 - -swtmr \[_ID_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

ID

-

软件定时器ID号。

-

[0,0xFFFFFFFF]

-
- -## 使用指南 - -- 参数缺省时,默认显示所有软件定时器的相关信息。 -- swtmr后加ID号时,显示ID对应的软件定时器相关信息。 - -## 使用实例 - -举例:输入swtmr和swtmr 1 - -## 输出说明 - -**图 1** 查询所有软件定时器相关信息 -![](figures/查询所有软件定时器相关信息.png "查询所有软件定时器相关信息") - -**图 2** 查询对应 ID 的软件定时器信息 -![](figures/查询对应-ID-的软件定时器信息.png "查询对应-ID-的软件定时器信息") - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

SwTmrID

-

软件定时器ID。

-

State

-

软件定时器状态。

-

状态可能为:"UnUsed", "Created", "Ticking"。

-

Mode

-

软件定时器模式。

-

模式可能为:"Once", "Period", "NSD(单次定时器,定时结束后不会自动删除)"。

-

Interval

-

软件定时器使用的Tick数。

-

Count

-

软件定时器已经工作的次数。

-

Arg

-

传入的参数。

-

handlerAddr

-

回调函数的地址。

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->- swtmr命令的ID参数输入形式以十进制形式表示或十六进制形式表示皆可。 ->- swtmr命令的ID参数在\[0, 当前软件定时器个数 - 1\]范围内时,返回对应ID的软件定时器的状态;其他取值时返回错误提示。 - diff --git a/zh-cn/device-dev/kernel/systeminfo.md b/zh-cn/device-dev/kernel/systeminfo.md deleted file mode 100755 index 16fbd841d383b8513254885c9c2cf19916186e67..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/systeminfo.md +++ /dev/null @@ -1,91 +0,0 @@ -# systeminfo - -- [命令功能](#section863016434820) -- [命令格式](#section139791817795) -- [参数说明](#section19472339164813) -- [使用指南](#section285522592) -- [使用实例](#section9471171015105) -- [输出说明](#section1657011114915) - -## 命令功能 - -systeminfo命令用于显示当前操作系统内资源使用情况,包括任务、信号量、互斥量、队列、定时器等。 - -## 命令格式 - -systeminfo - -## 参数说明 - -无。 - -## 使用指南 - -无。 - -## 使用实例 - -举例:输入systeminfo - -## 输出说明 - -**图 1** 查看系统资源使用情况 -![](figures/查看系统资源使用情况.png "查看系统资源使用情况") - -**表 1** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

Module

-

模块名称。

-

Used

-

当前使用量。

-

Total

-

最大可用量。

-

Enabled

-

模块是否开启。

-

Task

-

任务。

-

Sem

-

信号量。

-

Mutex

-

互斥量。

-

Queue

-

队列。

-

SwTmr

-

定时器。

-
- diff --git a/zh-cn/device-dev/kernel/task.md b/zh-cn/device-dev/kernel/task.md deleted file mode 100755 index 673ed06ae2a24eaa5140dab866d6a71551d14a85..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/task.md +++ /dev/null @@ -1,125 +0,0 @@ -# task - -- [命令功能](#section0533181714106) -- [命令格式](#section1014412308101) -- [参数说明](#section116057158506) -- [使用指南](#section2053502951112) -- [使用实例](#section12629113381116) -- [输出说明](#section19299103465015) - -## 命令功能 - -task命令用于查询进程及线程信息。 - -## 命令格式 - -task/task -a - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-a

-

查看更多信息。

-

N/A

-
- -## 使用指南 - -- 参数缺省时默认打印部分任务信息。 - -## 使用实例 - -举例:输入task - -## 输出说明 - -**图 1** 查询任务部分信息 -![](figures/查询任务部分信息.png "查询任务部分信息") - -**表 2** 输出说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

PID

-

进程ID。

-

PPID

-

父进程ID。

-

PGID

-

进程组ID。

-

UID

-

用户ID。

-

Status

-

任务当前的状态。

-

CPUUSE10s

-

10秒内CPU使用率。

-

PName

-

进程名。

-

TID

-

任务ID。

-

StackSize

-

任务堆栈的大小。

-

WaterLine

-

栈使用的峰值。

-

MEMUSE

-

内存使用量。

-

TaskName

-

任务名。

-
- diff --git a/zh-cn/device-dev/kernel/telnet.md b/zh-cn/device-dev/kernel/telnet.md deleted file mode 100755 index e68f22de468d07eb1f954a87be4a30add268a3e0..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/telnet.md +++ /dev/null @@ -1,65 +0,0 @@ -# telnet - -- [命令功能](#section3551830123913) -- [命令格式](#section14897133233918) -- [参数说明](#section977718353392) -- [使用指南](#section134991538183916) -- [使用实例](#section1097414426398) -- [输出说明](#section11846624191310) - -## 命令功能 - -本命令用于启动或关闭telnet server服务。 - -## 命令格式 - -telnet \[_on | off_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

on

-

启动telnet server服务。

-

N/A

-

off

-

关闭telnet server服务。

-

N/A

-
- -## 使用指南 - -- telnet启动要确保网络驱动及网络协议栈已经初始化完成,且板子的网卡是link up状态。 -- 暂时无法支持多个客户端(telnet + IP)同时连接开发板。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >telnet属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 - - -## 使用实例 - -举例:输入telnet on - -## 输出说明 - -**图 1** 输入 telnet on -![](figures/输入-telnet-on.png "输入-telnet-on") - diff --git a/zh-cn/device-dev/kernel/tftp.md b/zh-cn/device-dev/kernel/tftp.md deleted file mode 100755 index a82fdf93898b2f2825c4ae510477f85ea6e3846e..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/tftp.md +++ /dev/null @@ -1,87 +0,0 @@ -# tftp - -- [命令功能](#section15142134573911) -- [命令格式](#section20958174917394) -- [参数说明](#section576613532395) -- [使用指南](#section149795134408) -- [使用实例](#section148921918114015) -- [输出说明](#section7872155631313) - -## 命令功能 - -TFTP(Trivial File Transfer Protocol,简单文件传输协议)是TCP/IP协议族中的一个用来在客户机与服务器之间进行简单文件传输的协议,提供简单、低开销的文件传输服务。端口号为69。 - -tftp命令可以从TFTP服务器上下载文件。 - -## 命令格式 - -./bin/tftp _<-g/-p\>_ _-l_ _\[FullPathLocalFile\] -r \[RemoteFile\] \[Host\]_ - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-g/-p

-

文件传输方向:

-
  • -g 从TFTP服务器获取文件。
  • -p 上传文件到TFTP服务器。
-

N/A

-

-l FullPathLocalFile

-

本地文件完整路径。

-

N/A

-

-r RemoteFile

-

服务端文件名。

-

N/A

-

Host

-

服务端IP。

-

N/A

-
- -## 使用指南 - -1. 在服务器端搭建TFTP服务器,并进行正确配置。 -2. OpenHarmony单板使用tftp命令上传、下载文件。 -3. 传输的文件大小是有限制的不能大于32M。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >tftp属于调测功能,默认配置为关闭,正式产品中禁止使用该功能。 - - -## 使用实例 - -举例:从服务器下载out文件。 - -## 输出说明 - -``` -OHOS # ./bin/tftp -g -l /nfs/out -r out 192.168.1.2 -TFTP transfer finish -``` - -tftp命令执行后,传输正常完成会显示TFTP transfer finish, 失败的话会显示其他的打印信息帮助定位问题。 - diff --git a/zh-cn/device-dev/kernel/touch.md b/zh-cn/device-dev/kernel/touch.md deleted file mode 100755 index dc40b522af4032be79f096f674800feba6292a2f..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/touch.md +++ /dev/null @@ -1,59 +0,0 @@ -# touch - -- [命令功能](#section17541924112716) -- [命令格式](#section866182711274) -- [参数说明](#section268912296270) -- [使用指南](#section412093332714) -- [使用实例](#section414434814354) -- [输出说明](#section1028419515711) - -## 命令功能 - -- touch命令用来在指定的目录下创建一个不存在的空文件。 -- touch命令操作已存在的文件会成功,不会更新时间戳。 - -## 命令格式 - -touch \[_filename_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

filename

-

需要创建文件的名称。

-

N/A

-
- -## 使用指南 - -- touch命令用来创建一个空文件,该文件可读写。 -- 使用touch命令一次只能创建一个文件。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >在系统重要资源路径下使用touch命令创建文件,会对系统造成死机等未知影响,如在/dev路径下执行touch uartdev-0,会产生系统卡死现象。 - - -## 使用实例 - -举例:输入touch file.c 输出说明 - -## 输出说明 - -**图 1** 创建一个名为 file.c 的文件 -![](figures/创建一个名为-file-c-的文件.png "创建一个名为-file-c-的文件") - diff --git a/zh-cn/device-dev/kernel/umount.md b/zh-cn/device-dev/kernel/umount.md deleted file mode 100755 index 7cb41d53ef02df0549885092610bb7c5eb156eee..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/umount.md +++ /dev/null @@ -1,55 +0,0 @@ -# umount - -- [命令功能](#section365125133520) -- [命令格式](#section9615254123512) -- [参数说明](#section63446577355) -- [使用指南](#section92931509368) -- [使用实例](#section144311323616) -- [输出说明](#section360525113611) - -## 命令功能 - -umount命令用来卸载指定文件系统。 - -## 命令格式 - -umount \[_dir_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

dir

-

需要卸载文件系统对应的目录。

-

系统已挂载的文件系统的目录。

-
- -## 使用指南 - -umount后加上需要卸载的指定文件系统的目录,即将指定文件系统卸载。 - -## 使用实例 - -举例:umount /bin1/vs/sd - -## 输出说明 - -将已在/bin1/vs/sd挂载的文件系统卸载 - -**图 1** umount输出示例 -![](figures/umount输出示例.png "umount输出示例") - diff --git a/zh-cn/device-dev/kernel/uname.md b/zh-cn/device-dev/kernel/uname.md deleted file mode 100755 index 71a06837cc26f1ae62bc2eb0a240c47f3422f6b7..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/uname.md +++ /dev/null @@ -1,72 +0,0 @@ -# uname - -- [命令功能](#section107697383115) -- [命令格式](#section162824341116) -- [使用指南](#section2652124861114) -- [使用实例](#section0107995132) -- [输出说明](#section1215113245511) - -## 命令功能 - -uname命令用于显示当前操作系统的名称,版本创建时间,系统名称,版本信息等。 - -## 命令格式 - -uname \[_-a | -s | -t | -v | --help_\] - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

无参数

-

默认显示操作系统名称。

-

-a

-

显示全部信息。

-

-t

-

显示版本创建的时间。

-

-s

-

显示操作系统名称。

-

-v

-

显示版本信息。

-

--help

-

显示uname指令格式提示。

-
- -## 使用指南 - -uname用于显示当前操作系统名称。语法uname -a | -t| -s| -v 描述uname 命令将正在使用的操作系统名写到标准输出中,这几个参数不能混合使用。 - -## 使用实例 - -举例:输入uname -a - -## 输出说明 - -查看系统信息 - -![](figures/zh-cn_image_0000001052370305.png) - diff --git a/zh-cn/device-dev/kernel/vmm.md b/zh-cn/device-dev/kernel/vmm.md deleted file mode 100755 index 0d38eadc7e36fabed43abe813d992640bad42206..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/vmm.md +++ /dev/null @@ -1,158 +0,0 @@ -# vmm - -- [命令功能](#section445335110416) -- [命令格式](#section1795712553416) -- [参数说明](#section92544592410) -- [使用指南](#section104151141252) -- [使用实例](#section11545171957) -- [输出说明](#section075617368542) - -## 命令功能 - -查看进程的虚拟内存使用情况。 - -## 命令格式 - -vmm \[_-a / -h / --help_\] - -vmm \[_pid_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

-a

-

输出所有进程的虚拟内存使用情况

-

N/A

-

-h | --help

-

命令格式说明

-

N/A

-

pid

-

进程ID,说明指定进程的虚拟内存使用情况

-

[0,63]

-
- -## 使用指南 - -命令缺省输出所有进程的虚拟内存使用情况。 - -## 使用实例 - -输入vmm 3 - -## 输出说明 - -**图 1** PID为3的进程虚拟内存使用信息 -![](figures/PID为3的进程虚拟内存使用信息.png "PID为3的进程虚拟内存使用信息") - -**表 2** 进程基本信息 - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

PID

-

进程ID

-

aspace

-

进程虚拟内存控制块地址信息

-

name

-

进程名

-

base

-

虚拟内存起始地址

-

size

-

虚拟内存大小

-

pages

-

已使用的物理页数量

-
- -**表 3** 虚拟内存区间信息 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出

-

说明

-

region

-

虚拟区间控制块地址信息

-

name

-

虚拟区间类型

-

base

-

虚拟区间起始地址

-

size

-

虚拟区间大小

-

mmu_flags

-

虚拟区间mmu映射属性

-

pages

-

已使用的物理页数量(包括共享内存部分)

-

pg/ref

-

已使用的物理页数量

-
- diff --git a/zh-cn/device-dev/kernel/watch.md b/zh-cn/device-dev/kernel/watch.md deleted file mode 100755 index 0586d287df85decf88bc96708c892b19ab23dc4c..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/watch.md +++ /dev/null @@ -1,100 +0,0 @@ -# watch - -- [命令功能](#section20643141481314) -- [命令格式](#section1075441721316) -- [参数说明](#section1472810220135) -- [使用指南](#section186772414131) -- [使用实例](#section4764192791314) -- [输出说明](#section5791253155517) - -## 命令功能 - -watch命令用于周期性的监视一个命令的运行结果。 - -## 命令格式 - -watch - -watch \[_-c/-n/-t/--count/--interval/-no-title/--over_\] \[_command_\] - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

缺省值

-

取值范围

-

-c / --count

-

命令执行的总次数。

-

0xFFFFFF

-

(0,0xFFFFFF]

-

-n / --interval

-

命令周期性执行的时间间隔(s)。

-

1s

-

(0,0xFFFFFF]

-

-t / -no-title

-

关闭顶端的时间显示。

-

N/A

-

N/A

-

command

-

需要监测的命令。

-

N/A

-

N/A

-

--over

-

关闭当前监测指令。

-

N/A

-

N/A

-
- -## 使用指南 - -watch运行过程中可以执行**watch --over**结束本次watch命令。 - -## 使用实例 - -输入举例: - -watch -n 2 -c 6 task - -## 输出说明 - -**图 1** watch task 结果 -![](figures/watch-task-结果.png "watch-task-结果") - ->![](public_sys-resources/icon-note.gif) **说明:** ->示例中,总共有6次task命令打印,每次间隔2秒,截图为最后一次打印详情。 - diff --git a/zh-cn/device-dev/kernel/writeproc.md b/zh-cn/device-dev/kernel/writeproc.md deleted file mode 100755 index 7e0306ff60c5def1793041f59306a7d17118594b..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/kernel/writeproc.md +++ /dev/null @@ -1,69 +0,0 @@ -# writeproc - -- [命令功能](#section366714216619) -- [命令格式](#section8833164614615) -- [参数说明](#section12809111019453) -- [使用指南](#section15935131220717) -- [使用实例](#section79281818476) -- [输出说明](#section12742311179) - -## 命令功能 - -proc fs支持传入字符串参数,需要每个文件实现自己的写方法。 - -## 命令格式 - -writeproc <_data_\> \>\> /proc/<_filename_\> - -## 参数说明 - -**表 1** 参数说明 - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

取值范围

-

data

-

要输入的字符串,以空格为结束符,如需输入空格,请用""包裹。

-

N/A

-

filename

-

data要传入的proc文件。

-

N/A

-
- -## 使用指南 - -proc文件实现自身的write函数,调用writeproc命令后会将入参传入write函数。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->procfs不支持多线程访问。 - -## 使用实例 - -举例:writeproc test \>\> /proc/uptime - -## 输出说明 - -OHOS \# writeproc test \>\> /proc/uptime - -\[INFO\]write buf is: test - -test \>\> /proc/uptime - ->![](public_sys-resources/icon-note.gif) **说明:** ->uptime proc文件临时实现write函数,INFO日志为实现的测试函数打印的日志。 - diff --git "a/zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" deleted file mode 100644 index 29edaf0e1e6affff1fd4c5ff00687023434c6651..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\344\270\255\346\226\255\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 中断管理 - -- **[基本概念](基本概念.md)** - -- **[开发指导](开发指导.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" "b/zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" deleted file mode 100644 index e998fce8eb5759370f6a3e6b053cd26baed727f2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\344\272\213\344\273\266.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 事件 - -- **[基本概念](基本概念-5.md)** - -- **[开发指导](开发指导-6.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" "b/zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" deleted file mode 100644 index ce0ea2949c4c1e9fa1973457e88e40a411b2069d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\344\272\222\346\226\245\351\224\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 互斥锁 - -- **[基本概念](基本概念-7.md)** - -- **[开发指导](开发指导-8.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" deleted file mode 100644 index 22165d0c36e05cd78b42f6c18f233ccef9eb2269..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\344\273\273\345\212\241\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 任务管理 - -- **[基本概念](基本概念-2.md)** - -- **[开发指导](开发指导-3.md)** - - diff --git "a/zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" "b/zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" deleted file mode 100644 index 6eb88eb04b6e7a3335c5c84f9932d018134cbeb3..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\344\277\241\345\217\267\351\207\217.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 信号量 - -- **[基本概念](基本概念-11.md)** - -- **[开发指导](开发指导-12.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" deleted file mode 100755 index 871a1c5ac807e07ef3a6d220cefd6bef3044e91b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230.md" +++ /dev/null @@ -1,353 +0,0 @@ -# 内存 - -- [基本概念](#section1392116583424) -- [使用场景](#section159581619194319) -- [接口说明](#section114001032104317) - -## 基本概念 - -内存管理是开发过程中必须要关注的重要过程,它包括内存的分配、使用和回收。 - -良好的内存管理对于提高软件性能和可靠性有着十分重要的意义。 - -## 使用场景 - -针对用户态开发,OpenHarmony内核提供了一套内存系统调用接口,支持内存的申请释放、重映射、内存属性的设置等,还有C库的标准内存操作函数。 - -## 接口说明 - -**表 1** 标准C库相关接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口

-

功能

-

strings.h

-

int bcmp(const void *s1, const void *s2, size_t n)

-

比较字节序列。

-

strings.h

-

void bcopy(const void *src, void *dest, size_t n)

-

拷贝字节序列。

-

strings.h

-

void bzero(void *s, size_t n)

-

写入零值字节。

-

string.h

-

void *memccpy(void *dest, const void *src, int c, size_t n)

-

拷贝src 所指的内存内容前n 个字节到dest 所指的地址上。复制时检查参数c 是否出现,若是则返回dest 中值为c 的下一个字节地址。

-

string.h

-

void *memchr(const void *s, int c, size_t n)

-

在s所指内存的前n个字节中查找c。

-

string.h

-

int memcmp(const void *s1, const void *s2, size_t n)

-

内存比较。

-

string.h

-

void *memcpy(void *dest, const void *src, size_t n)

-

内存拷贝。

-

string.h

-

void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen)

-

找到一个子串。

-

string.h

-

void *memmove(void *dest, const void *src, size_t n)

-

内存移动。

-

string.h

-

void *mempcpy(void *dest, const void *src, size_t n)

-

拷贝内存区域。

-

string.h

-

void *memset(void *s, int c, size_t n)

-

内存初始化。

-

stdlib.h

-

void *malloc(size_t size)

-

申请内存。

-

stdlib.h

-

void *calloc(size_t nmemb, size_t size)

-

申请内存并清零。

-

stdlib.h

-

void *realloc(void *ptr, size_t size)

-

重分配内存。

-

stdlib.h/malloc.h

-

void *valloc(size_t size)

-

分配以页对齐的内存。

-

stdlib.h

-

void free(void *ptr)

-

释放内存。

-

malloc.h

-

size_t malloc_usable_size(void *ptr)

-

获取从堆分配的内存块的大小。

-

unistd.h

-

int getpagesize(void)

-

获取页面大小。

-

unistd.h

-

void *sbrk(intptr_t increment)

-

更改数据段大小。

-
- -差异接口详细说明: - -- **mmap** - - **函数原型:** - - void \*mmap\(void \*addr, size\_t length, int prot, int flags, int fd, off\_t offset\); - - **函数功能:**申请虚拟内存。 - - **参数说明:** - - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

描述

-

addr

-

用来请求使用某个特定的虚拟内存地址。如果取NULL,结果地址就将自动分配(这是推荐的做法),否则会降低程序的可移植性,因为不同系统的可用地址范围不一样。

-

length

-

内存段的大小。

-

prot

-

用于设置内存段的访问权限,有如下权限:

-
  • PROT_READ:允许读该内存段。
  • PROT_WRITE:允许写该内存段。
  • PROT_EXEC:允许执行该内存段。
  • PROT_NONE:不能访问。
-

flags

-

控制程序对内存段的改变所造成的影响,有如下属性:

-
  • MAP_PRIVATE:内存段私有,对它的修改值仅对本进程有效。
  • MAP_SHARED:把对该内存段的修改保存到磁盘文件中。
-

fd

-

打开的文件描述符。

-

offset

-

用以改变经共享内存段访问的文件中数据的起始偏移值。

-
- - >![](public_sys-resources/icon-note.gif) **说明:** - >mmap与Linux实现差异详见[与Linux标准库的差异](与Linux标准库的差异.md)章节。 - - **返回值:** - - - 成功返回:虚拟内存地址,这地址是页对齐。 - - 失败返回:\(void \*\)-1。 - - -- **munmap接口** - - **函数原型:** - - int munmap\(void \*addr, size\_t length\); - - **函数功能:**释放虚拟内存。 - - **参数说明:** - - - - - - - - - - - - - -

参数

-

描述

-

addr

-

虚拟内存起始位置。

-

length

-

内存段的大小。

-
- - **返回值:** - - - 成功返回0。 - - 失败返回-1。 - - -- **mprotect接口** - - **函数原型:** - - int mprotect\(void \*addr, size\_t length, int prot\); - - **函数功能:**修改内存段的访问权限。 - - **参数说明:** - - - - - - - - - - - - - - - - -

参数

-

描述

-

addr

-

内存段起始地址,必须页对齐;访问权限异常,内核将直接抛异常并且kill该进程,而不会产生SIGSEGV信号给当前进程。

-

length

-

内存段的大小。

-

prot

-

内存段的访问权限,有如下定义:

-
  • PROT_READ:允许读该内存段。
  • PROT_WRITE:允许写该内存段。
  • PROT_EXEC:允许执行该内存段。
  • PROT_NONE:不能访问。
-
- - **返回值:** - - - 成功返回0。 - - 失败返回-1。 - - -- **mremap接口** - - **函数原型:** - - void \*mremap\(void \*old\_address, size\_t old\_size, size\_t new\_size, int flags, void new\_address\); - - **函数功能:**重新映射虚拟内存地址。 - - **参数说明:** - - - - - - - - - - - - - - - - - - - -

参数

-

描述

-

old_address

-

需要扩大(或缩小)的内存段的原始地址。注意old_address必须是页对齐。

-

old_size

-

内存段的原始大小。

-

new_size

-

新内存段的大小。

-

flags

-

如果没有足够的空间在当前位置展开映射,则返回失败

-
  • MREMAP_MAYMOVE:允许内核将映射重定位到新的虚拟地址。
  • MREMAP_FIXED:mremap()接受第五个参数,void *new_address,该参数指定映射地址必须页对齐;在new_address和new_size指定的地址范围内的所有先前映射都被解除映射。如果指定了MREMAP_FIXED,还必须指定MREMAP_MAYMOVE。
-
- - **返回值:** - - - 成功返回:重新映射后的虚拟内存地址。 - - 失败返回:\(\(void \*\)-1\)。 - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" deleted file mode 100644 index f0dce32252a444dc8b0d715477e2aeb2e0740bda..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\344\277\241\346\201\257\347\273\237\350\256\241.md" +++ /dev/null @@ -1,107 +0,0 @@ -# 内存信息统计 - -- [基础概念](#section52691565235) -- [功能配置](#section470611682411) -- [开发指导](#section9368374243) - - [开发流程](#section679912407257) - - [编程实例](#section1025453412611) - - [示例代码](#section165277971315) - - [结果验证](#section3460102414271) - - -## 基础概念 - -内存信息包括内存池大小、内存使用量、剩余内存大小、最大空闲内存、内存水线、内存节点数统计、碎片率等。 - -- 内存水线:即内存池的最大使用量,每次申请和释放时,都会更新水线值,实际业务可根据该值,优化内存池大小; - -- 碎片率:衡量内存池的碎片化程度,碎片率高表现为内存池剩余内存很多,但是最大空闲内存块很小,可以用公式(fragment=100-最大空闲内存块大小/剩余内存大小)来度量; - -- 其他参数:通过调用接口(详见[内存管理](内存管理.md)章节接口说明),扫描内存池的节点信息,统计出相关信息。 - -## 功能配置 - -LOSCFG\_MEM\_WATERLINE:开关宏,默认打开;若关闭这个功能,在target\_config.h中将这个宏定义为0。如需获取内存水线,需要打开该配置。 - -## 开发指导 - -### 开发流程 - -关键结构体介绍: - -``` -typedef struct { - UINT32 totalUsedSize; // 内存池的内存使用量 - UINT32 totalFreeSize; // 内存池的剩余内存大小 - UINT32 maxFreeNodeSize; // 内存池的最大空闲内存块大小 - UINT32 usedNodeNum; // 内存池的非空闲内存块个数 - UINT32 freeNodeNum; // 内存池的空闲内存块个数 -#if (LOSCFG_MEM_WATERLINE == 1) // 默认打开,如需关闭,在target_config.h中将该宏设置为0 - UINT32 usageWaterLine; // 内存池的水线值 -#endif -} LOS_MEM_POOL_STATUS; -``` - -- 内存水线获取:调用LOS\_MemInfoGet接口,第1个参数是内存池首地址,第2个参数是LOS\_MEM\_POOL\_STATUS类型的句柄,其中字段usageWaterLine即水线值。 - -- 内存碎片率计算:同样调用LOS\_MemInfoGet接口,可以获取内存池的剩余内存大小和最大空闲内存块大小,然后根据公式(fragment=100-最大空闲内存块大小/剩余内存大小)得出此时的动态内存池碎片率。 - -### 编程实例 - -本实例实现如下功能: - -1.创建一个监控线程,用于获取内存池的信息; - -2.调用LOS\_MemInfoGet接口,获取内存池的基础信息; - -3.利用公式算出使用率及碎片率。 - -### 示例代码 - -代码实现如下: - -``` -#include -#include -#include "los_task.h" -#include "los_memory.h" -#include "los_config.h" - -void MemInfoTaskFunc(void) -{ - LOS_MEM_POOL_STATUS poolStatus = {0}; - LOS_MemInfoGet(pool, &poolStatus); - /* 算出内存池当前的碎片率百分比 */ - unsigned char fragment = 100 - poolStatus.maxFreeNodeSize * 100 / poolStatus.totalFreeSize; - /* 算出内存池当前的使用率百分比 */ - unsigned char usage = LOS_MemTotalUsedGet(pool) * 100 / LOS_MemPoolSizeGet(pool); - printf("usage = %d, fragment = %d, maxFreeSize = %d, totalFreeSize = %d, waterLine = %d\n", usage, fragment, poolStatus.maxFreeNodeSize, - poolStatus.totalFreeSize, poolStatus.usageWaterLine); -} - -int MemTest(void) -{ - unsigned int ret; - unsigned int taskID; - TSK_INIT_PARAM_S taskStatus = {0}; - taskStatus.pfnTaskEntry = (TSK_ENTRY_FUNC)MemInfoTaskFunc; - taskStatus.uwStackSize = 0x1000; - taskStatus.pcName = "memInfo"; - taskStatus.usTaskPrio = 10; - ret = LOS_TaskCreate(&taskID, &taskStatus); - if (ret != LOS_OK) { - printf("task create failed\n"); - return -1; - } - return 0; -} -``` - -### 结果验证 - -编译运行输出的结果如下: - -``` -usage = 22, fragment = 3, maxFreeSize = 49056, totalFreeSize = 50132, waterLine = 1414 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" deleted file mode 100644 index 5c57178e5077c4aff25a482ad5b6c4a5ed9f6cb5..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\346\263\204\346\274\217\346\243\200\346\265\213.md" +++ /dev/null @@ -1,128 +0,0 @@ -# 内存泄漏检测 - -- [基础概念](#section1026719436293) -- [功能配置](#section13991354162914) -- [开发指导](#section95828159308) - - [开发流程](#section369844416304) - - [编程实例](#section460801313313) - - [示例代码](#section96539275311) - - [结果验证](#section20527343183119) - - -## 基础概念 - -内存泄漏检测机制作为内核的可选功能,用于辅助定位动态内存泄漏问题。开启该功能,动态内存机制会自动记录申请内存时的函数调用关系(下文简称LR)。如果出现泄漏,就可以利用这些记录的信息,找到内存申请的地方,方便进一步确认。 - -## 功能配置 - -1. LOSCFG\_MEM\_LEAKCHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 -2. LOSCFG\_MEM\_RECORD\_LR\_CNT:记录的LR层数,默认3层;每层LR消耗sizeof\(void \*\)字节数的内存。 -3. LOSCFG\_MEM\_OMIT\_LR\_CNT:忽略的LR层数,默认4层,即从调用LOS\_MemAlloc的函数开始记录,可根据实际情况调整。为啥需要这个配置?有3点原因如下: - - LOS\_MemAlloc接口内部也有函数调用; - - 外部可能对LOS\_MemAlloc接口有封装; - - LOSCFG\_MEM\_RECORD\_LR\_CNT 配置的LR层数有限; - - -正确配置这个宏,将无效的LR层数忽略,就可以记录有效的LR层数,节省内存消耗。 - -## 开发指导 - -### 开发流程 - -该调测功能可以分析关键的代码逻辑中是否存在内存泄漏。开启这个功能,每次申请内存时,会记录LR信息。在需要检测的代码段前后,调用LOS\_MemUsedNodeShow接口,每次都会打印指定内存池已使用的全部节点信息,对比前后两次的节点信息,新增的节点信息就是疑似泄漏的内存节点。通过LR,可以找到具体申请的代码位置,进一步确认是否泄漏。 - -调用LOS\_MemUsedNodeShow接口输出的节点信息格式如下:每1行为一个节点信息;第1列为节点地址,可以根据这个地址,使用GDB等手段查看节点完整信息;第2列为节点的大小,等于节点头大小+数据域大小;第3\~5列为函数调用关系LR地址,可以根据这个值,结合汇编文件,查看该节点具体申请的位置。 - -``` -node size LR[0] LR[1] LR[2] -0x10017320: 0x528 0x9b004eba 0x9b004f60 0x9b005002 -0x10017848: 0xe0 0x9b02c24e 0x9b02c246 0x9b008ef0 -0x10017928: 0x50 0x9b008ed0 0x9b068902 0x9b0687c4 -0x10017978: 0x24 0x9b008ed0 0x9b068924 0x9b0687c4 -0x1001799c: 0x30 0x9b02c24e 0x9b02c246 0x9b008ef0 -0x100179cc: 0x5c 0x9b02c24e 0x9b02c246 0x9b008ef0 -``` - ->![](public_sys-resources/icon-caution.gif) **注意:** ->开启内存检测会影响内存申请的性能,且每个内存节点都会记录LR地址,内存开销也加大。 - -### 编程实例 - -本实例实现如下功能:构建内存泄漏代码段。 - -1. 调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; -2. 申请内存,但没有释放,模拟内存泄漏; -3. 再次调用LOS\_MemUsedNodeShow接口,输出全部节点信息打印; -4. 将两次log进行对比,得出泄漏的节点信息; -5. 通过LR地址,找出泄漏的代码位置; - -### 示例代码 - -代码实现如下: - -``` -#include -#include -#include "los_memory.h" -#include "los_config.h" - -void MemLeakTest(void) -{ - LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); - void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - LOS_MemUsedNodeShow(LOSCFG_SYS_HEAP_ADDR); -} -``` - -### 结果验证 - -编译运行输出log如下: - -``` -node size LR[0] LR[1] LR[2] -0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc -0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc -0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e -0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a -0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 - -node size LR[0] LR[1] LR[2] -0x20001b04: 0x24 0x08001a10 0x080035ce 0x080028fc -0x20002058: 0x40 0x08002fe8 0x08003626 0x080028fc -0x200022ac: 0x40 0x08000e0c 0x08000e56 0x0800359e -0x20002594: 0x120 0x08000e0c 0x08000e56 0x08000c8a -0x20002aac: 0x56 0x08000e0c 0x08000e56 0x08004220 -0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 -``` - -对比两次log,差异如下,这些内存节点就是疑似泄漏的内存块: - -``` -0x20003ac4: 0x1d 0x08001458 0x080014e0 0x080041e6 -0x20003ae0: 0x1d 0x080041ee 0x08000cc2 0x00000000 -``` - -部分汇编文件如下: - -``` - MemLeakTest: - 0x80041d4: 0xb510 PUSH {R4, LR} - 0x80041d6: 0x4ca8 LDR.N R4, [PC, #0x2a0] ; g_memStart - 0x80041d8: 0x0020 MOVS R0, R4 - 0x80041da: 0xf7fd 0xf93e BL LOS_MemUsedNodeShow ; 0x800145a - 0x80041de: 0x2108 MOVS R1, #8 - 0x80041e0: 0x0020 MOVS R0, R4 - 0x80041e2: 0xf7fd 0xfbd9 BL LOS_MemAlloc ; 0x8001998 - 0x80041e6: 0x2108 MOVS R1, #8 - 0x80041e8: 0x0020 MOVS R0, R4 - 0x80041ea: 0xf7fd 0xfbd5 BL LOS_MemAlloc ; 0x8001998 - 0x80041ee: 0x0020 MOVS R0, R4 - 0x80041f0: 0xf7fd 0xf933 BL LOS_MemUsedNodeShow ; 0x800145a - 0x80041f4: 0xbd10 POP {R4, PC} - 0x80041f6: 0x0000 MOVS R0, R0 -``` - -其中,通过查找0x080041ee,就可以发现该内存节点是在MemLeakTest接口里申请的且是没有释放的。 - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" deleted file mode 100644 index fb44d9bd13bde98aa1ac6c90c8b45856b63b8ed2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\347\256\241\347\220\206.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 内存管理 - -- **[基本概念](基本概念-4.md)** - -- **[静态内存](静态内存.md)** - -- **[动态内存](动态内存.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" deleted file mode 100644 index 82555bc86205532b29ab368edfe3adc72ba10287..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\345\255\230\350\260\203\346\265\213.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 内存调测 - -内存调测方法旨在辅助定位动态内存相关问题,提供了基础的动态内存池信息统计手段,向用户呈现内存池水线、碎片率等信息;提供了内存泄漏检测手段,方便用户准确定位存在内存泄漏的代码行,也可以辅助分析系统各个模块内存的使用情况;提供了踩内存检测手段,可以辅助定位越界踩内存的场景。 - -- **[内存信息统计](内存信息统计.md)** - -- **[内存泄漏检测](内存泄漏检测.md)** - -- **[踩内存检测](踩内存检测.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" deleted file mode 100644 index 6b7080f2bcbb60138e4f258cf3a20b1f35be9618..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\206\205\346\240\270\350\260\203\346\265\213.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 内核调测 - -- **[内存调测](内存调测.md)** - -- **[异常调测](异常调测.md)** - -- **[Trace调测](Trace调测.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" "b/zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" deleted file mode 100644 index 05922df9f795ac26bfa94d71858bab47dda9a8de..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\212\250\346\200\201\345\206\205\345\255\230.md" +++ /dev/null @@ -1,227 +0,0 @@ -# 动态内存 - -- [运行机制](#section328282013571) -- [开发指导](#section7921151015814) - - [使用场景](#section326917198583) - - [接口说明](#section1032331584) - - [开发流程](#section07271773592) - - [编程实例](#section84931234145913) - - [结果验证](#section165233233917) - - -## 运行机制 - -动态内存管理,即在内存资源充足的情况下,根据用户需求,从系统配置的一块比较大的连续内存(内存池,也是堆内存)中分配任意大小的内存块。当用户不需要该内存块时,又可以释放回系统供下一次使用。与静态内存相比,动态内存管理的优点是按需分配,缺点是内存池中容易出现碎片。 - -OpenHarmony LiteOS-M动态内存在TLSF算法的基础上,对区间的划分进行了优化,获得更优的性能,降低了碎片率。动态内存核心算法框图如下: - -**图 1** 动态内存核心算法 -![](figures/动态内存核心算法.png "动态内存核心算法") - -根据空闲内存块的大小,使用多个空闲链表来管理。根据内存空闲块大小分为两个部分:\[4, 127\]和\[27, 231\],如上图size class所示: - -1. 对\[4,127\]区间的内存进行等分,如上图绿色部分所示,分为31个小区间,每个小区间对应内存块大小为4字节的倍数。每个小区间对应一个空闲内存链表和用于标记对应空闲内存链表是否为空的一个比特位,值为1时,空闲链表非空。\[4,127\]区间的31个小区间内存对应31个比特位进行标记链表是否为空。 -2. 大于127字节的空闲内存块,按照2的次幂区间大小进行空闲链表管理。总共分为24个小区间,每个小区间又等分为8个二级小区间,见上图蓝色的Size Class和Size SubClass部分。每个二级小区间对应一个空闲链表和用于标记对应空闲内存链表是否为空的一个比特位。总共24\*8=192个二级小区间,对应192个空闲链表和192个比特位进行标记链表是否为空。 - -例如,当有40字节的空闲内存需要插入空闲链表时,对应小区间\[40,43\],第10个空闲链表,位图标记的第10比特位。把40字节的空闲内存挂载第10个空闲链表上,并判断是否需要更新位图标记。当需要申请40字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。当有580字节的空闲内存需要插入空闲链表时,对应二级小区间\[2^9,2^9+2^6\],第31+2\*8=47个空闲链表,并使用位图的第47个比特位来标记链表是否为空。把580字节的空闲内存挂载第47个空闲链表上,并判断是否需要更新位图标记。当需要申请580字节的内存时,根据位图标记获取存在满足申请大小的内存块的空闲链表,从空闲链表上获取空闲内存节点。如果分配的节点大于需要申请的内存大小,进行分割节点操作,剩余的节点重新挂载到相应的空闲链表上。如果对应的空闲链表为空,则向更大的内存区间去查询是否有满足条件的空闲链表,实际计算时,会一次性查找到满足申请大小的空闲链表。 - -内存管理结构如下图所示: - -**图 2** 动态内存管理结构图 -![](figures/动态内存管理结构图.png "动态内存管理结构图") - -- 内存池池头部分 - - 内存池池头部分包含内存池信息、位图标记数组和空闲链表数组。内存池信息包含内存池起始地址及堆区域总大小,内存池属性。位图标记数组有7个32位无符号整数组成,每个比特位标记对应的空闲链表是否挂载空闲内存块节点。空闲内存链表包含223个空闲内存头节点信息,每个空闲内存头节点信息维护内存节点头和空闲链表中的前驱、后继空闲内存节点。 - -- 内存池节点部分 - - 包含3种类型节点:未使用空闲内存节点,已使用内存节点和尾节点。每个内存节点维护一个前序指针,指向内存池中上一个内存节点,还维护内存节点的大小和使用标记。空闲内存节点和已使用内存节点后面的内存区域是数据域,尾节点没有数据域。 - - -## 开发指导 - -### 使用场景 - -动态内存管理的主要工作是动态分配并管理用户申请到的内存区间。动态内存管理主要用于用户需要使用大小不等的内存块的场景,当用户需要使用内存时,可以通过操作系统的动态内存申请函数索取指定大小的内存块,一旦使用完毕,通过动态内存释放函数归还所占用内存,使之可以重复使用。 - -### 接口说明 - -OpenHarmony LiteOS-M的动态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 - -**表 1** 动态内存模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

初始化和删除内存池

-

LOS_MemInit

-

初始化一块指定的动态内存池,大小为size。

-

LOS_MemDeInit

-

删除指定内存池,仅打开LOSCFG_MEM_MUL_POOL时有效。

-

申请、释放动态内存

-

LOS_MemAlloc

-

从指定动态内存池中申请size长度的内存。

-

LOS_MemFree

-

释放从指定动态内存中申请的内存。

-

LOS_MemRealloc

-

按size大小重新分配内存块,并将原内存块内容拷贝到新内存块。如果新内存块申请成功,则释放原内存块。

-

LOS_MemAllocAlign

-

从指定动态内存池中申请长度为size且地址按boundary字节对齐的内存。

-

获取内存池信息

-

LOS_MemPoolSizeGet

-

获取指定动态内存池的总大小。

-

LOS_MemTotalUsedGet

-

获取指定动态内存池的总使用量大小。

-

LOS_MemInfoGet

-

获取指定内存池的内存结构信息,包括空闲内存大小、已使用内存大小、空闲内存块数量、已使用的内存块数量、最大的空闲内存块大小。

-

LOS_MemPoolList

-

打印系统中已初始化的所有内存池,包括内存池的起始地址、内存池大小、空闲内存总大小、已使用内存总大小、最大的空闲内存块大小、空闲内存块数量、已使用的内存块数量。仅打开LOSCFG_MEM_MUL_POOL时有效。

-

获取内存块信息

-

LOS_MemFreeNodeShow

-

打印指定内存池的空闲内存块的大小及数量。

-

LOS_MemUsedNodeShow

-

打印指定内存池的已使用内存块的大小及数量。

-

检查指定内存池的完整性

-

LOS_MemIntegrityCheck

-

对指定内存池做完整性检查,仅打开LOSCFG_BASE_MEM_NODE_INTEGRITY_CHECK时有效。

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->- 由于动态内存管理需要管理控制块数据结构来管理内存,这些数据结构会额外消耗内存,故实际用户可使用内存总量小于配置项OS\_SYS\_MEM\_SIZE的大小。 ->- 对齐分配内存接口LOS\_MemAllocAlign/LOS\_MemMallocAlign因为要进行地址对齐,可能会额外消耗部分内存,故存在一些遗失内存,当系统释放该对齐内存时,同时回收由于对齐导致的遗失内存。 - -### 开发流程 - -本节介绍使用动态内存的典型场景开发流程。 - -1. 初始化LOS\_MemInit。 - - 初始一个内存池后生成一个内存池控制头、尾节点EndNode,剩余的内存被标记为FreeNode内存节点。注:EndNode作为内存池末尾的节点,size为0。 - - -1. 申请任意大小的动态内存LOS\_MemAlloc。 - - 判断动态内存池中是否存在大于申请量大小的空闲内存块空间,若存在,则划出一块内存块,以指针形式返回,若不存在,返回NULL。如果空闲内存块大于申请量,需要对内存块进行分割,剩余的部分作为空闲内存块挂载到空闲内存链表上。 - - -1. 释放动态内存LOS\_MemFree。 - - 回收内存块,供下一次使用。调用LOS\_MemFree释放内存块,则会回收内存块,并且将其标记为FreeNode。在回收内存块时,相邻的FreeNode会自动合并。 - - -### 编程实例 - -本实例执行以下步骤: - -1. 初始化一个动态内存池。 -2. 从动态内存池中申请一个内存块。 -3. 在内存块中存放一个数据。 -4. 打印出内存块中的数据。 -5. 释放该内存块。 - -示例代码如下: - -``` -#include "los_memory.h" - -VOID Example_DynMem(VOID) -{ - UINT32 *mem = NULL; - UINT32 ret; - - /*初始化内存池*/ - ret = LOS_MemInit(g_testPool, TEST_POOL_SIZE); - if (LOS_OK == ret) { - printf("Mem init success!\n"); - } else { - printf("Mem init failed!\n"); - return; - } - - /*分配内存*/ - mem = (UINT32 *)LOS_MemAlloc(g_testPool, 4); - if (NULL == mem) { - printf("Mem alloc failed!\n"); - return; - } - printf("Mem alloc success!\n"); - - /*赋值*/ - *mem = 828; - printf("*mem = %d\n", *mem); - - /*释放内存*/ - ret = LOS_MemFree(g_testPool, mem); - if (LOS_OK == ret) { - printf("Mem free success!\n"); - } else { - printf("Mem free failed!\n"); - } - - return; -} -``` - -### 结果验证 - -输出结果如下: - -``` -Mem init success! -Mem alloc success! -*mem = 828 -Mem free success! -``` - diff --git "a/zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" "b/zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" deleted file mode 100644 index 8b9323d6187bdca8b70e5da46a3e718326d6f937..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\217\214\345\220\221\351\223\276\350\241\250.md" +++ /dev/null @@ -1,191 +0,0 @@ -# 双向链表 - -- [基本概念](#section1990715203418) -- [功能说明](#section848334511411) -- [开发流程](#section01781261552) -- [编程实例](#section67569495514) - - [实例描述](#section48761994551) - - [示例代码](#section1280202685519) - - [结果验证](#section5811249105512) - - -## 基本概念 - -双向链表是指含有往前和往后两个方向的链表,即每个结点中除存放下一个节点指针外,还增加一个指向前一个节点的指针。其头指针head是唯一确定的。 - -从双向链表中的任意一个结点开始,都可以很方便地访问它的前驱结点和后继结点,这种数据结构形式使得双向链表在查找时更加方便,特别是大量数据的遍历。由于双向链表具有对称性,能方便地完成各种插入、删除等操作,但需要注意前后方向的操作。 - -## 功能说明 - -双向链表模块为用户提供下面几种功能,接口详细信息可以查看API参考。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

初始化链表

-

LOS_ListInit

-

将指定双向链表节点初始化为双向链表

-

LOS_DL_LIST_HEAD

-

定义一个双向链表节点并以该节点初始化为双向链表

-

增加节点

-

LOS_ListAdd

-

将指定节点插入到双向链表头端

-

LOS_ListTailInsert

-

将指定节点插入到双向链表尾端

-

删除节点

-

LOS_ListDelete

-

将指定节点从链表中删除

-

LOS_ListDelInit

-

将指定节点从链表中删除,并使用该节点初始化链表

-

判断双向链表是否为空

-

LOS_ListEmpty

-

判断链表是否为空

-

获取结构体信息

-

LOS_DL_LIST_ENTRY

-

获取包含链表的结构体地址,接口的第一个入参表示的是链表中的某个节点,第二个入参是要获取的结构体名称,第三个入参是链表在该结构体中的名称

-

LOS_OFF_SET_OF

-

获取指定结构体内的成员相对于结构体起始地址的偏移量

-

遍历双向链表

-

LOS_DL_LIST_FOR_EACH

-

遍历双向链表

-

LOS_DL_LIST_FOR_EACH_SAFE

-

遍历双向链表,并存储当前节点的后继节点用于安全校验

-

遍历包含双向链表的结构体

-

LOS_DL_LIST_FOR_EACH_ENTRY

-

遍历指定双向链表,获取包含该链表节点的结构体地址

-

LOS_DL_LIST_FOR_EACH_ENTRY_SAFE

-

遍历指定双向链表,获取包含该链表节点的结构体地址,并存储包含当前节点的后继节点的结构体地址

-
- -## 开发流程 - -双向链表的典型开发流程: - -1. 调用LOS\_ListInit/LOS\_DL\_LIST\_HEAD初始双向链表。 -2. 调用LOS\_ListAdd向链表插入节点。 -3. 调用LOS\_ListTailInsert向链表尾部插入节点。 -4. 调用LOS\_ListDelete删除指定节点。 -5. 调用LOS\_ListEmpty判断链表是否为空。 -6. 调用LOS\_ListDelInit删除指定节点并以此节点初始化链表。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 需要注意节点指针前后方向的操作。 ->- 链表操作接口,为底层接口,不对入参进行判空,需要使用者确保传参合法。 ->- 如果链表节点的内存是动态申请的,删除节点时,要注意释放内存。 - -## 编程实例 - -### 实例描述 - -本实例实现如下功能: - -1. 初始化双向链表。 -2. 增加节点。 -3. 删除节点。 -4. 测试操作是否成功。 - -### 示例代码 - -示例代码如下: - -``` -#include "stdio.h" -#include "los_list.h" - -static UINT32 ListSample(VOID) -{ - LOS_DL_LIST listHead = {NULL,NULL}; - LOS_DL_LIST listNode1 = {NULL,NULL}; - LOS_DL_LIST listNode2 = {NULL,NULL}; - - //首先初始化链表 - printf("Initial head\n"); - LOS_ListInit(&listHead); - - //添加节点1和节点2,并校验他们的相互关系 - LOS_ListAdd(&listHead, &listNode1); - if (listNode1.pstNext == &listHead && listNode1.pstPrev == &listHead) { - printf("Add listNode1 success\n"); - } - - LOS_ListTailInsert(&listHead, &listNode2); - if (listNode2.pstNext == &listHead && listNode2.pstPrev == &listNode1) { - printf("Tail insert listNode2 success\n"); - } - - //删除两个节点 - LOS_ListDelete(&listNode1); - LOS_ListDelete(&listNode2); - - //确认链表为空 - if (LOS_ListEmpty(&listHead)) { - printf("Delete success\n"); - } - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Initial head -Add listNode1 success -Tail insert listNode2 success -Delete success -``` - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" deleted file mode 100644 index 5464ca3ceec7232da4ed7051b1c38258e7c4a7c3..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\225\260\346\215\256\347\273\223\346\236\204.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 基本数据结构 - -- **[双向链表](双向链表.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" deleted file mode 100644 index dd72ce5e104fdf75ce5dcb71967eae9b0aaf7fab..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-11.md" +++ /dev/null @@ -1,53 +0,0 @@ -# 基本概念 - -- [运行机制](#section1794010261861) - - [信号量控制块](#section11372149164815) - - [信号量运作原理](#section139726510491) - - -信号量(Semaphore)是一种实现任务间通信的机制,可以实现任务间同步或共享资源的互斥访问。 - -一个信号量的数据结构中,通常有一个计数值,用于对有效资源数的计数,表示剩下的可被使用的共享资源数,其值的含义分两种情况: - -- 0,表示该信号量当前不可获取,因此可能存在正在等待该信号量的任务。 -- 正值,表示该信号量当前可被获取。 - -以同步为目的的信号量和以互斥为目的的信号量在使用上有如下不同: - -- 用作互斥时,初始信号量计数值不为0,表示可用的共享资源个数。在需要使用共享资源前,先获取信号量,然后使用一个共享资源,使用完毕后释放信号量。这样在共享资源被取完,即信号量计数减至0时,其他需要获取信号量的任务将被阻塞,从而保证了共享资源的互斥访问。另外,当共享资源数为1时,建议使用二值信号量,一种类似于互斥锁的机制。 -- 用作同步时,初始信号量计数值为0。任务1获取信号量而阻塞,直到任务2或者某中断释放信号量,任务1才得以进入Ready或Running态,从而达到了任务间的同步。 - -## 运行机制 - -### 信号量控制块 - -``` -/** - * 信号量控制块数据结构 - */ -typedef struct { - UINT16 semStat; /* 信号量状态 */ - UINT16 semType; /* 信号量类型 */ - UINT16 semCount; /* 信号量计数 */ - UINT16 semId; /* 信号量索引号 */ - LOS_DL_LIST semList; /* 挂接阻塞于该信号量的任务 */ -} LosSemCB; -``` - -### 信号量运作原理 - -信号量初始化,为配置的N个信号量申请内存(N值可以由用户自行配置,通过LOSCFG\_BASE\_IPC\_SEM\_LIMIT宏实现),并把所有信号量初始化成未使用,加入到未使用链表中供系统使用。 - -信号量创建,从未使用的信号量链表中获取一个信号量,并设定初值。 - -信号量申请,若其计数器值大于0,则直接减1返回成功。否则任务阻塞,等待其它任务释放该信号量,等待的超时时间可设定。当任务被一个信号量阻塞时,将该任务挂到信号量等待任务队列的队尾。 - -信号量释放,若没有任务等待该信号量,则直接将计数器加1返回。否则唤醒该信号量等待任务队列上的第一个任务。 - -信号量删除,将正在使用的信号量置为未使用信号量,并挂回到未使用链表。 - -信号量允许多个任务在同一时刻访问共享资源,但会限制同一时刻访问此资源的最大任务数目。当访问资源的任务数达到该资源允许的最大数量时,会阻塞其他试图获取该资源的任务,直到有任务释放该信号量。 - -**图 1** 信号量运作示意图 -![](figures/信号量运作示意图.png "信号量运作示意图") - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" deleted file mode 100644 index db5ae0ccd5e29fe476b391b83bd3c4ff13199e53..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-2.md" +++ /dev/null @@ -1,96 +0,0 @@ -# 基本概念 - -- [任务相关概念](#section673132352511) -- [任务运行机制](#section176294469251) - -从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,并独立于其它任务运行。 - -OpenHarmony LiteOS-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。任务模块具有如下特性: - -- 支持多任务。 -- 一个任务表示一个线程。 -- 抢占式调度机制,高优先级的任务可打断低优先级任务,低优先级任务必须在高优先级任务阻塞或结束后才能得到调度。 -- 相同优先级任务支持时间片轮转调度方式。 -- 共有32个优先级\[0-31\],最高优先级为0,最低优先级为31。 - -## 任务相关概念 - -**任务状态** - -任务有多种运行状态。系统初始化完成后,创建的任务就可以在系统中竞争一定的资源,由内核进行调度。 - -任务状态通常分为以下四种: - -- 就绪(Ready):该任务在就绪队列中,只等待CPU。 -- 运行(Running):该任务正在执行。 -- 阻塞(Blocked):该任务不在就绪队列中。包含任务被挂起(suspend状态)、任务被延时(delay状态)、任务正在等待信号量、读写队列或者等待事件等。 -- 退出态(Dead):该任务运行结束,等待系统回收资源。 - -**任务状态迁移** - -**图 1** 任务状态示意图 -![](figures/任务状态示意图.png "任务状态示意图") - -**任务状态迁移说明:** - -- 就绪态→运行态 - - 任务创建后进入就绪态,发生任务切换时,就绪队列中最高优先级的任务被执行,从而进入运行态,同时该任务从就绪队列中移出。 - -- 运行态→阻塞态 - - 正在运行的任务发生阻塞(挂起、延时、读信号量等)时,该任务会从就绪队列中删除,任务状态由运行态变成阻塞态,然后发生任务切换,运行就绪队列中最高优先级任务。 - -- 阻塞态→就绪态(阻塞态→运行态) - - 阻塞的任务被恢复后(任务恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的任务会被加入就绪队列,从而由阻塞态变成就绪态;此时如果被恢复任务的优先级高于正在运行任务的优先级,则会发生任务切换,该任务由就绪态变成运行态。 - -- 就绪态→阻塞态 - - 任务也有可能在就绪态时被阻塞(挂起),此时任务状态由就绪态变为阻塞态,该任务从就绪队列中删除,不会参与任务调度,直到该任务被恢复。 - -- 运行态→就绪态 - - 有更高优先级任务创建或者恢复后,会发生任务调度,此刻就绪队列中最高优先级任务变为运行态,那么原先运行的任务由运行态变为就绪态,依然在就绪队列中。 - -- 运行态→退出态 - - 运行中的任务运行结束,任务状态由运行态变为退出态。退出态包含任务运行结束的正常退出状态以及Invalid状态。例如,任务运行结束但是没有自删除,对外呈现的就是Invalid状态,即退出态。 - -- 阻塞态→退出态 - - 阻塞的任务调用删除接口,任务状态由阻塞态变为退出态。 - - -**任务ID** - -任务ID,在任务创建时通过参数返回给用户,是任务的重要标识。系统中的ID号是唯一的。用户可以通过任务ID对指定任务进行任务挂起、任务恢复、查询任务名等操作。 - -**任务优先级** - -优先级表示任务执行的优先顺序。任务的优先级决定了在发生任务切换时即将要执行的任务,就绪队列中最高优先级的任务将得到执行。 - -**任务入口函数** - -新任务得到调度后将执行的函数。该函数由用户实现,在任务创建时,通过任务创建结构体设置。 - -**任务栈** - -每个任务都拥有一个独立的栈空间,我们称为任务栈。栈空间里保存的信息包含局部变量、寄存器、函数参数、函数返回地址等。 - -**任务上下文** - -任务在运行过程中使用的一些资源,如寄存器等,称为任务上下文。当这个任务挂起时,其他任务继续执行,可能会修改寄存器等资源中的值。如果任务切换时没有保存任务上下文,可能会导致任务恢复后出现未知错误。因此在任务切换时会将切出任务的任务上下文信息,保存在自身的任务栈中,以便任务恢复后,从栈空间中恢复挂起时的上下文信息,从而继续执行挂起时被打断的代码。 - -**任务控制块TCB** - -每个任务都含有一个任务控制块\(TCB\)。TCB包含了任务上下文栈指针(stack pointer)、任务状态、任务优先级、任务ID、任务名、任务栈大小等信息。TCB可以反映出每个任务运行情况。 - -**任务切换** - -任务切换包含获取就绪队列中最高优先级任务、切出任务上下文保存、切入任务上下文恢复等动作。 - -## 任务运行机制 - -用户创建任务时,系统会初始化任务栈,预置上下文。此外,系统还会将“任务入口函数”地址放在相应位置。这样在任务第一次启动进入运行态时,将会执行“任务入口函数”。 - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" deleted file mode 100644 index 310f6014ea284196a44041b9ae68651d14d58555..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-21.md" +++ /dev/null @@ -1,82 +0,0 @@ -# 基本概念 - -- [运行机制](#section10284121317365) - - [日志方式](#section13804114513361) - - [Cow机制](#section172771130193610) - - [lfs掉电保护](#section42941021173614) - - -LittleFS主要用在微控制器和flash上,是一种嵌入式文件系统,具有如下3个特点: - -1. 掉电恢复 - - 在写入时即使复位或者掉电也可以恢复到上一个正确的状态。 - -2. 擦写均衡 - - 有效延长flash的使用寿命。 - -3. 有限的RAM/ROM - - 节省ROM和RAM空间。 - - -## 运行机制 - -最经典的掉电保护方法有两种,一种是使用日志,一种是通过COW方式。lfs结合了两种方法,并优化了两种方案的缺点,提供了一套掉电保护策略 - -### 日志方式 - -![](figures/zh-cn_image_0000001124310992.png) - -具体步骤为: - -1. 写入数据之前,先在日志区存储开始标志,记录要写入的数据位置和大小; -2. 待写入的数据写入日志区; -3. 待写入的数据写入数据区; -4. 写入完成之后,在日志区记录结束标志。 - -模拟掉电场景: - -1. 步骤1完成,步骤2没有完成;重启之后,保持原来的数据,日志无效; -2. 步骤1,2完成了,步骤3没有完成,尝试把步骤2的数据写入到数据区; -3. 步骤1,2,3完成了,步骤4没有完成,同样尝试把步骤2的数据写入到数据区; - -### Cow机制 - -![](figures/zh-cn_image_0000001170790681.png) - -具体步骤为: - -1. 想更新节点F的数据,先申请一个新的节点,把F的旧数据拷贝过去,然后更新新的数据; -2. 把父节点的指针指向新的节点,去掉旧节点的指针。 - -模拟掉电场景: - -步骤1完成了,步骤2没有完成,则使用旧的数据,新的节点变成孤儿节点。 - -### lfs掉电保护 - -fs结合了日志方式和COW机制两种方式进行掉电保护,并且优化了两种方案。 - -前面谈过文件系统三要素,超级块,inode,以及数据。对应lfs来说,他把超级块以及inode通过日志的方式存储,两种采用统一的存储结构,后文称两者为元数据;普通数据则采用cow的方式存储,采用czt逆序链表的方式。 - -![](figures/zh-cn_image_0000001124307264.png) - -**元数据的存储** - -![](figures/zh-cn_image_0000001124147160.png) - -元数据(对应root,dir)采用双block的方式存储,互为备份,每个block都有一个revision序号,值越大,表示block的数据越新,每个block默认可以存储最多0xff个文件的数据,如果超过这个值,则需要compact(压缩)。 - -Compact是干什么呢? 即当数据的大小大于某个值的时候,把数据整合,剔除同一个id的旧的数据,然后写入到备份block里面。 - -**普通数据的存储** - -Lfs的数据采用链表的方式逆向管理。 - -![](figures/zh-cn_image_0000001124306828.png) - -1. 采用逆向的指针,这样常规的追加数据,不需要额外的开销来重新建立所有的索引; -2. 每个偶数block有多个指针,指向更远的数据,这样可以在检索的时候加快速度。 - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" deleted file mode 100644 index a96f943c8d815c0e4274c22744ae6ca33b5d9bb1..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-5.md" +++ /dev/null @@ -1,52 +0,0 @@ -# 基本概念 - -- [运行机制](#section1735611583011) - - [事件控制块](#section1161415384467) - - [事件运作原理](#section187761153144617) - - -事件(Event)是一种任务间的通信机制,可用于任务间的同步操作。事件的特点是: - -- 任务间的事件同步,可以一对多,也可以多对多。一对多表示一个任务可以等待多个事件,多对多表示多个任务可以等待多个事件。但是一次写事件最多触发一个任务从阻塞中醒来。 -- 事件读超时机制。 -- 只做任务间同步,不传输具体数据。 - -提供了事件初始化、事件读写、事件清零、事件销毁等接口。 - -## 运行机制 - -### 事件控制块 - -``` -/** - * 事件控制块数据结构 - */ -typedef struct tagEvent { - UINT32 uwEventID; /* 事件集合,表示已经处理(写入和清零)的事件集合 */ - LOS_DL_LIST stEventList; /* 等待特定事件的任务链表 */ -} EVENT_CB_S, *PEVENT_CB_S; -``` - -### 事件运作原理 - -**事件初始化:**会创建一个事件控制块,该控制块维护一个已处理的事件集合,以及等待特定事件的任务链表。 - -**写事件:**会向事件控制块写入指定的事件,事件控制块更新事件集合,并遍历任务链表,根据任务等待具体条件满足情况决定是否唤醒相关任务。 - -**读事件:**如果读取的事件已存在时,会直接同步返回。其他情况会根据超时时间以及事件触发情况,来决定返回时机:等待的事件条件在超时时间耗尽之前到达,阻塞任务会被直接唤醒,否则超时时间耗尽该任务才会被唤醒。 - -读事件条件满足与否取决于入参eventMask和mode,eventMask即需要关注的事件。mode是具体处理方式,分以下三种情况: - -LOS\_WAITMODE\_AND:表示eventMask中所有事件都发生时,才返回。 - -LOS\_WAITMODE\_OR:表示eventMask中任何事件发生时,就返回。 - -LOS\_WAITMODE\_CLR:事件读取成功后,对应读取到的事件会被清零。需要配合LOS\_WAITMODE\_AND或者LOS\_WAITMODE\_OR来使用。 - -**事件清零:**根据指定掩码,去对事件控制块的事件集合进行清零操作。当掩码为0时,表示将事件集合全部清零。当掩码为0xffff时,表示不清除任何事件,保持事件集合原状。 - -**事件销毁:**销毁指定的事件控制块。 - -**图 1** 事件运作原理图 -![](figures/事件运作原理图.png "事件运作原理图") - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" deleted file mode 100644 index 4989a0b93edfc85ad0f1a4b5fb50b7f5eaa89019..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-7.md" +++ /dev/null @@ -1,19 +0,0 @@ -# 基本概念 - -- [运行机制](#section115161649726) - -互斥锁又称互斥型信号量,是一种特殊的二值性信号量,用于实现对共享资源的独占式处理。 - -任意时刻互斥锁的状态只有两种,开锁或闭锁。当有任务持有时,互斥锁处于闭锁状态,这个任务获得该互斥锁的所有权。当该任务释放它时,该互斥锁被开锁,任务失去该互斥锁的所有权。当一个任务持有互斥锁时,其他任务将不能再对该互斥锁进行开锁或持有。 - -多任务环境下往往存在多个任务竞争同一共享资源的应用场景,互斥锁可被用于对共享资源的保护从而实现独占式访问。另外互斥锁可以解决信号量存在的优先级翻转问题。 - -## 运行机制 - -多任务环境下会存在多个任务访问同一公共资源的场景,而有些公共资源是非共享的,需要任务进行独占式处理。互斥锁怎样来避免这种冲突呢? - -用互斥锁处理非共享资源的同步访问时,如果有任务访问该资源,则互斥锁为加锁状态。此时其他任务如果想访问这个公共资源则会被阻塞,直到互斥锁被持有该锁的任务释放后,其他任务才能重新访问该公共资源,此时互斥锁再次上锁,如此确保同一时刻只有一个任务正在访问这个公共资源,保证了公共资源操作的完整性。 - -**图 1** 互斥锁运作示意图 -![](figures/互斥锁运作示意图.png "互斥锁运作示意图") - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" "b/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" deleted file mode 100644 index 90541dda60a684efadf642baf6e01e6c01460b79..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\346\234\254\346\246\202\345\277\265-9.md" +++ /dev/null @@ -1,67 +0,0 @@ -# 基本概念 - -- [运行机制](#section1582619446311) - - [队列控制块](#section1648304614720) - - [队列运作原理](#section15384012164811) - - -队列又称消息队列,是一种常用于任务间通信的数据结构。队列接收来自任务或中断的不固定长度消息,并根据不同的接口确定传递的消息是否存放在队列空间中。 - -任务能够从队列里面读取消息,当队列中的消息为空时,挂起读取任务;当队列中有新消息时,挂起的读取任务被唤醒并处理新消息。任务也能够往队列里写入消息,当队列已经写满消息时,挂起写入任务;当队列中有空闲消息节点时,挂起的写入任务被唤醒并写入消息。 - -可以通过调整读队列和写队列的超时时间来调整读写接口的阻塞模式,如果将读队列和写队列的超时时间设置为0,就不会挂起任务,接口会直接返回,这就是非阻塞模式。反之,如果将都队列和写队列的超时时间设置为大于0的时间,就会以阻塞模式运行。 - -消息队列提供了异步处理机制,允许将一个消息放入队列,但不立即处理。同时队列还有缓冲消息的作用,可以使用队列实现任务异步通信,队列具有如下特性: - -- 消息以先进先出的方式排队,支持异步读写。 -- 读队列和写队列都支持超时机制。 -- 每读取一条消息,就会将该消息节点设置为空闲。 -- 发送消息类型由通信双方约定,可以允许不同长度(不超过队列的消息节点大小)的消息。 -- 一个任务能够从任意一个消息队列接收和发送消息。 -- 多个任务能够从同一个消息队列接收和发送消息。 -- 创建队列时所需的队列空间,接口内系统自行动态申请内存。 - -## 运行机制 - -### 队列控制块 - -``` -/** - * 队列控制块数据结构 - */ -typedef struct -{ - UINT8 *queue; /* 队列消息内存空间的指针 */ - UINT16 queueState; /* 队列状态 */ - UINT16 queueLen; /* 队列中消息节点个数,即队列长度 */ - UINT16 queueSize; /* 消息节点大小 */ - UINT16 queueID; /* 队列ID */ - UINT16 queueHead; /* 消息头节点位置(数组下标)*/ - UINT16 queueTail; /* 消息尾节点位置(数组下标)*/ - UINT16 readWriteableCnt[OS_READWRITE_LEN]; /* 数组下标0的元素表示队列中可读消息数, - 数组下标1的元素表示队列中可写消息数 */ - LOS_DL_LIST readWriteList[OS_READWRITE_LEN]; /* 读取或写入消息的任务等待链表, - 下标0:读取链表,下标1:写入链表 */ - LOS_DL_LIST memList; /* 内存块链表 */ -} LosQueueCB; -``` - -每个队列控制块中都含有队列状态,表示该队列的使用情况: - -- OS\_QUEUE\_UNUSED:队列未被使用。 -- OS\_QUEUE\_INUSED:队列被使用中。 - -### 队列运作原理 - -- 创建队列时,创建队列成功会返回队列ID。 -- 在队列控制块中维护着一个消息头节点位置Head和一个消息尾节点位置Tail,用于表示当前队列中消息的存储情况。Head表示队列中被占用的消息节点的起始位置。Tail表示被占用的消息节点的结束位置,也是空闲消息节点的起始位置。队列刚创建时,Head和Tail均指向队列起始位置。 -- 写队列时,根据readWriteableCnt\[1\]判断队列是否可以写入,不能对已满(readWriteableCnt\[1\]为0)队列进行写操作。写队列支持两种写入方式:向队列尾节点写入,也可以向队列头节点写入。尾节点写入时,根据Tail找到起始空闲消息节点作为数据写入对象,如果Tail已经指向队列尾部则采用回卷方式。头节点写入时,将Head的前一个节点作为数据写入对象,如果Head指向队列起始位置则采用回卷方式。 -- 读队列时,根据readWriteableCnt\[0\]判断队列是否有消息需要读取,对全部空闲(readWriteableCnt\[0\]为0)队列进行读操作会引起任务挂起。如果队列可以读取消息,则根据Head找到最先写入队列的消息节点进行读取。如果Head已经指向队列尾部则采用回卷方式。 -- 删除队列时,根据队列ID找到对应队列,把队列状态置为未使用,把队列控制块置为初始状态,并释放队列所占内存。 - -图 1 队列读写数据操作示意图 - -![](figures/zh-cn_image_0000001124146302.png) - -上图对读写队列做了示意,图中只画了尾节点写入方式,没有画头节点写入,但是两者是类似的。 - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" "b/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" deleted file mode 100644 index df2416afdc86ecb4952f852342ae640cb0d88d79..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270-1.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 基础内核 - -- **[中断管理](中断管理.md)** - -- **[任务管理](任务管理.md)** - -- **[内存管理](内存管理.md)** - -- **[IPC](IPC.md)** - -- **[时间管理](时间管理.md)** - -- **[软件定时器](软件定时器.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" deleted file mode 100644 index 94b43451a99a3d3e6b85388a828c0110bd2cc209..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\237\272\347\241\200\345\206\205\346\240\270.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 基础内核 - -- **[进程](进程.md)** - -- **[线程](线程.md)** - -- **[内存](内存.md)** - -- **[网络](网络.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index d24843996311d64f63f2873e2f53b784ee55dd73..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 小型系统内核 - -- **[认识LiteOS-M内核](认识LiteOS-M内核.md)** - -- **[快速入门](快速入门.md)** - -- **[基础内核](基础内核-1.md)** - -- **[扩展组件](扩展组件.md)** - -- **[内核调测](内核调测.md)** - -- **[附录](附录.md)** - - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" deleted file mode 100644 index c521fd755d1194a135d4a538535a5ec81172ad4f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-10.md" +++ /dev/null @@ -1,199 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section2148236125814) - - [示例代码](#section121451047155716) - - [结果验证](#section2742182082117) - - -## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

创建/删除消息队列

-

LOS_QueueCreate

-

创建一个消息队列,由系统动态申请队列空间。

-

LOS_QueueDelete

-

根据队列ID删除一个指定队列。

-

读/写队列(不带拷贝)

-

LOS_QueueRead

-

读取指定队列头节点中的数据(队列节点中的数据实际上是一个地址)。

-

LOS_QueueWrite

-

向指定队列尾节点中写入入参bufferAddr的值(即buffer的地址)。

-

LOS_QueueWriteHead

-

向指定队列头节点中写入入参bufferAddr的值(即buffer的地址)。

-

读/写队列(带拷贝)

-

LOS_QueueReadCopy

-

读取指定队列头节点中的数据。

-

LOS_QueueWriteCopy

-

向指定队列尾节点中写入入参bufferAddr中保存的数据。

-

LOS_QueueWriteHeadCopy

-

向指定队列头节点中写入入参bufferAddr中保存的数据。

-

获取队列信息

-

LOS_QueueInfoGet

-

获取指定队列的信息,包括队列ID、队列长度、消息节点大小、头节点、尾节点、可读节点数量、可写节点数量、等待读操作的任务、等待写操作的任务。

-
- -## 开发流程 - -1. 用LOS\_QueueCreate创建队列。创建成功后,可以得到队列ID。 -2. 通过LOS\_QueueWrite或者LOS\_QueueWriteCopy写队列。 -3. 通过LOS\_QueueRead或者LOS\_QueueReadCopy读队列。 -4. 通过LOS\_QueueInfoGet获取队列信息。 -5. 通过LOS\_QueueDelete删除队列。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 系统支持的最大队列数是指:整个系统的队列资源总个数,而非用户能使用的个数。例如:系统软件定时器多占用一个队列资源,那么用户能使用的队列资源就会减少一个。 ->- 创建队列时传入的队列名和flags暂时未使用,作为以后的预留参数。 ->- 队列接口函数中的入参timeOut是相对时间。 ->- LOS\_QueueReadCopy和LOS\_QueueWriteCopy及LOS\_QueueWriteHeadCopy是一组接口,LOS\_QueueRead和LOS\_QueueWrite及LOS\_QueueWriteHead是一组接口,每组接口需要配套使用。 ->- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,用户必须保证调用LOS\_QueueRead获取到的指针所指向的内存区域在读队列期间没有被异常修改或释放,否则可能导致不可预知的后果。 ->- 鉴于LOS\_QueueWrite和LOS\_QueueWriteHead和LOS\_QueueRead这组接口实际操作的是数据地址,也就意味着实际写和读的消息长度仅仅是一个指针数据,因此用户使用这组接口之前,需确保创建队列时的消息节点大小,为一个指针的长度,避免不必要的浪费和读取失败。 - -## 编程实例 - -### 实例描述 - -创建一个队列,两个任务。任务1调用写队列接口发送消息,任务2通过读队列接口接收消息。 - -1. 通过LOS\_TaskCreate创建任务1和任务2。 -2. 通过LOS\_QueueCreate创建一个消息队列。 -3. 在任务1 SendEntry中发送消息。 -4. 在任务2 RecvEntry中接收消息。 -5. 通过LOS\_QueueDelete删除队列。 - -### 示例代码 - -示例代码如下: - -``` -#include "los_task.h" -#include "los_queue.h" -static UINT32 g_queue; -#define BUFFER_LEN 50 - -VOID SendEntry(VOID) -{ - UINT32 ret = 0; - CHAR abuf[] = "test message"; - UINT32 len = sizeof(abuf); - - ret = LOS_QueueWriteCopy(g_queue, abuf, len, 0); - if(ret != LOS_OK) { - printf("send message failure, error: %x\n", ret); - } -} - -VOID RecvEntry(VOID) -{ - UINT32 ret = 0; - CHAR readBuf[BUFFER_LEN] = {0}; - UINT32 readLen = BUFFER_LEN; - - //休眠1s - usleep(1000000); - ret = LOS_QueueReadCopy(g_queue, readBuf, &readLen, 0); - if(ret != LOS_OK) { - printf("recv message failure, error: %x\n", ret); - } - - printf("recv message: %s\n", readBuf); - - ret = LOS_QueueDelete(g_queue); - if(ret != LOS_OK) { - printf("delete the queue failure, error: %x\n", ret); - } - - printf("delete the queue success!\n"); -} - -UINT32 ExampleQueue(VOID) -{ - printf("start queue example\n"); - UINT32 ret = 0; - UINT32 task1, task2; - TSK_INIT_PARAM_S initParam = {0}; - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)SendEntry; - initParam.usTaskPrio = 9; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - initParam.pcName = "SendQueue"; - - LOS_TaskLock(); - ret = LOS_TaskCreate(&task1, &initParam); - if(ret != LOS_OK) { - printf("create task1 failed, error: %x\n", ret); - return ret; - } - - initParam.pcName = "RecvQueue"; - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)RecvEntry; - ret = LOS_TaskCreate(&task2, &initParam); - if(ret != LOS_OK) { - printf("create task2 failed, error: %x\n", ret); - return ret; - } - - ret = LOS_QueueCreate("queue", 5, &g_queue, 0, 50); - if(ret != LOS_OK) { - printf("create queue failure, error: %x\n", ret); - } - - printf("create the queue success!\n"); - LOS_TaskUnlock(); - return ret; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -start test example -create the queue success! -recv message: test message -delete the queue success! -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" deleted file mode 100644 index 4a483b339176b6f58c5e4059fb13bd28b3eea629..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-12.md" +++ /dev/null @@ -1,206 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section22061718111412) - - [示例代码](#section1775922321416) - - [结果验证](#section160404016213) - - -## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

创建/删除信号量

-

LOS_SemCreate

-

创建信号量,返回信号量ID

-

LOS_BinarySemCreate

-

创建二值信号量,其计数值最大为1

-

LOS_SemDelete

-

删除指定的信号量

-

申请/释放信号量

-

LOS_SemPend

-

申请指定的信号量,并设置超时时间

-

LOS_SemPost

-

释放指定的信号量

-
- -## 开发流程 - -1. 创建信号量LOS\_SemCreate,若要创建二值信号量则调用LOS\_BinarySemCreate。 -2. 申请信号量LOS\_SemPend。 -3. 释放信号量LOS\_SemPost。 -4. 删除信号量LOS\_SemDelete。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->由于中断不能被阻塞,因此不能在中断中使用阻塞模式申请信号量。 - -## 编程实例 - -### 实例描述 - -本实例实现如下功能: - -1. 测试任务ExampleSem创建一个信号量,锁任务调度,创建两个任务ExampleSemTask1、ExampleSemTask2, ExampleSemTask2优先级高于ExampleSemTask1,两个任务中申请同一信号量,解锁任务调度后两任务阻塞,测试任务ExampleSem释放信号量。 -2. ExampleSemTask2得到信号量,被调度,然后任务休眠20Tick,ExampleSemTask2延迟,ExampleSemTask1被唤醒。 -3. ExampleSemTask1定时阻塞模式申请信号量,等待时间为10Tick,因信号量仍被ExampleSemTask2持有,ExampleSemTask1挂起,10Tick后仍未得到信号量,ExampleSemTask1被唤醒,试图以永久阻塞模式申请信号量,ExampleSemTask1挂起。 -4. 20Tick后ExampleSemTask2唤醒, 释放信号量后,ExampleSemTask1得到信号量被调度运行,最后释放信号量。 -5. ExampleSemTask1执行完,40Tick后任务ExampleSem被唤醒,执行删除信号量。 - -### 示例代码 - -示例代码如下: - -``` -#include "los_sem.h" -#include "securec.h" - -/* 任务ID */ -static UINT32 g_testTaskId01; -static UINT32 g_testTaskId02; - -/* 测试任务优先级 */ -#define TASK_PRIO_TEST 5 - -/* 信号量结构体id */ -static UINT32 g_semId; - -VOID ExampleSemTask1(VOID) -{ - UINT32 ret; - - printf("ExampleSemTask1 try get sem g_semId, timeout 10 ticks.\n"); - - /* 定时阻塞模式申请信号量,定时时间为10ticks */ - ret = LOS_SemPend(g_semId, 10); - - /* 申请到信号量 */ - if (ret == LOS_OK) { - LOS_SemPost(g_semId); - return; - } - /* 定时时间到,未申请到信号量 */ - if (ret == LOS_ERRNO_SEM_TIMEOUT) { - printf("ExampleSemTask1 timeout and try get sem g_semId wait forever.\n"); - - /*永久阻塞模式申请信号量*/ - ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); - printf("ExampleSemTask1 wait_forever and get sem g_semId.\n"); - if (ret == LOS_OK) { - LOS_SemPost(g_semId); - return; - } - } -} - -VOID ExampleSemTask2(VOID) -{ - UINT32 ret; - printf("ExampleSemTask2 try get sem g_semId wait forever.\n"); - - /* 永久阻塞模式申请信号量 */ - ret = LOS_SemPend(g_semId, LOS_WAIT_FOREVER); - - if (ret == LOS_OK) { - printf("ExampleSemTask2 get sem g_semId and then delay 20 ticks.\n"); - } - - /* 任务休眠20 ticks */ - LOS_TaskDelay(20); - - printf("ExampleSemTask2 post sem g_semId.\n"); - /* 释放信号量 */ - LOS_SemPost(g_semId); - return; -} - -UINT32 ExampleSem(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - TSK_INIT_PARAM_S task2; - - /* 创建信号量 */ - LOS_SemCreate(0, &g_semId); - - /* 锁任务调度 */ - LOS_TaskLock(); - - /* 创建任务1 */ - (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask1; - task1.pcName = "TestTask1"; - task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = TASK_PRIO_TEST; - ret = LOS_TaskCreate(&g_testTaskId01, &task1); - if (ret != LOS_OK) { - printf("task1 create failed .\n"); - return LOS_NOK; - } - - /* 创建任务2 */ - (VOID)memset_s(&task2, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - task2.pfnTaskEntry = (TSK_ENTRY_FUNC)ExampleSemTask2; - task2.pcName = "TestTask2"; - task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task2.usTaskPrio = (TASK_PRIO_TEST - 1); - ret = LOS_TaskCreate(&g_testTaskId02, &task2); - if (ret != LOS_OK) { - printf("task2 create failed.\n"); - return LOS_NOK; - } - - /* 解锁任务调度 */ - LOS_TaskUnlock(); - - ret = LOS_SemPost(g_semId); - - /* 任务休眠400 ticks */ - LOS_TaskDelay(400); - - /* 删除信号量 */ - LOS_SemDelete(g_semId); - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -ExampleSemTask2 try get sem g_semId wait forever. -ExampleSemTask2 get sem g_semId and then delay 20 ticks. -ExampleSemTask1 try get sem g_semId, timeout 10 ticks. - -ExampleSemTask1 timeout and try get sem g_semId wait forever. -ExampleSemTask2 post sem g_semId. -ExampleSemTask1 wait_forever and get sem g_semId. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" deleted file mode 100644 index 46c7d87b7cbbfa961feb34f316b94c73475277b3..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-14.md" +++ /dev/null @@ -1,159 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section127752801718) - - [示例代码](#section321653551711) - - [结果验证](#section4366193318167) - - -用户需要了解当前系统运行的时间以及Tick与秒、毫秒之间的转换关系时,需要使用到时间管理模块的接口。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的时间管理提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 时间管理接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

时间转换

-

LOS_MS2Tick

-

毫秒转换成Tick

-

LOS_Tick2MS

-

Tick转化为毫秒

-

OsCpuTick2MS

-

Cycle数目转化为毫秒,使用2个

-

UINT32类型的数值分别表示结果数值的高、低32位。

-

OsCpuTick2US

-

Cycle数目转化为微秒,使用2个

-

UINT32类型的数值分别表示结果数值的高、低32位。

-

时间统计

-

LOS_SysClockGet

-

获取系统时钟

-

LOS_TickCountGet

-

获取自系统启动以来的Tick数

-

LOS_CyclePerTickGet

-

每个Tick多少Cycle数

-
- -## 开发流程 - -时间管理的典型开发流程: - -1. 根据实际需求,完成板级配置适配,并配置系统主时钟频率OS\_SYS\_CLOCK(单位Hz)和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND。OS\_SYS\_CLOCK的默认值基于硬件平台配置。 -2. 调用时钟转换/统计接口。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 时间管理不是单独的功能模块,依赖于OS\_SYS\_CLOCK和LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND两个配置选项。 ->- 系统的Tick数在关中断的情况下不进行计数,故系统Tick数不能作为准确时间使用。 ->- 配置选项维护在开发板工程的文件target\_config.h。 - -## 编程实例 - -### 实例描述 - -在下面的例子中,介绍了时间管理的基本方法,包括: - -1. 时间转换:将毫秒数转换为Tick数,或将Tick数转换为毫秒数。 -2. 时间统计:每Tick的Cycle数、自系统启动以来的Tick数和延迟后的Tick数。 - -### 示例代码 - -前提条件: - -- 使用每秒的Tick数LOSCFG\_BASE\_CORE\_TICK\_PER\_SECOND的默认值100。 -- 配好OS\_SYS\_CLOCK系统主时钟频率。 - -时间转换: - -``` -VOID Example_TransformTime(VOID) -{ - UINT32 ms; - UINT32 tick; - - tick = LOS_MS2Tick(10000); // 10000ms转换为tick - dprintf("tick = %d \n", tick); - ms = LOS_Tick2MS(100); // 100tick转换为ms - dprintf("ms = %d \n", ms); -} -``` - -时间统计和时间延迟: - -``` -VOID Example_GetTime(VOID) -{ - UINT32 cyclePerTick; - UINT64 tickCount; - - cyclePerTick = LOS_CyclePerTickGet(); - if(0 != cyclePerTick) { - dprintf("LOS_CyclePerTickGet = %d \n", cyclePerTick); - } - - tickCount = LOS_TickCountGet(); - if(0 != tickCount) { - dprintf("LOS_TickCountGet = %d \n", (UINT32)tickCount); - } - - LOS_TaskDelay(200); - tickCount = LOS_TickCountGet(); - if(0 != tickCount) { - dprintf("LOS_TickCountGet after delay = %d \n", (UINT32)tickCount); - } -} -``` - -### 结果验证 - -编译运行得到的结果为: - -时间转换: - -``` -tick = 1000 -ms = 1000 -``` - -时间统计和时间延迟: - -``` -LOS_CyclePerTickGet = 495000 -LOS_TickCountGet = 1 -LOS_TickCountGet after delay = 201 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" deleted file mode 100644 index 37753d3a43aad040cae343376b2a57aa48ff7e20..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-16.md" +++ /dev/null @@ -1,218 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section3741753191918) - - [示例代码](#section20760101182016) - - [结果验证](#section11244112818172) - - -## 接口说明 - -OpenHarmony LiteOS-M内核的软件定时器模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 软件定时器接口 - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

创建、删除定时器

-

LOS_SwtmrCreate

-

创建定时器

-

LOS_SwtmrDelete

-

删除定时器

-

启动、停止定时器

-

LOS_SwtmrStart

-

启动定时器

-

LOS_SwtmrStop

-

停止定时器

-

获得软件定时器剩余Tick数

-

LOS_SwtmrTimeGet

-

获得软件定时器剩余Tick数

-
- -## 开发流程 - -软件定时器的典型开发流程: - -1. 配置软件定时器。 - - 确认配置项LOSCFG\_BASE\_CORE\_SWTMR和LOSCFG\_BASE\_IPC\_QUEUE为1打开状态; - - 配置LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数; - - 配置OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度; - -2. 创建定时器LOS\_SwtmrCreate。 - - 创建一个指定计时时长、指定超时处理函数、指定触发模式的软件定时器; - - 返回函数运行结果,成功或失败; - -3. 启动定时器LOS\_SwtmrStart。 -4. 获得软件定时器剩余Tick数LOS\_SwtmrTimeGet。 -5. 停止定时器LOS\_SwtmrStop。 -6. 删除定时器LOS\_SwtmrDelete。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 软件定时器的回调函数中不要做过多操作,不要使用可能引起任务挂起或者阻塞的接口或操作。 ->- 软件定时器使用了系统的一个队列和一个任务资源,软件定时器任务的优先级设定为0,且不允许修改 。 ->- 系统可配置的软件定时器资源个数是指:整个系统可使用的软件定时器资源总个数,而并非是用户可使用的软件定时器资源个数。例如:系统软件定时器多占用一个软件定时器资源数,那么用户能使用的软件定时器资源就会减少一个。 ->- 创建单次软件定时器,该定时器超时执行完回调函数后,系统会自动删除该软件定时器,并回收资源。 ->- 创建单次不自删除属性的定时器,用户需要调用定时器删除接口删除定时器,回收定时器资源,避免资源泄露。 - -## 编程实例 - -### 实例描述 - -在下面的例子中,演示如下功能: - -1. 软件定时器创建、启动、删除、暂停、重启操作。 -2. 单次软件定时器,周期软件定时器使用方法。 - -### 示例代码 - -前提条件: - -- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR配置项打开。 -- 在los\_config.h中,将LOSCFG\_BASE\_CORE\_SWTMR\_ALIGN配置项关闭,示例代码中演示代码不涉及定时器对齐。 -- 配置好LOSCFG\_BASE\_CORE\_SWTMR\_LIMIT最大支持的软件定时器数。 -- 配置好OS\_SWTMR\_HANDLE\_QUEUE\_SIZE软件定时器队列最大长度。 - -代码实现如下: - -``` -#include "los_swtmr.h" - -/* Timer count */ -UINT32 g_timerCount1 = 0; -UINT32 g_timerCount2 = 0; - -/* 任务ID */ -UINT32 g_testTaskId01; - -void Timer1_Callback(UINT32 arg) // 回调函数1 -{ - UINT32 tick_last1; - g_timerCount1++; - tick_last1=(UINT32)LOS_TickCountGet(); // 获取当前Tick数 - printf("g_timerCount1=%d, tick_last1=%d\n", g_timerCount1, tick_last1); -} - -void Timer2_Callback(UINT32 arg) // 回调函数2 -{ - UINT32 tick_last2; - tick_last2=(UINT32)LOS_TickCountGet(); - g_timerCount2++; - printf("g_timerCount2=%d tick_last2=%d\n", g_timerCount2, tick_last2); -} - -void Timer_example(void) -{ - UINT32 id1; // timer id - UINT32 id2; // timer id - UINT32 uwTick; - - /*创建单次软件定时器,Tick数为1000,启动到1000Tick数时执行回调函数1 */ - LOS_SwtmrCreate (1000, LOS_SWTMR_MODE_ONCE, Timer1_Callback, &id1, 1); - - /*创建周期性软件定时器,每100Tick数执行回调函数2 */ - LOS_SwtmrCreate(100, LOS_SWTMR_MODE_PERIOD, Timer2_Callback, &id2, 1); - printf("create Timer1 success\n"); - - LOS_SwtmrStart (id1); //启动单次软件定时器 - printf("start Timer1 sucess\n"); - - LOS_TaskDelay(200); //延时200Tick数 - LOS_SwtmrTimeGet(id1, &uwTick); // 获得单次软件定时器剩余Tick数 - printf("uwTick =%d\n", uwTick); - - LOS_SwtmrStop(id1); // 停止软件定时器 - printf("stop Timer1 sucess\n"); - - LOS_SwtmrStart(id1); - LOS_TaskDelay(1000); - - LOS_SwtmrDelete(id1); // 删除软件定时器 - printf("delete Timer1 sucess\n"); - - LOS_SwtmrStart(id2); // 启动周期性软件定时器 - printf("start Timer2\n"); - - LOS_TaskDelay(1000); - LOS_SwtmrStop(id2); - LOS_SwtmrDelete(id2); -} - -UINT32 Example_TaskEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - - /* 锁任务调度 */ - LOS_TaskLock(); - - /* 创建任务1 */ - memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Timer_example; - task1.pcName = "TimerTsk"; - task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_testTaskId01, &task1); - if (ret != LOS_OK) { - printf("TimerTsk create failed.\n"); - return LOS_NOK; - } - - /* 解锁任务调度 */ - LOS_TaskUnlock(); - - return LOS_OK; -} -``` - -### 结果验证 - -编译烧录运行,输出结果如下: - -``` -create Timer1 success -start Timer1 sucess -uwTick =798 -stop Timer1 sucess -g_timerCount1=1, tick_last1=1208 -delete Timer1 sucess -start Timer2 -g_timerCount2=1 tick_last2=1313 -g_timerCount2=2 tick_last2=1413 -g_timerCount2=3 tick_last2=1513 -g_timerCount2=4 tick_last2=1613 -g_timerCount2=5 tick_last2=1713 -g_timerCount2=6 tick_last2=1813 -g_timerCount2=7 tick_last2=1913 -g_timerCount2=8 tick_last2=2013 -g_timerCount2=9 tick_last2=2113 -g_timerCount2=10 tick_last2=2213 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" deleted file mode 100644 index ee4e2944bc774a1dd9cc59822734b6de9a1c723b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" +++ /dev/null @@ -1,306 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [结果验证](#section189023104457) - - -任务创建后,内核可以执行锁任务调度,解锁任务调度,挂起,恢复,延时等操作,同时也可以设置任务优先级,获取任务优先级。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的任务管理模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 任务管理模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

创建和删除任务

-

LOS_TaskCreateOnly

-

创建任务,并使该任务进入suspend状态,不对该任务进行调度。如果需要调度,可以调用LOS_TaskResume使该任务进入ready状态。

-

LOS_TaskCreate

-

创建任务,并使该任务进入ready状态,如果就绪队列中没有更高优先级的任务,则运行该任务。

-

LOS_TaskDelete

-

删除指定的任务。

-

控制任务状态

-

LOS_TaskResume

-

恢复挂起的任务,使该任务进入ready状态。

-

LOS_TaskSuspend

-

挂起指定的任务,然后切换任务

-

LOS_TaskDelay

-

任务延时等待,释放CPU,等待时间到期后该任务会重新进入ready状态。传入参数为Tick数目。

-

LOS_Msleep

-

传入参数为毫秒数,转换为Tick数目,调用LOS_TaskDelay。

-

LOS_TaskYield

-

当前任务时间片设置为0,释放CPU,触发调度运行就绪任务队列中优先级最高的任务。

-

控制任务调度

-

LOS_TaskLock

-

锁任务调度,但任务仍可被中断打断。

-

LOS_TaskUnlock

-

解锁任务调度。

-

LOS_Schedule

-

触发任务调度。

-

控制任务优先级

-

LOS_CurTaskPriSet

-

设置当前任务的优先级。

-

LOS_TaskPriSet

-

设置指定任务的优先级。

-

LOS_TaskPriGet

-

获取指定任务的优先级。

-

获取任务信息

-

LOS_CurTaskIDGet

-

获取当前任务的ID。

-

LOS_NextTaskIDGet

-

获取任务就绪队列中优先级最高的任务的ID。

-

LOS_NewTaskIDGet

-

等同LOS_NextTaskIDGet。

-

LOS_CurTaskNameGet

-

获取当前任务的名称。

-

LOS_TaskNameGet

-

获取指定任务的名称。

-

LOS_TaskStatusGet

-

获取指定任务的状态。

-

LOS_TaskInfoGet

-

获取指定任务的信息,包括任务状态、优先级、任务栈大小、栈顶指针SP、任务入口函数、已使用的任务栈大小等。

-

LOS_TaskIsRunning

-

获取任务模块是否已经开始调度运行。

-

任务信息维测

-

LOS_TaskSwitchInfoGet

-

获取任务切换信息,需要开启宏LOSCFG_BASE_CORE_EXC_TSK_SWITCH。

-
- -## 开发流程 - -以创建任务为例,讲解开发流程。 - -1. 锁任务调度LOS\_TaskLock,防止高优先级任务调度。 -2. 创建任务LOS\_TaskCreate。 -3. 解锁任务LOS\_TaskUnlock,让任务按照优先级进行调度。 -4. 延时任务LOS\_TaskDelay,任务延时等待。 -5. 挂起指定的任务LOS\_TaskSuspend,任务挂起等待恢复操作。 -6. 恢复挂起的任务LOS\_TaskResume。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 执行Idle任务时,会对待回收链表中的任务控制块和任务栈进行回收。 ->- 任务名是指针,并没有分配空间,在设置任务名时,禁止将局部变量的地址赋值给任务名指针。 ->- 任务栈的大小按8字节大小对齐。确定任务栈大小的原则是,够用就行,多了浪费,少了任务栈溢出。 ->- 挂起当前任务时,如果已经锁任务调度,则无法挂起。 ->- Idle任务及软件定时器任务不能被挂起或者删除。 ->- 在中断处理函数中或者在锁任务的情况下,执行LOS\_TaskDelay会失败。 ->- 锁任务调度,并不关中断,因此任务仍可被中断打断。 ->- 锁任务调度必须和解锁任务调度配合使用。 ->- 设置任务优先级时可能会发生任务调度。 ->- 可配置的系统最大任务数是指:整个系统的任务总个数,而非用户能使用的任务个数。例如:系统软件定时器多占用一个任务资源,那么用户能使用的任务资源就会减少一个。 ->- LOS\_CurTaskPriSet和LOS\_TaskPriSet接口不能在中断中使用,也不能用于修改软件定时器任务的优先级。 ->- LOS\_TaskPriGet接口传入的task ID对应的任务未创建或者超过最大任务数,统一返回-1。 ->- 在删除任务时要保证任务申请的资源(如互斥锁、信号量等)已被释放。 - -## 编程实例 - -本实例介绍基本的任务操作方法,包含2个不同优先级任务的创建、任务延时、任务锁与解锁调度、挂起和恢复等操作,阐述任务优先级调度的机制以及各接口的应用。示例代码如下: - -``` -UINT32 g_taskHiId; -UINT32 g_taskLoId; -#define TSK_PRIOR_HI 4 -#define TSK_PRIOR_LO 5 - -UINT32 Example_TaskHi(VOID) -{ - UINT32 ret; - - printf("Enter TaskHi Handler.\n"); - - /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务(TaskLo任务) */ - ret = LOS_TaskDelay(100); - if (ret != LOS_OK) { - printf("Delay TaskHi Failed.\n"); - return LOS_NOK; - } - - /* 100个Ticks时间到了后,该任务恢复,继续执行 */ - printf("TaskHi LOS_TaskDelay Done.\n"); - - /* 挂起自身任务 */ - ret = LOS_TaskSuspend(g_taskHiId); - if (ret != LOS_OK) { - printf("Suspend TaskHi Failed.\n"); - return LOS_NOK; - } - printf("TaskHi LOS_TaskResume Success.\n"); - return ret; -} - -/* 低优先级任务入口函数 */ -UINT32 Example_TaskLo(VOID) -{ - UINT32 ret; - - printf("Enter TaskLo Handler.\n"); - - /* 延时100个Ticks,延时后该任务会挂起,执行剩余任务中最高优先级的任务 */ - ret = LOS_TaskDelay(100); - if (ret != LOS_OK) { - printf("Delay TaskLo Failed.\n"); - return LOS_NOK; - } - - printf("TaskHi LOS_TaskSuspend Success.\n"); - - /* 恢复被挂起的任务g_taskHiId */ - ret = LOS_TaskResume(g_taskHiId); - if (ret != LOS_OK) { - printf("Resume TaskHi Failed.\n"); - return LOS_NOK; - } - return ret; -} - -/* 任务测试入口函数,创建两个不同优先级的任务 */ -UINT32 Example_TskCaseEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S initParam; - - /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ - LOS_TaskLock(); - - printf("LOS_TaskLock() Success!\n"); - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskHi; - initParam.usTaskPrio = TSK_PRIOR_HI; - initParam.pcName = "TaskHi"; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - - /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ - ret = LOS_TaskCreate(&g_taskHiId, &initParam); - if (ret != LOS_OK) { - LOS_TaskUnlock(); - - printf("Example_TaskHi create Failed!\n"); - return LOS_NOK; - } - - printf("Example_TaskHi create Success!\n"); - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_TaskLo; - initParam.usTaskPrio = TSK_PRIOR_LO; - initParam.pcName = "TaskLo"; - initParam.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - - /* 创建低优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ - ret = LOS_TaskCreate(&g_taskLoId, &initParam); - if (ret != LOS_OK) { - LOS_TaskUnlock(); - printf("Example_TaskLo create Failed!\n"); - return LOS_NOK; - } - - printf("Example_TaskLo create Success!\n"); - - /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ - LOS_TaskUnlock(); - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -LOS_TaskLock() Success! -Example_TaskHi create Success! -Example_TaskLo create Success! -Enter TaskHi Handler. -Enter TaskLo Handler. -TaskHi LOS_TaskDelay Done. -TaskHi LOS_TaskSuspend Success. -TaskHi LOS_TaskResume Success. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" deleted file mode 100644 index 6869a792fd853689071ea77ccce8691aa24b9c8e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-6.md" +++ /dev/null @@ -1,194 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section460018317164) - - [实例描述](#section896412438910) - - [示例代码](#section149077554912) - - [结果验证](#section4461439172017) - - -## 接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

事件检测

-

LOS_EventPoll

-

根据eventID,eventMask(事件掩码),mode(事件读取模式),检查用户期待的事件是否发生。

-
须知:

当mode含LOS_WAITMODE_CLR,且用户期待的事件发生时,此时eventID中满足要求的事件会被清零,这种情况下eventID既是入参也是出参。其他情况eventID只作为入参。

-
-

初始化

-

LOS_EventInit

-

事件控制块初始化。

-

事件读

-

LOS_EventRead

-

读事件(等待事件),任务会根据timeOut(单位:tick)进行阻塞等待;

-

未读取到事件时,返回值为0;

-

正常读取到事件时,返回正值(事件发生的集合);

-

其他情况返回特定错误码。

-

事件写

-

LOS_EventWrite

-

写一个特定的事件到事件控制块。

-

事件清除

-

LOS_EventClear

-

根据events掩码,清除事件控制块中的事件。

-

事件销毁

-

LOS_EventDestroy

-

事件控制块销毁。

-
- -## 开发流程 - -事件的典型开发流程: - -1. 初始化事件控制块 -2. 阻塞读事件控制块 -3. 写入相关事件 -4. 阻塞任务被唤醒,读取事件并检查是否满足要求 -5. 处理事件控制块 -6. 事件控制块销毁 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 进行事件读写操作时,事件的第25位为保留位,不可以进行位设置。 ->- 对同一事件反复写入,算作一次写入。 - -## 编程实例 - -### 实例描述 - -示例中,任务Example\_TaskEntry创建一个任务Example\_Event,Example\_Event读事件阻塞,Example\_TaskEntry向该任务写事件。可以通过示例日志中打印的先后顺序理解事件操作时伴随的任务切换。 - -1. 在任务Example\_TaskEntry创建任务Example\_Event,其中任务Example\_Event优先级高于Example\_TaskEntry。 -2. 在任务Example\_Event中读事件0x00000001,阻塞,发生任务切换,执行任务Example\_TaskEntry。 -3. 在任务Example\_TaskEntry向任务Example\_Event写事件0x00000001,发生任务切换,执行任务Example\_Event。 -4. Example\_Event得以执行,直到任务结束。 -5. Example\_TaskEntry得以执行,直到任务结束。 - -### 示例代码 - -示例代码如下: - -``` -#include "los_event.h" -#include "los_task.h" -#include "securec.h" - -/* 任务ID */ -UINT32 g_testTaskId; - -/* 事件控制结构体 */ -EVENT_CB_S g_exampleEvent; - -/* 等待的事件类型 */ -#define EVENT_WAIT 0x00000001 - -/* 用例任务入口函数 */ -VOID Example_Event(VOID) -{ - UINT32 ret; - UINT32 event; - - /* 超时等待方式读事件,超时时间为100 ticks, 若100 ticks后未读取到指定事件,读事件超时,任务直接唤醒 */ - printf("Example_Event wait event 0x%x \n", EVENT_WAIT); - - event = LOS_EventRead(&g_exampleEvent, EVENT_WAIT, LOS_WAITMODE_AND, 100); - if (event == EVENT_WAIT) { - printf("Example_Event,read event :0x%x\n", event); - } else { - printf("Example_Event,read event timeout\n"); - } -} - -UINT32 Example_TaskEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - - /* 事件初始化 */ - ret = LOS_EventInit(&g_exampleEvent); - if (ret != LOS_OK) { - printf("init event failed .\n"); - return -1; - } - - /* 创建任务 */ - (VOID)memset_s(&task1, sizeof(TSK_INIT_PARAM_S), 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Event; - task1.pcName = "EventTsk1"; - task1.uwStackSize = OS_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_testTaskId, &task1); - if (ret != LOS_OK) { - printf("task create failed.\n"); - return LOS_NOK; - } - - /* 写g_testTaskId 等待事件 */ - printf("Example_TaskEntry write event.\n"); - - ret = LOS_EventWrite(&g_exampleEvent, EVENT_WAIT); - if (ret != LOS_OK) { - printf("event write failed.\n"); - return LOS_NOK; - } - - /* 清标志位 */ - printf("EventMask:%d\n", g_exampleEvent.uwEventID); - LOS_EventClear(&g_exampleEvent, ~g_exampleEvent.uwEventID); - printf("EventMask:%d\n", g_exampleEvent.uwEventID); - - /* 删除任务 */ - ret = LOS_TaskDelete(g_testTaskId); - if (ret != LOS_OK) { - printf("task delete failed.\n"); - return LOS_NOK; - } - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Example_Event wait event 0x1 -Example_TaskEntry write event. -Example_Event,read event :0x1 -EventMask:1 -EventMask:0 -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" deleted file mode 100644 index a194bc9e585299c70eae4256ca0e0877f4e226c5..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274-8.md" +++ /dev/null @@ -1,205 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section783435801510) -- [编程实例](#section1426719434114) - - [实例描述](#section896412438910) - - [示例代码](#section149077554912) - - [结果验证](#section2059413981311) - - -## 接口说明 - -**表 1** 互斥锁模块接口 - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

互斥锁的创建和删除

-

LOS_MuxCreate

-

创建互斥锁

-

LOS_MuxDelete

-

删除指定的互斥锁

-

互斥锁的申请和释放

-

LOS_MuxPend

-

申请指定的互斥锁

-

LOS_MuxPost

-

释放指定的互斥锁

-
- -## 开发流程 - -互斥锁典型场景的开发流程: - -1. 创建互斥锁LOS\_MuxCreate。 -2. 申请互斥锁LOS\_MuxPend。 - - 申请模式有三种:无阻塞模式、永久阻塞模式、定时阻塞模式。 - - - 无阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有任务持有,或者持有该互斥锁的任务和申请该互斥锁的任务为同一个任务,则申请成功。 - - 永久阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则,该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,直到有其他任务释放该互斥锁,阻塞任务才会重新得以执行。 - - 定时阻塞模式:任务需要申请互斥锁,若该互斥锁当前没有被占用,则申请成功。否则该任务进入阻塞态,系统切换到就绪任务中优先级高者继续执行。任务进入阻塞态后,指定时间超时前有其他任务释放该互斥锁,或者用户指定时间超时后,阻塞任务才会重新得以执行。 - -3. 释放互斥锁LOS\_MuxPost。 - - 如果有任务阻塞于指定互斥锁,则唤醒被阻塞任务中优先级高的,该任务进入就绪态,并进行任务调度; - - 如果没有任务阻塞于指定互斥锁,则互斥锁释放成功。 - -4. 删除互斥锁LOS\_MuxDelete。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 两个任务不能对同一把互斥锁加锁。如果某任务对已被持有的互斥锁加锁,则该任务会被挂起,直到持有该锁的任务对互斥锁解锁,才能执行对这把互斥锁的加锁操作。 ->- 互斥锁不能在中断服务程序中使用。 ->- LiteOS-M内核作为实时操作系统需要保证任务调度的实时性,尽量避免任务的长时间阻塞,因此在获得互斥锁之后,应该尽快释放互斥锁。 ->- 持有互斥锁的过程中,不得再调用LOS\_TaskPriSet等接口更改持有互斥锁任务的优先级。 - -## 编程实例 - -### 实例描述 - -本实例实现如下流程。 - -1. 任务Example\_TaskEntry创建一个互斥锁,锁任务调度,创建两个任务Example\_MutexTask1、Example\_MutexTask2。Example\_MutexTask2优先级高于Example\_MutexTask1,解锁任务调度。 -2. Example\_MutexTask2被调度,以永久阻塞模式申请互斥锁,并成功获取到该互斥锁,然后任务休眠100Tick,Example\_MutexTask2挂起,Example\_MutexTask1被唤醒。 -3. Example\_MutexTask1以定时阻塞模式申请互斥锁,等待时间为10Tick,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。10Tick超时时间到达后,Example\_MutexTask1被唤醒,以永久阻塞模式申请互斥锁,因互斥锁仍被Example\_MutexTask2持有,Example\_MutexTask1挂起。 -4. 100Tick休眠时间到达后,Example\_MutexTask2被唤醒, 释放互斥锁,唤醒Example\_MutexTask1。Example\_MutexTask1成功获取到互斥锁后,释放,删除互斥锁。 - -### 示例代码 - -示例代码如下: - -``` -#include -#include "los_mux.h" - -/* 互斥锁句柄id */ -UINT32 g_testMux; -/* 任务ID */ -UINT32 g_testTaskId01; -UINT32 g_testTaskId02; - -VOID Example_MutexTask1(VOID) -{ - UINT32 ret; - - printf("task1 try to get mutex, wait 10 ticks.\n"); - /* 申请互斥锁 */ - ret = LOS_MuxPend(g_testMux, 10); - - if (ret == LOS_OK) { - printf("task1 get mutex g_testMux.\n"); - /* 释放互斥锁 */ - LOS_MuxPost(g_testMux); - return; - } - if (ret == LOS_ERRNO_MUX_TIMEOUT ) { - printf("task1 timeout and try to get mutex, wait forever.\n"); - /* 申请互斥锁 */ - ret = LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); - if (ret == LOS_OK) { - printf("task1 wait forever, get mutex g_testMux.\n"); - /* 释放互斥锁 */ - LOS_MuxPost(g_testMux); - /* 删除互斥锁 */ - LOS_MuxDelete(g_testMux); - printf("task1 post and delete mutex g_testMux.\n"); - return; - } - } - return; -} - -VOID Example_MutexTask2(VOID) -{ - printf("task2 try to get mutex, wait forever.\n"); - /* 申请互斥锁 */ - (VOID)LOS_MuxPend(g_testMux, LOS_WAIT_FOREVER); - - printf("task2 get mutex g_testMux and suspend 100 ticks.\n"); - - /* 任务休眠100Ticks */ - LOS_TaskDelay(100); - - printf("task2 resumed and post the g_testMux\n"); - /* 释放互斥锁 */ - LOS_MuxPost(g_testMux); - return; -} - -UINT32 Example_TaskEntry(VOID) -{ - UINT32 ret; - TSK_INIT_PARAM_S task1; - TSK_INIT_PARAM_S task2; - - /* 创建互斥锁 */ - LOS_MuxCreate(&g_testMux); - - /* 锁任务调度 */ - LOS_TaskLock(); - - /* 创建任务1 */ - memset(&task1, 0, sizeof(TSK_INIT_PARAM_S)); - task1.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask1; - task1.pcName = "MutexTsk1"; - task1.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task1.usTaskPrio = 5; - ret = LOS_TaskCreate(&g_testTaskId01, &task1); - if (ret != LOS_OK) { - printf("task1 create failed.\n"); - return LOS_NOK; - } - - /* 创建任务2 */ - memset(&task2, 0, sizeof(TSK_INIT_PARAM_S)); - task2.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_MutexTask2; - task2.pcName = "MutexTsk2"; - task2.uwStackSize = LOSCFG_BASE_CORE_TSK_DEFAULT_STACK_SIZE; - task2.usTaskPrio = 4; - ret = LOS_TaskCreate(&g_testTaskId02, &task2); - if (ret != LOS_OK) { - printf("task2 create failed.\n"); - return LOS_NOK; - } - - /* 解锁任务调度 */ - LOS_TaskUnlock(); - - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -task2 try to get mutex, wait forever. -task2 get mutex g_testMux and suspend 100 ticks. -task1 try to get mutex, wait 10 ticks. -task1 timeout and try to get mutex, wait forever. -task2 resumed and post the g_testMux -task1 wait forever, get mutex g_testMux. -task1 post and delete mutex g_testMux. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100644 index c97dfdd3f24126cbb537d98f53e59a4786fdbc13..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,130 +0,0 @@ -# 开发指导 - -- [接口说明](#section158501652121514) -- [开发流程](#section11841123033618) -- [编程实例](#section460018317164) - - [结果验证](#section1048572415182) - - -当产生中断请求时,CPU暂停当前的任务,转而去响应外设请求。用户可以根据需要注册对应的中断处理程序,指定CPU响应中断请求时所执行的具体操作。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的中断模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 中断模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

创建、删除中断

-

HalHwiCreate

-

中断创建,注册中断号、中断触发模式、中断优先级、中断处理程序。中断被触发时,会调用该中断处理程序。

-

HalHwiDelete

-

根据指定的中断号,删除中断。

-

打开、关闭中断

-

LOS_IntUnLock

-

开中断,使能当前处理器所有中断响应。

-

LOS_IntLock

-

关中断,关闭当前处理器所有中断响应。

-

LOS_IntRestore

-

恢复到使用LOS_IntLock、LOS_IntUnLock操作之前的中断状态。

-
- -## 开发流程 - -1. 调用中断创建接口HalHwiCreate创建中断。 -2. 调用TestHwiTrigger接口触发指定中断(该接口在测试套中定义,通过写中断控制器的相关寄存器模拟外部中断,一般的外设设备,不需要执行这一步)。 -3. 调用HalHwiDelete接口删除指定中断,此接口根据实际情况使用,判断是否需要删除中断。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 根据具体硬件,配置支持的最大中断数及可设置的中断优先级个数。 ->- 中断处理程序耗时不能过长,否则会影响CPU对中断的及时响应。 ->- 中断响应过程中不能直接、间接执行引起调度的LOS\_Schedule等函数。 ->- 中断恢复LOS\_IntRestore\(\)的入参必须是与之对应的LOS\_IntLock\(\)的返回值(即关中断之前的CPSR值)。Cortex-M系列处理器中0-15中断为内部使用,因此不建议用户去申请和创建。 - -## 编程实例 - -本实例实现如下功能: - -1. 创建中断。 -2. 触发中断。 -3. 删除中断。 - -代码实现如下,演示如何创建中断和删除中断,当指定的中断号HWI\_NUM\_TEST产生中断时,会调用中断处理函数: - -``` -#include "los_interrupt.h" - -/*创建中断*/ -#define HWI_NUM_TEST 7 - -STATIC VOID HwiUsrIrq(VOID) -{ - printf("in the func HwiUsrIrq \n"); -} - -static UINT32 Example_Interrupt(VOID) -{ - UINT32 ret; - HWI_PRIOR_T hwiPrio = 3; - HWI_MODE_T mode = 0; - HWI_ARG_T arg = 0; - - /*创建中断*/ - ret = HalHwiCreate(HWI_NUM_TEST, hwiPrio, mode, (HWI_PROC_FUNC)HwiUsrIrq, arg); - if(ret == LOS_OK){ - printf("Hwi create success!\n"); - } else { - printf("Hwi create failed!\n"); - return LOS_NOK; - } - - /* 延时50个Ticks, 当有硬件中断发生时,会调用函数HwiUsrIrq*/ - LOS_TaskDelay(50); - - /*删除中断*/ - ret = HalHwiDelete(HWI_NUM_TEST); - if(ret == LOS_OK){ - printf("Hwi delete success!\n"); - } else { - printf("Hwi delete failed!\n"); - return LOS_NOK; - } - return LOS_OK; -} -``` - -### 结果验证 - -编译运行得到的结果为: - -``` -Hwi create success! -Hwi delete success!. -``` - diff --git "a/zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" deleted file mode 100644 index 8e9a050102de2a7721f962338b3d4420498c3d4b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\274\202\345\270\270\350\260\203\346\265\213.md" +++ /dev/null @@ -1,329 +0,0 @@ -# 异常调测 - -- [基本概念](#section2741911123412) -- [运行机制](#section16618124317346) -- [接口说明](#section16111931351) -- [使用指导](#section16317163520350) - - [开发流程](#section13457839133618) - - [定位流程](#section197332323815) - - -## 基本概念 - -OpenHarmony LiteOS-M提供异常接管调测手段,帮助开发者定位分析问题。异常接管是操作系统对运行期间发生的异常情况进行处理的一系列动作,例如打印异常发生时异常类型、发生异常时的系统状态、当前函数的调用栈信息、CPU现场信息、任务调用堆栈等信息。 - -## 运行机制 - -栈帧用于保存函数调用过程中的函数参数、变量、返回值等信息。调用函数时,会创建子函数的栈帧,同时将函数入参、局部变量、寄存器入栈。栈帧从高地址向低地址生长。以ARM32 CPU架构为例,每个栈帧中都会保存PC、LR、SP和FP寄存器的历史值。LR链接寄存器(Link Register)指向函数的返回地址,FP帧指针寄存器(Frame Point)指向当前函数的父函数的栈帧起始地址。利用FP寄存器可以得到父函数的栈帧,从栈帧中获取父函数的FP,就可以得到祖父函数的栈帧,以此类推,可以追溯程序调用栈,得到函数间的调用关系。 - -当系统发生异常时,系统打印异常函数的栈帧中保存的寄存器内容,以及父函数、祖父函数的栈帧中的LR链接寄存器、FP帧指针寄存器内容,用户就可以据此追溯函数间的调用关系,定位异常原因。 - -堆栈分析原理如下图所示,实际堆栈信息根据不同CPU架构有所差异,此处仅做示意。 - -**图 1** 堆栈分析原理示意图 -![](figures/堆栈分析原理示意图.png "堆栈分析原理示意图") - -图中不同颜色的寄存器表示不同的函数。可以看到函数调用过程中,寄存器的保存。通过FP寄存器,栈回溯到异常函数的父函数,继续按照规律对栈进行解析,推出函数调用关系,方便用户定位问题。 - -## 接口说明 - -OpenHarmony LiteOS-M内核的回溯栈模块提供下面几种功能,接口详细信息可以查看API参考。 - -**表 1** 回溯栈模块接口 - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

回溯栈接口

-

LOS_BackTrace

-

打印调用处的函数调用栈关系。

-

LOS_RecordLR

-

在无法打印的场景,用该接口获取调用处的函数调用栈关系。

-
- -## 使用指导 - -### 开发流程 - -开启异常调测的典型流程如下: - -1. 配置异常接管相关宏。 - - 需要在target\_config.h头文件中修改配置: - - - - - - - - - - - - - - - - -

配置项

-

含义

-

设置值

-

LOSCFG_BACKTRACE_DEPTH

-

函数调用栈深度,默认15层

-

15

-

LOSCFG_BACKTRACE_TYPE

-

回溯栈类型:

-

0:表示关闭该功能;

-

1:表示支持Cortex-m系列硬件的函数调用栈解析;

-

2:表示用于Risc-v系列硬件的函数调用栈解析;

-

根据工具链类型设置1或2

-
- - -1. 使用示例中有问题的代码,编译、运行工程,在串口终端中查看异常信息输出。示例代码模拟异常代码,实际产品开发时使用异常调测机制定位异常问题。 - - 本示例演示异常输出,包含1个任务,该任务入口函数模拟若干函数调用,最终调用一个模拟异常的函数。代码实现如下: - - ``` - #include - #include "los_config.h" - #include "los_interrupt.h" - #include "los_task.h" - - UINT32 g_taskExcId; - #define TSK_PRIOR 4 - - /* 模拟异常函数 */ - - UINT32 Get_Result_Exception_0(UINT16 dividend){ - UINT32 divisor = 0; - UINT32 result = dividend / divisor; - return result; - } - - UINT32 Get_Result_Exception_1(UINT16 dividend){ - return Get_Result_Exception_0(dividend); - } - - UINT32 Get_Result_Exception_2(UINT16 dividend){ - return Get_Result_Exception_1(dividend); - } - - UINT32 Example_Exc(VOID) - { - UINT32 ret; - - printf("Enter Example_Exc Handler.\r\n"); - - /* 模拟函数调用 */ - ret = Get_Result_Exception_2(TSK_PRIOR); - printf("Divided result =%u.\r\n", ret); - - printf("Exit Example_Exc Handler.\r\n"); - return ret; - } - - - /* 任务测试入口函数,创建一个会发生异常的任务 */ - UINT32 Example_Exc_Entry(VOID) - { - UINT32 ret; - TSK_INIT_PARAM_S initParam; - - /* 锁任务调度,防止新创建的任务比本任务高而发生调度 */ - LOS_TaskLock(); - - printf("LOS_TaskLock() Success!\r\n"); - - initParam.pfnTaskEntry = (TSK_ENTRY_FUNC)Example_Exc; - initParam.usTaskPrio = TSK_PRIOR; - initParam.pcName = "Example_Exc"; - initParam.uwStackSize = LOSCFG_SECURE_STACK_DEFAULT_SIZE; - /* 创建高优先级任务,由于锁任务调度,任务创建成功后不会马上执行 */ - ret = LOS_TaskCreate(&g_taskExcId, &initParam); - if (ret != LOS_OK) { - LOS_TaskUnlock(); - - printf("Example_Exc create Failed!\r\n"); - return LOS_NOK; - } - - printf("Example_Exc create Success!\r\n"); - - /* 解锁任务调度,此时会发生任务调度,执行就绪队列中最高优先级任务 */ - LOS_TaskUnlock(); - - return LOS_OK; - } - ``` - - -1. 上述代码串口终端输出异常信息如下: - - ``` - entering kernel init... - LOS_TaskLock() Success! - Example_Exc create Success! - Entering scheduler - Enter Example_Exc Handler. - *************Exception Information************** - Type = 10 - ThrdPid = 4 - Phase = exc in task - FaultAddr = 0xabababab - Current task info: - Task name = Example_Exc - Task ID = 4 - Task SP = 0x200051ac - Task ST = 0x20004ff0 - Task SS = 0x200 - Exception reg dump: - PC = 0x80037da - LR = 0x80037fe - SP = 0x20005190 - R0 = 0x4 - R1 = 0x40 - R2 = 0x4 - R3 = 0x0 - R4 = 0x4040404 - R5 = 0x5050505 - R6 = 0x6060606 - R7 = 0x20005190 - R8 = 0x8080808 - R9 = 0x9090909 - R10 = 0x10101010 - R11 = 0x11111111 - R12 = 0x12121212 - PriMask = 0x0 - xPSR = 0x41000000 - ----- backtrace start ----- - backtrace 0 -- lr = 0x800381a - backtrace 1 -- lr = 0x8003836 - backtrace 2 -- lr = 0x8005a4e - backtrace 3 -- lr = 0x8000494 - backtrace 4 -- lr = 0x8008620 - backtrace 5 -- lr = 0x800282c - backtrace 6 -- lr = 0x80008a0 - backtrace 7 -- lr = 0x80099f8 - backtrace 8 -- lr = 0x800a01a - backtrace 9 -- lr = 0x800282c - backtrace 10 -- lr = 0x80008a0 - backtrace 11 -- lr = 0x80099f8 - backtrace 12 -- lr = 0x8009bf0 - backtrace 13 -- lr = 0x8009c52 - backtrace 14 -- lr = 0x80099aa - ----- backtrace end ----- - - TID Priority Status StackSize WaterLine StackPoint TopOfStack EventMask SemID name - --- -------- -------- --------- ---------- ---------- ---------- --------- ----- ---- - 0 0 Pend 0x2d0 0x104 0x200029bc 0x200027f0 0x0 0xffff Swt_Task - 1 31 Ready 0x500 0x44 0x20002f84 0x20002ac8 0x0 0xffff IdleCore000 - 2 6 Ready 0x1000 0x44 0x20003f94 0x20002fd8 0x0 0xffff TaskSampleEntry1 - 3 7 Ready 0x1000 0x44 0x20004f9c 0x20003fe0 0x0 0xffff TaskSampleEntry2 - 4 4 Running 0x200 0xec 0x200051ac 0x20004ff0 0x0 0xffff Example_Exc - - OS exception NVIC dump: - interrupt enable register, base address: 0xe000e100, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt pending register, base address: 0xe000e200, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt active register, base address: 0xe000e300, size: 0x20 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt priority register, base address: 0xe000e400, size: 0xf0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 - interrupt exception register, base address: 0xe000ed18, size: 0xc - 0x0 0x0 0xf0f00000 - interrupt shcsr register, base address: 0xe000ed24, size: 0x4 - 0x70008 - interrupt control register, base address: 0xe000ed04, size: 0x4 - 0x400f806 - - memory pools check: - system heap memcheck over, all passed! - memory pool check end! - ``` - - -### 定位流程 - -异常接管一般的定位步骤如下: - -1. 打开编译后生成的镜像反汇编(asm)文件。如果默认没有生成,可以使用objdump工具生成,命令为: - - ``` - arm-none-eabi-objdump -S -l XXX.elf - ``` - - -1. 搜索PC指针(指向当前正在执行的指令)在asm中的位置,找到发生异常的函数。 - - PC地址指向发生异常时程序正在执行的指令。在当前执行的二进制文件对应的asm文件中,查找PC值0x80037da,找到当前CPU正在执行的指令行,反汇编如下所示: - - ``` - UINT32 Get_Result_Exception_0(UINT16 dividend){ - 80037c8: b480 push {r7} - 80037ca: b085 sub sp, #20 - 80037cc: af00 add r7, sp, #0 - 80037ce: 4603 mov r3, r0 - 80037d0: 80fb strh r3, [r7, #6] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:10 - UINT32 divisor = 0; - 80037d2: 2300 movs r3, #0 - 80037d4: 60fb str r3, [r7, #12] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:11 - UINT32 result = dividend / divisor; - 80037d6: 88fa ldrh r2, [r7, #6] - 80037d8: 68fb ldr r3, [r7, #12] - 80037da: fbb2 f3f3 udiv r3, r2, r3 - 80037de: 60bb str r3, [r7, #8] - ``` - - -1. 可以看到: - 1. 异常时CPU正在执行的指令是udiv r3, r2, r3,其中r3取值为0,导致发生除零异常。 - 2. 异常发生在函数Get\_Result\_Exception\_0中。 - -2. 根据LR值查找异常函数的父函数。 - - 包含LR值0x80037fe的反汇编如下所示: - - ``` - 080037ec : - Get_Result_Exception_1(): - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:15 - UINT32 Get_Result_Exception_1(UINT16 dividend){ - 80037ec: b580 push {r7, lr} - 80037ee: b082 sub sp, #8 - 80037f0: af00 add r7, sp, #0 - 80037f2: 4603 mov r3, r0 - 80037f4: 80fb strh r3, [r7, #6] - kernel_liteos_m\targets\cortex-m7_nucleo_f767zi_gcc/Core/Src/exc_example.c:16 - return Get_Result_Exception_0(dividend); - 80037f6: 88fb ldrh r3, [r7, #6] - 80037f8: 4618 mov r0, r3 - 80037fa: f7ff ffe5 bl 80037c8 - 80037fe: 4603 mov r3, r0 - ``` - - -1. LR值80037fe上一行是bl 80037c8 ,此处调用了异常函数,调用异常函数的父函数为Get\_Result\_Exception\_1\(\)。 -2. 重复步骤3,解析异常信息中backtrace start至backtrace end之间的LR值,得到调用产生异常的函数调用栈关系,找到异常原因。 - diff --git "a/zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" "b/zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" deleted file mode 100644 index 53ddc75318ff70d0ffed93acc947c9c1eccd6723..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\345\277\253\351\200\237\345\205\245\351\227\250.md" +++ /dev/null @@ -1,47 +0,0 @@ -# 快速入门 - -- [搭建开发环境](#section157851447151716) -- [获取OpenHarmony源码](#section381985201816) -- [获取示例工程源码](#section204717216181) -- [编译运行](#section9772514181917) - -OpenHarmony LiteOS-M内核的编译构建系统是一个基于gn和ninja的组件化构建系统,支持按组件配置、裁剪和拼装,按需构建出定制化的产品。编译构建系统的详细信息可以参考[编译构建概述](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA%E6%A6%82%E8%BF%B0.md)。本文主要介绍如何基于gn和ninja编译LiteOS-M工程。 - -## 搭建开发环境 - -在搭建各个开发板环境前,需要完成OpenHarmony系统基础环境搭建。系统基础环境主要是指OpenHarmony的编译环境和开发环境,详细介绍请参考官方站点[搭建系统基础环境](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/quick-start/%E6%90%AD%E5%BB%BA%E7%B3%BB%E7%BB%9F%E7%8E%AF%E5%A2%83.md)。开发者需要根据环境搭建文档,完成下述软件的安装:Python3.7+、gn、ninja、hb。对于LiteOS-M内核,还需要安装ARM GCC编译工具链。 - -## 获取OpenHarmony源码 - -开发者需要在Linux服务器上通过Git克隆获取OpenHarmony最新源码,详细的源码获取方式,请见[源码获取](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/get-code/%E6%BA%90%E7%A0%81%E8%8E%B7%E5%8F%96.md)。获取OpenHarmony完整仓代码后,假设克隆目录为\~/openHarmony。 - -## 获取示例工程源码 - -以开发板Nucleo-F767Zi为例,演示如何编译运行OpenHarmony LiteOS-M内核工程。在本地目录,执行下述命令克隆示例代码。 - -``` -git clone https://gitee.com/harylee/nucleo_f767zi.git -``` - -假设克隆到的代码目录为\~/nucleo\_f767zi。 执行如下命令把代码目录的device、vendor目录复制到openHarmony工程的相应目录。 - -``` -cp -r ~/nucleo_f767zi/device/st ~/openHarmony/device/st -cp -r ~/nucleo_f767zi/vendor/st ~/openHarmony/vendor/st -``` - -关于示例代码目录的说明,可以参考资料站点[板级目录规范](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0-0.md#section6204129143013)。如果需要自行移植开发板,请参考[板级系统移植](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E6%9D%BF%E7%BA%A7%E7%B3%BB%E7%BB%9F%E7%A7%BB%E6%A4%8D.md)。 - -## 编译运行 - -编译运行前,把交叉编译工具链bin目录配置到PATH环境变量中或者在device/st/nucleo\_f767zi/liteos\_m/config.gni文件中把board\_toolchain\_path配置项设置为交叉编译工具链bin目录。 在OpenHarmony根目录,执行hb set设置产品路径,选择nucleo\_f767zi产品,然后执行hb build开启编译。如下: - -``` -user@dev:~/OpenHarmony$ hb set -[OHOS INFO] Input code path: # 直接按回车,然后选择nucleo_f767zi产品即可 -OHOS Which product do you need? nucleo_f767zi@st -user@dev:~/OpenHarmony$ hb build -``` - -最终的镜像生成在\~/openHarmony/out/nucleo\_f767zi/目录中,通过STM32 ST-LINK Utility软件将镜像文件下载至单板查看运行效果。 - diff --git "a/zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" "b/zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" deleted file mode 100644 index dcfc826616e437211372c13a415dcc6b3657ae63..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\211\251\345\261\225\347\273\204\344\273\266.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 扩展组件 - -- **[C++支持](C++支持.md)** - -- **[CPUP](CPUP.md)** - -- **[文件系统](文件系统-19.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" "b/zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" deleted file mode 100755 index c1735a0278573df6d279873637fc764342e644e8..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\345\221\275\344\273\244.md" +++ /dev/null @@ -1,45 +0,0 @@ -# 文件命令 - -- **[cat](cat.md)** - -- **[cd](cd.md)** - -- **[chgrp](chgrp.md)** - -- **[chmod](chmod.md)** - -- **[chown](chown.md)** - -- **[cp](cp.md)** - -- **[format](format.md)** - -- **[ls](ls.md)** - -- **[lsfd](lsfd.md)** - -- **[mkdir](mkdir.md)** - -- **[mount](mount.md)** - -- **[partinfo](partinfo.md)** - -- **[partition](partition.md)** - -- **[pwd](pwd.md)** - -- **[rm](rm.md)** - -- **[rmdir](rmdir.md)** - -- **[statfs](statfs.md)** - -- **[sync](sync.md)** - -- **[touch](touch.md)** - -- **[writeproc](writeproc.md)** - -- **[umount](umount.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" "b/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" deleted file mode 100644 index ba10ab39c51ce9917ccc7a664e4b13c3e7842824..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237-19.md" +++ /dev/null @@ -1,204 +0,0 @@ -# 文件系统 - -当前支持的文件系统有FATFS与LittleFS,支持的功能如下表所示: - -**表 1** ****功能列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

FATFS

-

LITTELFS

-

文件操作

-

open

-

打开文件

-

支持

-

支持

-

close

-

关闭文件

-

支持

-

支持

-

read

-

读取文件内容

-

支持

-

支持

-

write

-

往文件写入内容

-

支持

-

支持

-

lseek

-

设置文件偏移位置

-

支持

-

支持

-

unlink

-

删除文件

-

支持

-

支持

-

rename

-

重命名文件

-

支持

-

支持

-

fstat

-

通过文件句柄获取文件信息

-

支持

-

支持

-

stat

-

通过文件路径名获取文件信息

-

支持

-

支持

-

fsync

-

文件内容刷入存储设备

-

支持

-

支持

-

目录操作

-

mkdir

-

创建目录

-

支持

-

支持

-

opendir

-

打开目录

-

支持

-

支持

-

readdir

-

读取目录项内容

-

支持

-

支持

-

closedir

-

关闭目录

-

支持

-

支持

-

rmdir

-

删除目录

-

支持

-

支持

-

分区操作

-

mount

-

分区挂载

-

支持

-

支持

-

umount

-

分区卸载

-

支持

-

支持

-

umount2

-

分区卸载,可通过MNT_FORCE参数进行强制卸载

-

支持

-

不支持

-

statfs

-

获取分区信息

-

支持

-

不支持

-
- -- **[FAT](FAT-20.md)** - -- **[LittleFS](LittleFS.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" "b/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" deleted file mode 100644 index b17821e62df9a268e8b4328bafafe90bba795d3b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\226\207\344\273\266\347\263\273\347\273\237.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 文件系统 - -OpenHarmony轻内核支持的文件系统有:VFS(虚拟文件系统)、NFS、RAMFS、FAT、JFFS2。 - -**各个文件系统功能概述:** - -**表 1** 文件系统功能概述 - - - - - - - - - - - - - - - - - - - - - - -

文件系统

-

功能特点概述

-

VFS

-

VFS是Virtual File System(虚拟文件系统)的缩写,它不是一个实际的文件系统,而是一个异构文件系统之上的软件粘合层,为用户提供统一的类Unix文件操作接口。

-

NFS

-

NFS是Network File System(网络文件系统)的缩写。它最大的功能是可以通过网络,让不同的机器、不同的操作系统彼此分享其他用户的文件。

-

RAMFS

-

RAMFS是一种基于RAM的文件系统。RAMFS文件系统把所有的文件都放在RAM中,所以读/写操作发生在RAM中,避免了对存储器的读写损耗,也提高了数据读写速度。RAMFS是基于RAM的动态文件系统的一种存储缓冲机制。

-

FAT

-

FAT文件系统是File Allocation Table(文件配置表)的简称,有FAT12、FAT16、FAT32。在可移动存储介质(U盘、SD卡、移动硬盘等)上多使用FAT文件系统,使设备与Windows、Linux等桌面系统之间保持很好的兼容性。

-

JFFS2

-

JFFS2是Journalling Flash File System Version 2(日志文件系统)的缩写,是MTD设备上的日志型文件系统。主要应用于对NOR_FLASH闪存的文件管理。OpenHarmony内核的JFFS2支持多分区。

-
- -- **[VFS](VFS.md)** - -- **[NFS](NFS.md)** - -- **[RAMFS](RAMFS.md)** - -- **[FAT](FAT.md)** - -- **[JFFS2](JFFS2.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" "b/zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" deleted file mode 100644 index 967a229499e4473b06fadcc91807e5a91cab2e66..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\227\266\351\227\264\347\256\241\347\220\206.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 时间管理 - -- **[基本概念](基本概念-13.md)** - -- **[开发指导](开发指导-14.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" deleted file mode 100755 index a365148450986901a04ff48891283a2ab4b8ded8..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223-0.md" +++ /dev/null @@ -1,197 +0,0 @@ -# 标准库 - -- [框架流程](#section1247343413257) -- [操作实例](#section4807125622614) -- [常见问题](#section1219455217277) - -OpenHarmony内核OpenHarmony使用**musl libc**库,支持标准POSIX接口,开发者可基于POSIX标准接口开发内核之上的组件及应用。 - -## 框架流程 - -**图 1** POSIX接口框架 -![](figures/POSIX接口框架.png "POSIX接口框架") - -**musl libc**库支持POSIX标准,涉及的系统调用相关接口由OpenHarmony内核适配支持 ,以满足接口对外描述的功能要求。 - -标准库支持接口的详细情况请参考C库的API文档,其中也涵盖了与POSIX标准之间的差异说明。 - -## 操作实例 - -在本示例中,主线程创建了THREAD\_NUM个子线程,每个子线程启动后等待被主线程唤醒,主线程成功唤醒所有子线程后,子线程继续执行直至生命周期结束,同时主线程通过pthread\_join方法等待所有线程执行结束。 - -``` -#include -#include -#include - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif /* __cplusplus */ -#endif /* __cplusplus */ - -#define THREAD_NUM 3 -int g_startNum = 0; /* 启动的线程数 */ -int g_wakenNum = 0; /* 唤醒的线程数 */ - -struct testdata { - pthread_mutex_t mutex; - pthread_cond_t cond; -} g_td; - -/* - * 子线程入口函数 - */ -static void *ChildThreadFunc(void *arg) -{ - int rc; - pthread_t self = pthread_self(); - - /* 获取mutex锁 */ - rc = pthread_mutex_lock(&g_td.mutex); - if (rc != 0) { - printf("ERROR:take mutex lock failed, error code is %d!\n", rc); - goto EXIT; - } - - /* g_startNum计数加一,用于统计已经获得mutex锁的子线程个数 */ - g_startNum++; - - /* 等待cond条件变量 */ - rc = pthread_cond_wait(&g_td.cond, &g_td.mutex); - if (rc != 0) { - printf("ERROR: pthread condition wait failed, error code is %d!\n", rc); - (void)pthread_mutex_unlock(&g_td.mutex); - goto EXIT; - } - - /* 尝试获取mutex锁,正常场景,此处无法获取锁 */ - rc = pthread_mutex_trylock(&g_td.mutex); - if (rc == 0) { - printf("ERROR: mutex gets an abnormal lock!\n"); - goto EXIT; - } - - /* g_wakenNum计数加一,用于统计已经被cond条件变量唤醒的子线程个数 */ - g_wakenNum++; - - /* 释放mutex锁 */ - rc = pthread_mutex_unlock(&g_td.mutex); - if (rc != 0) { - printf("ERROR: mutex release failed, error code is %d!\n", rc); - goto EXIT; - } -EXIT: - return NULL; -} - -static int testcase(void) -{ - int i, rc; - pthread_t thread[THREAD_NUM]; - - /* 初始化mutex锁 */ - rc = pthread_mutex_init(&g_td.mutex, NULL); - if (rc != 0) { - printf("ERROR: mutex init failed, error code is %d!\n", rc); - goto ERROROUT; - } - - /* 初始化cond条件变量 */ - rc = pthread_cond_init(&g_td.cond, NULL); - if (rc != 0) { - printf("ERROR: pthread condition init failed, error code is %d!\n", rc); - goto ERROROUT; - } - - /* 批量创建THREAD_NUM个子线程 */ - for (i = 0; i < THREAD_NUM; i++) { - rc = pthread_create(&thread[i], NULL, ChildThreadFunc, NULL); - if (rc != 0) { - printf("ERROR: pthread create failed, error code is %d!\n", rc); - goto ERROROUT; - } - } - - /* 等待所有子线程都完成mutex锁的获取 */ - while (g_startNum < THREAD_NUM) { - usleep(100); - } - - /* 获取mutex锁,确保所有子线程都阻塞在pthread_cond_wait上 */ - rc = pthread_mutex_lock(&g_td.mutex); - if (rc != 0) { - printf("ERROR: mutex lock failed, error code is %d\n", rc); - goto ERROROUT; - } - - /* 释放mutex锁 */ - rc = pthread_mutex_unlock(&g_td.mutex); - if (rc != 0) { - printf("ERROR: mutex unlock failed, error code is %d!\n", rc); - goto ERROROUT; - } - - for (int j = 0; j < THREAD_NUM; j++) { - /* 在cond条件变量上广播信号 */ - rc = pthread_cond_signal(&g_td.cond); - if (rc != 0) { - printf("ERROR: pthread condition failed, error code is %d!\n", rc); - goto ERROROUT; - } - } - - sleep(1); - - /* 检查是否所有子线程都已被唤醒 */ - if (g_wakenNum != THREAD_NUM) { - printf("ERROR: not all threads awaken, only %d thread(s) awaken!\n", g_wakenNum); - goto ERROROUT; - } - - /* join所有子线程,即等待其结束 */ - for (i = 0; i < THREAD_NUM; i++) { - rc = pthread_join(thread[i], NULL); - if (rc != 0) { - printf("ERROR: pthread join failed, error code is %d!\n", rc); - goto ERROROUT; - } - } - - /* 销毁cond条件变量 */ - rc = pthread_cond_destroy(&g_td.cond); - if (rc != 0) { - printf("ERROR: pthread condition destroy failed, error code is %d!\n", rc); - goto ERROROUT; - } - return 0; -ERROROUT: - return -1; -} - -/* - * 示例代码主函数 - */ -int main(int argc, char *argv[]) -{ - int rc; - - /* 启动测试函数 */ - rc = testcase(); - if (rc != 0) { - printf("ERROR: testcase failed!\n"); - } - - return 0; -} -#ifdef __cplusplus -#if __cplusplus -} -#endif /* __cplusplus */ -#endif /* __cplusplus */ -``` - -## 常见问题 - -无。 - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" deleted file mode 100755 index 56f2c7aa1b5ffa7d292a929f310373364a55d09c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 标准库 - -- **[标准库](标准库-0.md)** - -- **[与Linux标准库的差异](与Linux标准库的差异.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" deleted file mode 100644 index 7522c305c5e44955578700d055f5320dd744d90c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\345\272\223\346\224\257\346\214\201.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 标准库支持 - -- **[CMSIS支持](CMSIS支持.md)** - -- **[POSIX支持](POSIX支持.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index 5911c5e037af1c64615d90c915a8d4a5defe1761..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\240\207\345\207\206\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 标准系统内核 - -- **[Linux内核概述](Linux内核概述.md)** - -- **[OpenHarmony开发板Patch使用指导](OpenHarmony开发板Patch使用指导.md)** - -- **[Linux内核编译与构建指导](Linux内核编译与构建指导.md)** - - diff --git "a/zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" "b/zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" deleted file mode 100644 index 3a5640015631e761cd32d7ed3b6564cbb056e5a4..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\346\266\210\346\201\257\351\230\237\345\210\227.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 消息队列 - -- **[基本概念](基本概念-9.md)** - -- **[开发指导](开发指导-10.md)** - - diff --git "a/zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" "b/zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" deleted file mode 100755 index 6d10fdb0221d7d2aaf211f32ca45b1c37b1bb884..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\347\263\273\347\273\237\345\221\275\344\273\244.md" +++ /dev/null @@ -1,47 +0,0 @@ -# 系统命令 - -- **[cpup](cpup.md)** - -- **[date](date.md)** - -- **[dmesg](dmesg.md)** - -- **[exec](exec.md)** - -- **[free](free.md)** - -- **[help](help.md)** - -- **[hwi](hwi.md)** - -- **[kill](kill.md)** - -- **[log](log.md)** - -- **[memcheck](memcheck.md)** - -- **[oom](oom.md)** - -- **[pmm](pmm.md)** - -- **[reset](reset.md)** - -- **[sem](sem.md)** - -- **[stack](stack.md)** - -- **[su](su.md)** - -- **[swtmr](swtmr.md)** - -- **[systeminfo](systeminfo.md)** - -- **[task](task.md)** - -- **[uname](uname.md)** - -- **[vmm](vmm.md)** - -- **[watch](watch.md)** - - diff --git "a/zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" "b/zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" deleted file mode 100755 index 7add0e4dc775da92317ccd9a6bb4edb6f6dff2e9..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\347\272\277\347\250\213.md" +++ /dev/null @@ -1,702 +0,0 @@ -# 线程 - -- [基本概念](#section1179311337405) -- [使用场景](#section44877547404) -- [接口说明](#section2069477134115) - -## 基本概念 - -从系统的角度看,线程是竞争系统资源的最小运行单元。线程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它线程运行。 - -OpenHarmony内核每个进程内的线程独立运行、独立调度,当前进程内线程的调度不受其它进程内线程的影响。 - -OpenHarmony内核中的线程采用抢占式调度机制,同时支持时间片轮转调度和FIFO调度方式。 - -OpenHarmony内核的线程一共有32个优先级\(0-31\),最高优先级为0,最低优先级为31。 - -当前进程内高优先级的线程可抢占当前进程内低优先级线程,当前进程内低优先级线程必须在当前进程内高优先级线程阻塞或结束后才能得到调度。 - -**线程状态说明:** - -- 初始化(Init):该线程正在被创建。 - -- 就绪(Ready):该线程在就绪列表中,等待CPU调度。 - -- 运行(Running):该线程正在运行。 - -- 阻塞(Blocked):该线程被阻塞挂起。Blocked状态包括:pending\(因为锁、事件、信号量等阻塞\)、suspended(主动pend)、delay\(延时阻塞\)、pendtime\(因为锁、事件、信号量时间等超时等待\)。 - -- 退出(Exit):该线程运行结束,等待父线程回收其控制块资源。 - - -**图 1** 线程状态迁移示意图 -![](figures/线程状态迁移示意图.png "线程状态迁移示意图") - -**线程状态迁移说明:** - -- Init→Ready: - - 线程创建拿到控制块后为Init状态,处于线程初始化阶段,当线程初始化完成将线程插入调度队列,此时线程进入就绪状态。 - -- Ready→Running: - - 线程创建后进入就绪态,发生线程切换时,就绪列表中最高优先级的线程被执行,从而进入运行态,但此刻该线程会从就绪列表中删除。 - -- Running→Blocked: - - 正在运行的线程发生阻塞(挂起、延时、读信号量等)时,线程状态由运行态变成阻塞态,然后发生线程切换,运行就绪列表中剩余最高优先级线程。 - -- Blocked→Ready : - - 阻塞的线程被恢复后(线程恢复、延时时间超时、读信号量超时或读到信号量等),此时被恢复的线程会被加入就绪列表,从而由阻塞态变成就绪态。 - -- Ready→Blocked: - - 线程也有可能在就绪态时被阻塞(挂起),此时线程状态会由就绪态转变为阻塞态,该线程从就绪列表中删除,不会参与线程调度,直到该线程被恢复。 - -- Running→Ready: - - 有更高优先级线程创建或者恢复后,会发生线程调度,此刻就绪列表中最高优先级线程变为运行态,那么原先运行的线程由运行态变为就绪态,并加入就绪列表中。 - -- Running→Exit: - - 运行中的线程运行结束,线程状态由运行态变为退出态。若未设置分离属性(PTHREAD\_CREATE\_DETACHED)的线程,运行结束后对外呈现的是Exit状态,即退出态。 - - -## 使用场景 - -线程创建后,用户态可以执行线程调度、挂起、恢复、延时等操作,同时也可以设置线程优先级和调度策略,获取线程优先级和调度策略。 - -## 接口说明 - -OpenHarmony内核系统中的线程管理模块,线程间通信为用户提供下面几种功能: - -**表 1** 线程管理模块功能 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

名称

-

说明

-

备注

-

pthread.h

-

pthread_attr_destroy

-

销毁线程属性对象。

-

-

-

pthread.h

-

pthread_attr_getinheritsched

-

获取线程属性对象的调度属性。

-

-

-

pthread.h

-

pthread_attr_getschedparam

-

获取线程属性对象的调度参数属性。

-

-

-

pthread.h

-

pthread_attr_getschedpolicy

-

获取线程属性对象的调度策略属性。

-

OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

-

pthread.h

-

pthread_attr_getstacksize

-

获取线程属性对象的堆栈大小。

-

-

-

pthread.h

-

pthread_attr_init

-

初始化线程属性对象。

-

-

-

pthread.h

-

pthread_attr_setdetachstate

-

设置线程属性对象的分离状态。

-

-

-

pthread.h

-

pthread_attr_setinheritsched

-

设置线程属性对象的继承调度属性。

-

-

-

pthread.h

-

pthread_attr_setschedparam

-

设置线程属性对象的调度参数属性。

-

OpenHarmony:设置线程优先级的参数值越小,线程在系统中的优先级越高;设置参数值越大,优先级越低。

-

注意:需要将pthread_attr_t线程属性的inheritsched字段设置为PTHREAD_EXPLICIT_SCHED,否则设置的线程调度优先级将不会生效,系统默认设置为PTHREAD_INHERIT_SCHED。

-

pthread.h

-

pthread_attr_setschedpolicy

-

设置线程属性对象的调度策略属性。

-

OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

-

pthread.h

-

pthread_attr_setstacksize

-

设置线程属性对象的堆栈大小。

-

-

-

pthread.h

-

pthread_getattr_np

-

获取已创建线程的属性。

-

-

-

pthread.h

-

pthread_cancel

-

向线程发送取消请求。

-

-

-

pthread.h

-

pthread_testcancel

-

请求交付任何未决的取请求。

-

-

-

pthread.h

-

pthread_setcanceltype

-

设置线程可取消类型。

-

-

-

pthread.h

-

pthread_setcancelstate

-

设置线程可取消状态。

-

-

-

pthread.h

-

pthread_create

-

创建一个新的线程。

-

-

-

pthread.h

-

pthread_detach

-

分离一个线程。

-

-

-

pthread.h

-

pthread_equal

-

比较两个线程ID是否相等。

-

-

-

pthread.h

-

pthread_exit

-

终止正在调用的线程。

-

-

-

pthread.h

-

pthread_getschedparam

-

获取线程的调度策略和参数。

-

OpenHarmony:支持SCHED_FIFO 、SCHED_RR调度策略。

-

pthread.h

-

pthread_join

-

等待指定的线程结束。

-

-

-

pthread.h

-

pthread_self

-

获取当前线程的ID。

-

-

-

pthread.h

-

pthread_setschedprio

-

设置线程的调度静态优先级。

-

-

-

pthread.h

-

pthread_kill

-

向线程发送信号。

-

-

-

pthread.h

-

pthread_once

-

使函数调用只能执行一次。

-

-

-

pthread.h

-

pthread_atfork

-

注册fork的处理程序。

-

-

-

pthread.h

-

pthread_cleanup_pop

-

删除位于清理处理程序堆栈顶部的例程。

-

-

-

pthread.h

-

pthread_cleanup_push

-

将例程推送到清理处理程序堆栈的顶部。

-

-

-

pthread.h

-

pthread_barrier_destroy

-

销毁屏障对象(高级实时线程)

-

-

-

pthread.h

-

pthread_barrier_init

-

初始化屏障对象(高级实时线程)

-

-

-

pthread.h

-

pthread_barrier_wait

-

屏障同步(高级实时线程)

-

-

-

pthread.h

-

pthread_barrierattr_destroy

-

销毁屏障属性对象。

-

-

-

pthread.h

-

pthread_barrierattr_init

-

初始化屏障属性对象。

-

-

-

pthread.h

-

pthread_mutex_destroy

-

销毁互斥锁。

-

-

-

pthread.h

-

pthread_mutex_init

-

初始化互斥锁。

-

-

-

pthread.h

-

pthread_mutex_lock

-

互斥锁加锁操作。

-

-

-

pthread.h

-

pthread_mutex_trylock

-

互斥锁尝试加锁操作。

-

-

-

pthread.h

-

pthread_mutex_unlock

-

互斥锁解锁操作。

-

-

-

pthread.h

-

pthread_mutexattr_destroy

-

销毁互斥锁属性对象。

-

-

-

pthread.h

-

pthread_mutexattr_gettype

-

获取互斥锁类型属性。

-

-

-

pthread.h

-

pthread_mutexattr_init

-

初始化互斥锁属性对象。

-

-

-

pthread.h

-

pthread_mutexattr_settype

-

设置互斥锁类型属性。

-

-

-

pthread.h

-

pthread_mutex_timedlock

-

使用超时锁定互斥锁。

-

-

-

pthread.h

-

pthread_rwlock_destroy

-

销毁读写锁。

-

-

-

pthread.h

-

pthread_rwlock_init

-

初始化读写锁。

-

-

-

pthread.h

-

pthread_rwlock_rdlock

-

获取读写锁读锁操作。

-

-

-

pthread.h

-

pthread_rwlock_timedrdlock

-

使用超时锁定读写锁读锁。

-

-

-

pthread.h

-

pthread_rwlock_timedwrlock

-

使用超时锁定读写锁写锁。

-

-

-

pthread.h

-

pthread_rwlock_tryrdlock

-

尝试获取读写锁读锁操作。

-

-

-

pthread.h

-

pthread_rwlock_trywrlock

-

尝试获取读写锁写锁操作。

-

-

-

pthread.h

-

pthread_rwlock_unlock

-

读写锁解锁操作。

-

-

-

pthread.h

-

pthread_rwlock_wrlock

-

获取读写锁写锁操作。

-

-

-

pthread.h

-

pthread_rwlockattr_destroy

-

销毁读写锁属性对象。

-

-

-

pthread.h

-

pthread_rwlockattr_init

-

初始化读写锁属性对象。

-

-

-

pthread.h

-

pthread_cond_broadcast

-

解除若干已被等待条件阻塞的线程。

-

-

-

pthread.h

-

pthread_cond_destroy

-

销毁条件变量。

-

-

-

pthread.h

-

pthread_cond_init

-

初始化条件变量。

-

-

-

pthread.h

-

pthread_cond_signal

-

解除被阻塞的线程。

-

-

-

pthread.h

-

pthread_cond_timedwait

-

定时等待条件。

-

-

-

pthread.h

-

pthread_cond_wait

-

等待条件。

-

-

-

semaphore.h

-

sem_destroy

-

销毁指定的无名信号量。

-

-

-

semaphore.h

-

sem_getvalue

-

获得指定信号量计数值。

-

-

-

semaphore.h

-

sem_init

-

创建并初始化一个无名信号量。

-

-

-

semaphore.h

-

sem_post

-

增加信号量计数。

-

-

-

semaphore.h

-

sem_timedwait

-

获取信号量,且有超时返回功能。

-

-

-

semaphore.h

-

sem_trywait

-

尝试获取信号量。

-

-

-

semaphore.h

-

sem_wait

-

获取信号量。

-

-

-
- diff --git "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" "b/zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" deleted file mode 100755 index 17eafd2f164bce1274e6f33838e60f7ef7a255f2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234.md" +++ /dev/null @@ -1,303 +0,0 @@ -# 网络 - -- [基本概念](#section9840143083510) -- [使用场景](#section1575885183516) -- [接口说明](#section16351198193614) - -## 基本概念 - -网络模块实现了TCP/IP协议栈基本功能,提供标准的POSIX socket接口。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前系统使用**lwIP**提供网络能力。 - -## 使用场景 - -针对用户态开发,OpenHarmony内核提供了一套网络功能系统调用接口,支持socket的创建关闭、数据收发、网络属性的设置等,通过C库提供标准的POSIX socket函数供开发者使用。 - -## 接口说明 - -**表 1** 标准C库相关接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

头文件

-

接口

-

功能

-

sys/socket.h

-

int accept(int socket, struct sockaddr *address, socklen_t *address_len)

-

接受连接。

-

sys/socket.h

-

int bind(int s, const struct sockaddr *name, socklen_t namelen)

-

socket与IP地址绑定。

-

sys/socket.h

-

int shutdown(int socket, int how)

-

关闭连接。

-

sys/socket.h

-

int getpeername(int s, struct sockaddr *name, socklen_t *namelen)

-

获取对端地址。

-

sys/socket.h

-

int getsockname(int s, struct sockaddr *name, socklen_t *namelen)

-

获取本地地址。

-

sys/socket.h

-

int getsockopt(int s, struct sockaddr *name, socklen_t *namelen)

-

获取socket属性信息。

-

sys/socket.h

-

int setsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen)

-

配置socket属性。

-

unistd.h

-

int close(int s)

-

关闭socket。

-

sys/socket.h

-

int connect(int s, const struct sockaddr *name, socklen_t namelen)

-

连接到指定的目的IP。

-

sys/socket.h

-

int listen(int sockfd, int backlog)

-

聆听连接本socket的请求。

-

sys/socket.h

-

ssize_t recv(int socket, void *buffer, size_t length, int flags)

-

接收socket上收到的数据。

-

sys/socket.h

-

ssize_t recvmsg(int s, struct msghdr *message, int flags)

-

接收socket上收到的数据,可使用更丰富的参数。

-

sys/socket.h

-

ssize_t recvfrom(int socket, void *buffer, size_t length, int flags, struct sockaddr *address, socklen_t *address_len)

-

接收socket上收到的数据,可同时获得数据来源IP地址。

-

sys/socket.h

-

ssize_t send(int s, const void *dataptr, size_t size, int flags)

-

通过socket发送数据。

-

sys/socket.h

-

ssize_t sendmsg(int s, const struct msghdr *message, int flags)

-

通过socket发送数据,可使用更丰富的参数。

-

sys/socket.h

-

ssize_t sendto(int s, const void *dataptr, size_t size, int flags, const struct sockaddr *to, socklen_t tolen)

-

通过socket发送数据,可指定发送的目的IP地址。

-

sys/socket.h

-

int socket(int domain, int type, int protocol)

-

创建socket。

-

sys/select.h

-

int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)

-

多路复用。

-

sys/ioctl.h

-

int ioctl(int s, int request, ...)

-

socket属性获取、设置。

-

arpa/inet.h

-

const char *inet_ntop(int af, const void *src, char *dst, socklen_t size)

-

网络地址格式转换:将二进制格式IP地址转换为字符串格式。

-

arpa/inet.h

-

int inet_pton(int af, const char *src, void *dst)

-

网络地址格式转换:将字符串格式IP地址转换为二进制格式。

-
- -与标准接口差异详细说明: - -- **sendmsg** - - **函数原型:** - - ssize\_t sendmsg\(int s, const struct msghdr \*message, int flags\) - - **函数功能:**发送消息。 - - **参数说明:** - - - - - - - - - - - - - - - - -

参数

-

描述

-

s

-

套接字描述符。

-

message

-

待发送的消息,不支持发送ancillary消息。

-

flags

-

用于指定发送消息时行为特性,有如下行为特性:

-
  • MSG_MORE:允许将多次发送的消息进行拼包发送。
  • MSG_DONTWAIT:非阻塞操作。
-
- - **返回值:** - - - 成功返回:已发送的消息长度(字节数)。 - - 失败返回:-1,并设置errno。 - - -- **recvmsg** - - **函数原型:** - - ssize\_t recvmsg\(int s, struct msghdr \*message, int flags\) - - **函数功能:**接收消息。 - - **参数说明:** - - - - - - - - - - - - - - - - -

参数

-

描述

-

s

-

套接字描述符。

-

message

-

存放接收的消息,不支持接收ancillary消息。

-

flags

-

用于指定接收消息时行为特性,有如下行为特性:

-
  • MSG_PEEK:允许预读消息而不取走。
  • MSG_DONTWAIT:非阻塞操作。
-
- - **返回值:** - - - 成功返回:已接收的消息长度(字节数)。 - - 失败返回:-1,并设置errno。 - - -- **ioctl** - - **函数原型:** - - int ioctl\(int s, int request, ...\) - - **函数功能:**获取或设置socket属性。 - - **参数说明:** - - - - - - - - - - - - - -

参数

-

描述

-

s

-

套接字描述符。

-

request

-

对socket属性要进行的操作,当前支持如下操作:

-
  • FIONREAD:获取socket当前可读取的数据大小(字节数)。
  • FIONBIO:设置socket是否非阻塞。
-
- - **返回值:** - - - 成功返回:0。 - - 失败返回:-1,并设置errno。 - - diff --git "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" "b/zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" deleted file mode 100755 index 2a1245c1579a6c54b19f60a348de42461a2cce77..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\347\275\221\347\273\234\345\221\275\344\273\244.md" +++ /dev/null @@ -1,25 +0,0 @@ -# 网络命令 - -- **[arp](arp.md)** - -- **[dhclient](dhclient.md)** - -- **[dns](dns.md)** - -- **[ifconfig](ifconfig.md)** - -- **[ipdebug](ipdebug.md)** - -- **[netstat](netstat.md)** - -- **[ntpdate](ntpdate.md)** - -- **[ping](ping.md)** - -- **[ping6](ping6.md)** - -- **[telnet](telnet.md)** - -- **[tftp](tftp.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" deleted file mode 100644 index 7984b0843bb602a8962a0c40915c143803202041..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\256\244\350\257\206LiteOS-M\345\206\205\346\240\270.md" +++ /dev/null @@ -1,62 +0,0 @@ -# 认识LiteOS-M内核 - -- [内核简介](#section1429342661510) - - [cpu体系架构支持](#section48891456112819) - - [运行机制](#section4599142312817) - - -## 内核简介 - -OpenHarmony LiteOS-M内核是面向IoT领域构建的轻量级物联网操作系统内核,具有小体积、低功耗、高性能的特点。其代码结构简单,主要包括内核最小功能集、内核抽象层、可选组件以及工程目录等。OpenHarmony LiteOS-M内核架构包含硬件相关层以及硬件无关层,如下图所示,其中Kernel Arch模块属于硬件相关层,该模块按不同编译工具链、芯片架构分类,提供统一的HAL(Hardware Abstraction Layer)接口,提升了硬件易适配性,满足AIoT类型丰富的硬件和编译工具链的拓展;Components等其他模块属于硬件无关层,其中Kernel Task等内核模块提供基础能力,Components模块提供网络、文件系统等组件能力,Utils模块提供错误处理、调测等能力,KAL(Kernel Abstraction Layer)模块提供统一的标准接口。 - -**图 1** 内核架构图 -![](figures/内核架构图.png "内核架构图") - -### cpu体系架构支持 - -CPU体系架构分为通用架构定义和特定架构定义两层,通用架构定义层为所有体系架构都需要支持和实现的接口,特定架构定义层为特定体系架构所特有的部分。在新增一个体系架构的时候,必须需要实现通用架构定义层,如果该体系架构还有特有的功能,可以在特定架构定义层来实现。 - -**表 1** CPU体系架构规则 - - - - - - - - - - - - - - - - - - - - -

规则

-

通用体系架构层

-

特定体系架构层

-

头文件位置

-

kernel/arch/include

-

kernel/arch/<arch>/<arch>/<toolchain>/

-

头文件命名

-

los_<function>.h

-

los_arch_<function>.h

-

函数命名

-

Halxxxx

-

Halxxxx

-
- -LiteOS-M已经支持ARM Cortex-M3、ARM Cortex-M4、ARM Cortex-M7、ARM Cortex-M33、RISC-V等主流架构,如果需要扩展CPU体系架构,请参考[芯片架构适配点](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/porting/%E7%A7%BB%E6%A4%8D%E6%A6%82%E8%BF%B0.md#%E8%8A%AF%E7%89%87%E6%9E%B6%E6%9E%84%E9%80%82%E9%85%8D%E7%82%B9)。 - -### 运行机制 - -在开发板配置文件target\_config.h配置系统时钟、每秒Tick数,可以对任务、内存、IPC、异常处理模块进行裁剪配置。系统启动时,根据配置进行指定模块的初始化。内核启动流程包含外设初始化、系统时钟配置、内核初始化、操作系统启动等,详见内核启动流程图。 - -**图 2** 内核启动流程 -![](figures/内核启动流程.png "内核启动流程") - diff --git "a/zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" "b/zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" deleted file mode 100755 index 2327e141234e6cce885f500c2297d1de5f9061cd..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\260\203\346\265\213.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 调测 - -- **[Shell介绍](Shell介绍.md)** - -- **[Shell命令开发指导](Shell命令开发指导.md)** - -- **[Shell命令编程实例](Shell命令编程实例.md)** - -- **[Shell命令使用详解](Shell命令使用详解.md)** - -- **[魔法键使用方法](魔法键使用方法.md)** - -- **[用户态异常信息说明](用户态异常信息说明.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" "b/zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" deleted file mode 100644 index ab5d4101a001ddd96502f65b446ba27511f254ab..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\270\251\345\206\205\345\255\230\346\243\200\346\265\213.md" +++ /dev/null @@ -1,85 +0,0 @@ -# 踩内存检测 - -- [基础概念](#section17368154517335) -- [功能配置](#section4696190123420) -- [开发指导](#section672362973417) - - [开发流程](#section026014863416) - - [编程实例](#section186311302356) - - [示例代码](#section12709533354) - - [结果验证](#section81214126369) - - -## 基础概念 - -踩内存检测机制作为内核的可选功能,用于检测动态内存池的完整性。通过该机制,可以及时发现内存池是否发生了踩内存问题,并给出错误信息,便于及时发现系统问题,提高问题解决效率,降低问题定位成本。 - -## 功能配置 - -LOSCFG\_BASE\_MEM\_NODE\_INTEGRITY\_CHECK:开关宏,默认关闭;若打开这个功能,在target\_config.h中将这个宏定义为1。 - -1. 开启这个功能,每次申请内存,会实时检测内存池的完整性。 -2. 如果不开启该功能,也可以调用LOS\_MemIntegrityCheck接口检测,但是每次申请内存时,不会实时检测内存完整性,而且由于节点头没有魔鬼数字(开启时才有,省内存),检测的准确性也会相应降低,但对于系统的性能没有影响,故根据实际情况开关该功能。 - -由于该功能只会检测出哪个内存节点被破坏了,并给出前节点信息(因为内存分布是连续的,当前节点最有可能被前节点破坏)。如果要进一步确认前节点在哪里申请的,需开启内存泄漏检测功能,通过LR记录,辅助定位。 - ->![](public_sys-resources/icon-caution.gif) **注意:** ->开启该功能,节点头多了魔鬼数字字段,会增大节点头大小。由于实时检测完整性,故性能影响较大;若性能敏感的场景,可以不开启该功能,使用LOS\_MemIntegrityCheck接口检测。 - -## 开发指导 - -### 开发流程 - -通过调用LOS\_MemIntegrityCheck接口检测内存池是否发生了踩内存,如果没有踩内存问题,那么接口返回0且没有log输出;如果存在踩内存问题,那么会输出相关log,详见下文编程实例的结果输出。 - -### 编程实例 - -本实例实现如下功能: - -1. 申请两个物理上连续的内存块; -2. 通过memset构造越界访问,踩到下个节点的头4个字节; -3. 调用LOS\_MemIntegrityCheck检测是否发生踩内存。 - -### 示例代码 - -代码实现如下: - -``` -#include -#include -#include "los_memory.h" -#include "los_config.h" - -void MemIntegrityTest(void) -{ - /* 申请两个物理连续的内存块 */ - void *ptr1 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - void *ptr2 = LOS_MemAlloc(LOSCFG_SYS_HEAP_ADDR, 8); - /* 第一个节点内存块大小是8字节,那么12字节的清零,会踩到第二个内存节点的节点头,构造踩内存场景 */ - memset(ptr1, 0, 8 + 4); - LOS_MemIntegrityCheck(LOSCFG_SYS_HEAP_ADDR); -} -``` - -### 结果验证 - -编译运行输出log如下: - -``` -[ERR][OsMemMagicCheckPrint], 2028, memory check error! -memory used but magic num wrong, magic num = 0x00000000 /* 提示信息,检测到哪个字段被破坏了,用例构造了将下个节点的头4个字节清零,即魔鬼数字字段 */ - - broken node head: 0x20003af0 0x00000000 0x80000020, prev node head: 0x20002ad4 0xabcddcba 0x80000020 -/* 被破坏节点和其前节点关键字段信息,分别为其前节点地址、节点的魔鬼数字、节点的sizeAndFlag;可以看出被破坏节点的魔鬼数字字段被清零,符合用例场景 */ - - broken node head LR info: /* 节点的LR信息需要开启内存检测功能才有有效输出 */ - LR[0]:0x0800414e - LR[1]:0x08000cc2 - LR[2]:0x00000000 - - pre node head LR info: /* 通过LR信息,可以在汇编文件中查找前节点是哪里申请,然后排查其使用的准确性 */ - LR[0]:0x08004144 - LR[1]:0x08000cc2 - LR[2]:0x00000000 -[ERR]Memory interity check error, cur node: 0x20003b10, pre node: 0x20003af0 /* 被破坏节点和其前节点的地址 */ -``` - diff --git "a/zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" "b/zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" deleted file mode 100644 index 903970bdd61bd096a10c842a567cdcfa25d9ba13..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\275\257\344\273\266\345\256\232\346\227\266\345\231\250.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 软件定时器 - -- **[基本概念](基本概念-15.md)** - -- **[开发指导](开发指导-16.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index 0ae605881ae93ccbe37bda0971479cb69a6be0e8..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 轻量和小型系统内核 - -- **[轻量系统内核](轻量系统内核.md)** - -- **[小型系统内核](小型系统内核.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" "b/zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" deleted file mode 100644 index 290c4915bf94adb34bc2804d40268adcfe38fd87..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\275\273\351\207\217\347\263\273\347\273\237\345\206\205\346\240\270.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 轻量系统内核 - -- **[基础内核](基础内核.md)** - -- **[文件系统](文件系统.md)** - -- **[标准库](标准库.md)** - -- **[调测](调测.md)** - - diff --git "a/zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" "b/zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" deleted file mode 100755 index c425b175ae513cd01fbb8a5c4cbf17dca6351e1d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\350\277\233\347\250\213.md" +++ /dev/null @@ -1,301 +0,0 @@ -# 进程 - -- [基本概念](#section29197338383) -- [使用场景](#section85513272398) -- [接口说明](#section4517119124015) - -## 基本概念 - -从系统的角度看,进程是资源管理单元。进程可以使用或等待CPU、使用内存空间等系统资源,并独立于其它进程运行。 - -OpenHarmony内核的进程模块可以给用户提供多个进程,实现了进程之间的切换和通信,帮助用户管理业务程序流程。这样用户可以将更多的精力投入到业务功能的实现中。 - -OpenHarmony内核中的进程采用抢占式调度机制,支持时间片轮转调度方式。 - -OpenHarmony内核的进程一共有32个优先级\(0-31\),用户进程可配置的优先级有22个\(10-31\),最高优先级为10,最低优先级为31。 - -高优先级的进程可抢占低优先级进程,低优先级进程必须在高优先级进程阻塞或结束后才能得到调度。 - -每一个用户态进程均拥有自己独立的进程空间,相互之间不可见,实现进程间隔离。 - -用户态根进程init由内核态创建,其它用户态进程均由init进程fork而来。 - -**进程状态说明:** - -- 初始化(Init):该进程正在被创建。 - -- 就绪(Ready):该进程在就绪列表中,等待CPU调度。 - -- 运行(Running):该进程正在运行。 - -- 阻塞(Pending):该进程被阻塞挂起。本进程内所有的线程均被阻塞时,进程被阻塞挂起。 - -- 僵尸态(Zombies):该进程运行结束,等待父进程回收其控制块资源。 - - -**图 1** 进程状态迁移示意图 -![](figures/进程状态迁移示意图.png "进程状态迁移示意图") - -**进程状态迁移说明:** - -- Init→Ready: - - 进程创建或fork时,拿到该进程控制块后进入Init状态,处于进程初始化阶段,当进程初始化完成将进程插入调度队列,此时进程进入就绪状态。 - -- Ready→Running: - - 进程创建后进入就绪态,发生进程切换时,就绪列表中最高优先级的进程被执行,从而进入运行态。若此时该进程中已无其它线程处于就绪态,则该进程从就绪列表删除,只处于运行态;若此时该进程中还有其它线程处于就绪态,则该进程依旧在就绪队列,此时进程的就绪态和运行态共存。 - -- Running→Pending: - - 进程内所有的线程均处于阻塞态时,进程在最后一个线程转为阻塞态时,同步进入阻塞态,然后发生进程切换。 - -- Pending→Ready: - - 阻塞进程内的任意线程恢复就绪态时,进程被加入到就绪队列,同步转为就绪态。 - -- Ready→Pending: - - 进程内的最后一个就绪态线程处于阻塞态时,进程从就绪列表中删除,进程由就绪态转为阻塞态。 - -- Running→Ready: - - 进程由运行态转为就绪态的情况有以下两种: - - 1. 有更高优先级的进程创建或者恢复后,会发生进程调度,此刻就绪列表中最高优先级进程变为运行态,那么原先运行的进程由运行态变为就绪态。 - 2. 若进程的调度策略为SCHED\_RR,且存在同一优先级的另一个进程处于就绪态,则该进程的时间片消耗光之后,该进程由运行态转为就绪态,另一个同优先级的进程由就绪态转为运行态。 - -- Running→Zombies: - - 当进程的主线程或所有线程运行结束后,进程由运行态转为僵尸态,等待父进程回收资源。 - - -## 使用场景 - -进程创建后,用户只能操作自己进程空间的资源,无法操作其它进程的资源(共享资源除外)。 用户态允许进程挂起,恢复,延时等操作,同时也可以设置用户态进程调度优先级和调度策略,获取进程调度优先级和调度策略。进程结束的时候,进程会主动释放持有的进程资源,但持有的进程pid资源需要父进程通过wait/waitpid或父进程退出时回收。 - -## 接口说明 - -OpenHarmony内核系统中的进程管理模块为用户提供下面几种功能: - -**表 1** 进程管理模块功能 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

备注

-

进程

-

fork

-

创建一个新进程。

-

-

-

exit

-

终止进程。

-

-

-

atexit

-

注册正常进程终止的回调函数。

-

-

-

abort

-

中止进程执行。

-

-

-

getpid

-

获取进程ID。

-

-

-

getppid

-

获取父进程ID。

-

-

-

getpgrp

-

获取调用进程的进程组ID。

-

-

-

getpgid

-

获取进程的进程组ID。

-

-

-

setpgrp

-

设置调用进程的进程组ID。

-

-

-

setpgid

-

设置进程的进程组ID。

-

-

-

kill

-

给进程发送信号。

-
  • 仅支持1-30号信号的发送。
  • 信号的默认行为不支持STOP及CONTINUE,无COREDUMP功能。
  • 不能屏蔽SIGSTOP、SIGKILL、SIGCONT。
  • 异步信号,发送信号给某进程后,直到该进程被调度后才会执行信号回调(为安全起见,杀死进程的动作是进程自己执行的,内核不能通过信号强制杀死对方)。
  • 进程消亡会发送SIGCHLD给父进程,发送动作无法取消。
  • 无法通过信号唤醒正在睡眠的进程。
-

wait

-

等待任意子进程结束并回收子进程资源。

-

status的值可以由以下宏定义解析:

-
  • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
  • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
  • WTERMSIG(status) 仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
  • 不支持的操作: WIFSTOPPED、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
-

waitpid

-

等待子进程结束并回收子进程资源。

-

options:不支持WUNTRACED,WCONTINUED;

-

status的值可以由以下宏定义解析:

-
  • WIFEXITED(status):如果子进程正常结束,它就返回真;否则返回假。
  • WEXITSTATUS(status):如果WIFEXITED(status)为真,则可以用该宏取得子进程exit()返回的退出码。
  • WTERMSIG(status)仅支持以下情况:子进程触发异常结束后通过WTERMSIG获取的进程退出编号始终为SIGUSR2。
  • 不支持:WIFSTOPPED 、WSTOPSIG、WCOREDUMP 、WIFCONTINUED。
-

调度

-

getpriority

-

获取指定ID的静态优先级。

-
  • 不支持:PRIO_PGRP、PRIO_USER。
-
  • 无动态优先级概念,用于设置静态优先级。
-

setpriority

-

设置指定ID的静态优先级。

-

sched_rr_get_interval

-

获取执行时间限制。

-

-

-

sched_yield

-

系统调用运行进程主动让出执行权。

-

-

-

sched_get_priority_max

-

获取进程静态优先级取值范围的最大值。

-

调度策略只支持:SCHED_RR。

-

sched_get_priority_min

-

获取进程静态优先级取值范围的最小值。

-

sched_getscheduler

-

获取调度策略。

-

sched_setscheduler

-

设置调度策略。

-

sched_getparam

-

获取调度参数。

-

-

-

sched_setparam

-

设置调度参数。

-

-

-

exec

-

execl

-

执行指定的elf格式的用户程序文件。

-

-

-

execle

-

执行指定的elf格式的用户程序文件。

-

-

-

execlp

-

执行指定的elf格式的用户程序文件。

-

-

-

execv

-

执行指定的elf格式的用户程序文件。

-

-

-

execve

-

执行指定的elf格式的用户程序文件。

-

-

-

execvp

-

执行指定的elf格式的用户程序文件。

-

-

-
- diff --git "a/zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" "b/zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" deleted file mode 100644 index 73adc5ca617dfb9d657241bd0ba43d4afd5c5cbc..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\351\231\204\345\275\225.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 附录 - -- **[内核编码规范](内核编码规范.md)** - -- **[基本数据结构](基本数据结构.md)** - -- **[标准库支持](标准库支持.md)** - - diff --git "a/zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" "b/zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" deleted file mode 100644 index 090cea4a0d0b7ec7188f2836b0014de6b5e0bdab..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\351\235\231\346\200\201\345\206\205\345\255\230.md" +++ /dev/null @@ -1,182 +0,0 @@ -# 静态内存 - -- [运行机制](#section165473517522) -- [开发指导](#section57511620165218) - - [使用场景](#section215474911529) - - [接口说明](#section79231214539) - - [开发流程](#section1388511316548) - - [编程实例](#section17801515105519) - - [结果验证](#section11818154112319) - - -## 运行机制 - -静态内存实质上是一个静态数组,静态内存池内的块大小在初始化时设定,初始化后块大小不可变更。 - -静态内存池由一个控制块LOS\_MEMBOX\_INFO和若干相同大小的内存块LOS\_MEMBOX\_NODE构成。控制块位于内存池头部,用于内存块管理,包含内存块大小uwBlkSize,内存块数量uwBlkNum,已分配使用的内存块数量uwBlkCnt和空闲内存块链表stFreeList。内存块的申请和释放以块大小为粒度,每个内存块包含指向下一个内存块的指针pstNext。 - -**图 1** 静态内存示意图 -![](figures/静态内存示意图.png "静态内存示意图") - -## 开发指导 - -### 使用场景 - -当用户需要使用固定长度的内存时,可以通过静态内存分配的方式获取内存,一旦使用完毕,通过静态内存释放函数归还所占用内存,使之可以重复使用。 - -### 接口说明 - -OpenHarmony LiteOS-M的静态内存管理主要为用户提供以下功能,接口详细信息可以查看API参考。 - -**表 1** 静态内存模块接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

功能分类

-

接口名

-

描述

-

初始化静态内存池

-

LOS_MemboxInit

-

初始化一个静态内存池,根据入参设定其起始地址、总大小及每个内存块大小。

-

清除静态内存块内容

-

LOS_MemboxClr

-

清零从静态内存池中申请的静态内存块的内容。

-

申请、释放静态内存

-

LOS_MemboxAlloc

-

从指定的静态内存池中申请一块静态内存块。

-

LOS_MemboxFree

-

释放从静态内存池中申请的一块静态内存块。

-

获取、打印静态内存池信息

-

LOS_MemboxStatisticsGet

-

获取指定静态内存池的信息,包括内存池中总内存块数量、已经分配出去的内存块数量、每个内存块的大小。

-

LOS_ShowBox

-

打印指定静态内存池所有节点信息(打印等级是LOS_INFO_LEVEL),包括内存池起始地址、内存块大小、总内存块数量、每个空闲内存块的起始地址、所有内存块的起始地址。

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->初始化后的内存池的内存块数量,不等于总大小除于内存块大小,因为内存池的控制块和每个内存块的控制头,都存在内存开销,设置总大小时,需要将这些因素考虑进去。 - -### 开发流程 - -本节介绍使用静态内存的典型场景开发流程。 - -1. 规划一片内存区域作为静态内存池。 -2. 调用LOS\_MemboxInit初始化静态内存池。 - - 初始化会将入参指定的内存区域分割为N块(N值取决于静态内存总大小和块大小),将所有内存块挂到空闲链表,在内存起始处放置控制头。 - -3. 调用LOS\_MemboxAlloc接口分配静态内存。 - - 系统将会从空闲链表中获取第一个空闲块,并返回该内存块的起始地址。 - -4. 调用LOS\_MemboxClr接口。 - - 将入参地址对应的内存块清零。 - -5. 调用LOS\_MemboxFree接口。 - - 将该内存块加入空闲链表。 - - -### 编程实例 - -本实例执行以下步骤: - -1. 初始化一个静态内存池。 -2. 从静态内存池中申请一块静态内存。 -3. 在内存块存放一个数据。 -4. 打印出内存块中的数据。 -5. 清除内存块中的数据。 -6. 释放该内存块。 - - 示例代码如下: - - -``` -#include "los_membox.h" - -VOID Example_StaticMem(VOID) -{ - UINT32 *mem = NULL; - UINT32 blkSize = 10; - UINT32 boxSize = 100; - UINT32 boxMem[1000]; - UINT32 ret; - - /*内存池初始化*/ - ret = LOS_MemboxInit(&boxMem[0], boxSize, blkSize); - if(ret != LOS_OK) { - printf("Membox init failed!\n"); - return; - } else { - printf("Membox init success!\n"); - } - - /*申请内存块*/ - mem = (UINT32 *)LOS_MemboxAlloc(boxMem); - if (NULL == mem) { - printf("Mem alloc failed!\n"); - return; - } - printf("Mem alloc success!\n"); - - /*赋值*/ - *mem = 828; - printf("*mem = %d\n", *mem); - - /*清除内存内容*/ - LOS_MemboxClr(boxMem, mem); - printf("Mem clear success \n *mem = %d\n", *mem); - - /*释放内存*/ - ret = LOS_MemboxFree(boxMem, mem); - if (LOS_OK == ret) { - printf("Mem free success!\n"); - } else { - printf("Mem free failed!\n"); - } - - return; -} -``` - -### 结果验证 - -输出结果如下: - -``` -Membox init success! -Mem alloc success! -*mem = 828 -Mem clear success -*mem = 0 -Mem free success! -``` - diff --git "a/zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" "b/zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" deleted file mode 100755 index 9bd18a8340d5f63817550f51f09b9cbae5dc6caf..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/kernel/\351\255\224\346\263\225\351\224\256\344\275\277\347\224\250\346\226\271\346\263\225.md" +++ /dev/null @@ -1,38 +0,0 @@ -# 魔法键使用方法 - -- [使用场景](#section2350114718546) -- [使用方法](#section3305151511559) - -## 使用场景 - -在系统运行出现无响应等情况时,可以通过魔法键功能确定系统是否被锁中断(魔法键也无响应)或者查看系统任务运行状态等信息。 - -在中断有响应的情况下,可以通过魔法键查看task信息中 cpup(CPU占用率)看是哪个任务长时间占用CPU导致系统其他任务无响应(一般为比较高优先级任务一直抢占CPU,导致低优先级任务无响应)。 - -## 使用方法 - -1. 配置宏LOSCFG\_ENABLE\_MAGICKEY。 - -魔法键依赖于宏LOSCFG\_ENABLE\_MAGICKEY,使用时通过menuconfig在配置项中开启“Enable MAGIC KEY”: - -Debug ---\> Enable MAGIC KEY;若关闭该选项,则魔法键失效。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->1. 可以在menuconfig中,将光标移动到LOSCFG\_ENABLE\_MAGICKEY上,输入“?”,查看帮助信息。 - -2. 输入“ctrl + r”键,打开魔法键检测功能。 - -在连接UART或者USB转虚拟串口的情况下,输入“ctrl + r” 键,打开魔法键检测功能,输出 “Magic key on”;再输入一次后,则关闭魔法键检测功能,输出“Magic key off”。魔法键功能如下: - -- ctrl + z:帮助键,输出相关魔法键简单介绍; - -- ctrl + t:输出任务相关信息; - -- ctrl + p:系统主动进入panic,输出panic相关信息后,系统会挂住; - -- ctrl + e:系统进行简单完整性内存池检查,检查出错会输出相关错误信息,检查正常会输出“system memcheck over, all passed!”。 - - ->![](public_sys-resources/icon-notice.gif) **须知:** ->魔法键检测功能打开情况下,如果需要通过UART或者USB转虚拟串口输入特殊字符需避免与魔法键值重复,否则魔法键会被误触发,而原有设计功能可能出现错误。 - diff --git "a/zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" deleted file mode 100755 index bb7404eca3e670115c48f40f4f219347162c5064..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/CMake\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" +++ /dev/null @@ -1,435 +0,0 @@ -# CMake方式组织编译的库移植 - -- [源码获取](#section1771132116245) -- [移植思路](#section9737174410328) -- [交叉编译](#section38205577332) - - [编译参考](#section1088111263418) - - [设置执行交叉编译](#section8168182883515) - -- [测试](#section6686144293611) -- [将该库编译添加到OpenHarmony工程中](#section1651053153715) - -以double-conversion库为例,其移植过程如下文所示 - -## 源码获取 - -从仓库[获取double-conversion源码](https://github.com/google/double-conversion),其目录结构如下表: - -**表 1** 源码目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

double-conversion/cmake/

-

CMake组织编译使用到的模板

-

double-conversion/double-conversion/

-

源文件目录

-

double-conversion/msvc/

-

-

-

double-conversion/test/

-

测试用例源文件

-

double-conversion/.gitignore

-

-

-

double-conversion/AUTHORS

-

-

-

double-conversion/BUILD

-

-

-

double-conversion/CMakeLists.txt

-

CMake方式顶层编译组织文件

-

double-conversion/COPYING

-

-

-

double-conversion/Changelog

-

-

-

double-conversion/LICENSE

-

-

-

double-conversion/Makefile

-

-

-

double-conversion/README.md

-

-

-

double-conversion/SConstruct

-

-

-

double-conversion/WORKSPACE

-

-

-
- -## 移植思路 - -移植思路:通过修改工具链,交叉编译该三方库,生成OpenHarmony平台的可执行文件,最后再通过GN调用CMake的方式添加到OpenHarmony工程中。 - -## 交叉编译 - -### 编译参考 - -代码仓库的[README.md](https://github.com/google/double-conversion/blob/master/README.md)中详细介绍了使用CMake编译double-conversion库的步骤,以及测试方法。本文参考该指导设置该库的编译配置,并完成测试。若开发人员在移植过程中对该库的编译选项配置有疑惑的地方,可参考该指导。对于其他使用CMake可独立编译的三方库,在移植时可以参考其自带的编译指导。 - -### 设置执行交叉编译 - -CMake方式可通过指定工具链进行交叉编译,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: - -1. 设置工具链 - - 将下列clang工具链配置添加到该工程的顶层CMakeLists.txt(即[表1中的该文件](#table824211132418))中即可。 - - ``` - set(CMAKE_CROSSCOMPILING TRUE) - set(CMAKE_SYSTEM_NAME Generic) - set(CMAKE_CXX_COMPILER_ID Clang) - set(CMAKE_TOOLCHAIN_PREFIX llvm-) - #指定c编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,使用clang编译时标志中必须指定--target,否则无法交叉编译。 - set(CMAKE_C_COMPILER clang) - set(CMAKE_C_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") - #指定c++编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,必须指定--target,否则无法交叉编译。 - set(CMAKE_CXX_COMPILER clang++) - set(CMAKE_CXX_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") - #指定链接工具和链接标志,必须指定--target和--sysroot,其中OHOS_ROOT_PATH可通过cmake命令后缀参数来指定。 - set(MY_LINK_FLAGS "--target=arm-liteos --sysroot=${OHOS_SYSROOT_PATH}") - set(CMAKE_LINKER clang) - set(CMAKE_CXX_LINKER clang++) - set(CMAKE_C_LINKER clang) - set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINKER} - ${MY_LINK_FLAGS} -o ") - set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINKER} - ${MY_LINK_FLAGS} -o ") - #指定链接库的查找路径。 - set(CMAKE_SYSROOT ${OHOS_SYSROOT_PATH}) - ``` - -2. 执行编译 - - linux命令行中进入double-conversion的源文件目录(即[表1所示目录](#table824211132418)),执行下列命令: - - ``` - mkdir build && cd build - cmake .. -DBUILD_TESTING=ON -DOHOS_SYSROOT_PATH="..." - make -j - ``` - - 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot目录的位置,以OpenHarmony为例即目录openHarmony/prebuilts/lite/sysroot的绝对路径。 - -3. 查看结果 - - 步骤2操作完成后,build目录下会生成静态库文件和测试用例: - - **表 2** 编译生成文件目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

double-conversion/build/libdouble-conversion.a

-

生成的静态库文件

-

double-conversion/build/test/

-

目录下存放生成的测试用例和相关CMake缓存文件

-

double-conversion/build/CMakeCache.txt

-

CMake构建过程中的缓存文件

-

double-conversion/build/CMakeFiles/

-

-

-

double-conversion/build/cmake_install.cmake

-

-

-

double-conversion/build/CTestTestfile.cmake

-

-

-

double-conversion/build/DartConfiguration.tcl

-

-

-

double-conversion/build/generated/

-

-

-

double-conversion/build/Makefile

-

-

-

double-conversion/build/Testing/

-

-

-
- - -## 测试 - -1. 搭建OpenHarmony环境 - - 以hi3518ev300为例,编译出OpenHarmony镜像,烧写到开发板,参考[开发Hi3518第一个示例程序](https://device.harmonyos.com/cn/docs/start/introduce/oem_camera_start_example-0000001051610926)。 - - 进入系统如下所示: - - **图 1** OpenHarmony启动成功界面 - ![](figures/OpenHarmony启动成功界面.png "OpenHarmony启动成功界面") - -2. 挂载nfs目录,将[表2](#table1452412391911)中test目录下cctest可执行文件放入nfs目录 -3. 执行用例 - - 该库采用非交叉编译时用例是通过make test执行,CMake会有相关的执行结果统计;交叉编译时无法使用该方法,因此可直接执行生成的测试文件完成测试。 - - - 挂载成功后执行下列命令可列出用例所有条目: - - ``` - cd nfs - ./cctest --list - ``` - - 上述命令执行结果部分展示: - - ``` - test-bignum/Assign< - test-bignum/ShiftLeft< - test-bignum/AddUInt64< - test-bignum/AddBignum< - test-bignum/SubtractBignum< - test-bignum/MultiplyUInt32< - test-bignum/MultiplyUInt64< - test-bignum/MultiplyPowerOfTen< - test-bignum/DivideModuloIntBignum< - test-bignum/Compare< - test-bignum/PlusCompare< - test-bignum/Square< - test-bignum/AssignPowerUInt16< - test-bignum-dtoa/BignumDtoaVariousDoubles< - test-bignum-dtoa/BignumDtoaShortestVariousFloats< - test-bignum-dtoa/BignumDtoaGayShortest< - test-bignum-dtoa/BignumDtoaGayShortestSingle< - test-bignum-dtoa/BignumDtoaGayFixed< - test-bignum-dtoa/BignumDtoaGayPrecision< - test-conversions/DoubleToShortest< - test-conversions/DoubleToShortestSingle< - ... - ``` - - - 以test-bignum条目为例,执行下列命令开始测试: - - ``` - ./cctest test-bignum - ``` - - 测试结果如下则表示通过: - - ``` - Ran 13 tests. - ``` - - -## 将该库编译添加到OpenHarmony工程中 - -1. 复制库到OpenHarmony工程中 - - 拷贝已经能够成功交叉编译的库到OpenHarmony的third\_party目录,为了不修改要移植的三方库目录下的BUILD.gn文件,再添加一层目录放置新增的gn转CMake编译适配文件,新增的文件有BUILD.gn、build\_thirdparty.py、 config.gni,新增后的目录结构如下所示。 - - **表 3** 添加到工程后的目录结构 - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/double-conversion/BUILD.gn

-

将三方库加入工程的gn适配文件

-

openHarmony/third_party/double-conversion/build_thirdpaty.py

-

GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转CMake

-

openHarmony/third_party/double-conversion/config.gni

-

三方库编译配置文件,可修改该文件来配置用例是否参与构建等

-

openHarmony/third_party/double-conversion/double-conversion/

-

要移植的三方库目录

-
- -2. 添加gn到CMake适配文件 - - - **新增的BUILD.gn文件实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony平台时只需修改路径即可**。 - - ``` - import("config.gni") - group("double-conversion") { - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - deps = [":make"] - } - } - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - action("make") { - script = "//third_party/double-conversion/build_thirdparty.py" - outputs = ["$root_out_dir/log_dc.txt"] - exec_path = rebase_path(rebase_path("./build", ohos_third_party_dir)) - command = "rm * .* -rf && $CMAKE_TOOLS_PATH/cmake .. $CMAKE_FLAG $CMAKE_TOOLCHAIN_FLAG && make -j" - args = [ - "--path=$exec_path", - "--command=${command}" - ] - } - } - ``` - - - **新增的config.gni用于配置该库,实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时只需修改CMAKE\_FLAG的配置即可。** - - ``` - #CMAKE_FLAG: config compile feature - CMAKE_FLAG = "-DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=11" - - #toolchain:follow up-layer,depend on $ohos_build_compiler - if (ohos_build_compiler == "clang") { - CMAKE_TOOLCHAIN_FLAG = "-DOHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" - } else { - CMAKE_TOOLCHAIN_FLAG = "" - } - - #CMake tools path,no need setting if this path already joined to $PATH. - CMAKE_TOOLS_PATH = "setting CMake tools path..." - ``` - - - **新增的build\_thirdparty.py实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时无需修改即可使用。** - - ``` - import os - import sys - from subprocess import Popen - import argparse - import shlex - - def cmd_exec(command): - cmd = shlex.split(command) - proc = Popen(cmd) - proc.wait() - ret_code = proc.returncode - if ret_code != 0: - raise Exception("{} failed, return code is {}".format(cmd, ret_code)) - - def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--path', help='Build path.') - parser.add_argument('--command', help='Build command.') - parser.add_argument('--enable', help='enable python.', nargs='*') - args = parser.parse_args() - - if args.enable: - if args.enable[0] == 'false': - return - - if args.path: - curr_dir = os.getcwd() - os.chdir(args.path) - if args.command: - if '&&' in args.command: - command = args.command.split('&&') - for data in command: - cmd_exec(data) - else: - cmd_exec(args.command) - os.chdir(curr_dir) - - if __name__ == '__main__': - sys.exit(main()) - ``` - - - 在配置文件中添加开关控制该库编译,默认设为关闭 - - 在//build/lite/ohos\_var.gni文件中添加下列配置: - - ``` - declare_args() { - ohos_build_thirdparty_migrated_from_fuchisa = true - } - ``` - -3. 编译构建 - - - 手动单独构建: - - 执行下列命令 - - ``` - hb build -T //third_party/double-conversion:double-conversion - ``` - - 编译成功则[build](#li15717101715249)目录下会生成静态库文件和测试用例 - - diff --git "a/zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" deleted file mode 100755 index a2a6a92ee5a1723f8e5981139bc642a67e7ab9e0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/Makefile\346\226\271\345\274\217\347\273\204\347\273\207\347\274\226\350\257\221\347\232\204\345\272\223\347\247\273\346\244\215.md" +++ /dev/null @@ -1,309 +0,0 @@ -# Makefile方式组织编译的库移植 - -- [源码获取](#section114115321416) -- [设置交叉编译](#section81263255384) -- [测试](#section1830015913391) -- [将该库编译添加到OpenHarmony工程中](#section1898016213406) - -以yxml库为例,其移植过程如下文所示 - -## 源码获取 - -从仓库[获取yxml源码](https://github.com/getdnsapi/yxml),其目录结构如下表: - -**表 1** 源码目录结构 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

yxml/bench/

-

benchmark相关代码

-

yxml/test/

-

测试输入输出文件,及测试脚本

-

yxml/Makefile

-

编译组织文件

-

yxml/.gitattributes

-

-

-

yxml/.gitignore

-

-

-

yxml/COPYING

-

-

-

yxml/yxml.c

-

-

-

yxml/yxml.c.in

-

-

-

yxml/yxml-gen.pl

-

-

-

yxml/yxml.h

-

-

-

yxml/yxml.md

-

-

-

yxml/yxml-states

-

-

-
- -## 设置交叉编译 - -设置Makefile的交叉编译工具链,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: - -1. 设置工具链 - - 将下列clang工具链配置替换掉yxml库根目录的MakeFile(即[表1中的文件](#table16520154171813))中的原有配置。 - - clang工具链配置 - - ``` - #设置交叉编译工具链,确保工具链所在路径已经添加到了PATH环境变量中 - CC:=clang - AR:=llvm-ar - #cflags中必须要添加--target及--sysroot选项 - CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g --target=arm-liteos -march=armv7-a --sysroot=$(OHOS_ROOT_PATH)prebuilts/lite/sysroot - ``` - - 原有配置 - - ``` - CC:=gcc - AR:=ar - CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g - ``` - -2. 执行编译 - - linux命令行中进入yxml的源文件目录(即图1所示目录),执行下列命令: - - ``` - make test OHOS_SYSROOT_PATH=... - ``` - - 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot所在目录,以OpenHarmony为例即源码根目录prebuilts/lite/sysroot/所在的绝对路径。 - -3. 查看结果 - - 步骤2操作完成后,yxml下会生成out目录,里面有静态库文件和测试用例: - - **表 2** yxml编译生成目录 - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/yxml/yxml/out/lib/

-

编译生成的静态库的存放目录

-

openHarmony/third_party/yxml/yxml/out/test/

-

编译生成的测试用例及其输入输出等文件的存放目录

-
- - -## 测试 - -yxml库测试步骤与double-conversion库基本一致,可参考[CMake方式组织编译的库移植](CMake方式组织编译的库移植.md#section6686144293611)的测试过程,以下内容介绍yxml库测试用例的使用方法: - -**表 3** 生成的test目录结构示意 - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/yxml/yxml/out/test/test.sh

-

自动化测试脚本,由于OpenHarmony不支持脚本运行,因此无法使用,可参考其内容手动测试

-

openHarmony/third_party/yxml/yxml/out/test/test

-

用于测试的可执行文件

-

openHarmony/third_party/yxml/yxml/out/test/*.xml

-

测试输入文件

-

openHarmony/third_party/yxml/yxml/out/test/*.out

-

期望的输出文件

-
- -test.sh内容如下所示: - -``` -#!/bin/sh -for i in *.xml; do - b=`basename $i .xml` - o=${b}.out - t=${b}.test - ./test <$i >$t - if [ -n "`diff -q $o $t`" ]; then - echo "Test failed for $i:" - diff -u $o $t - exit 1 - fi -done -echo "All tests completed successfully." -``` - -由于OpenHarmony的shell中暂不支持输入输出重定向(<和\>),所以测试时需要将输入\*.xml文件内容直接复制进shell后回车,输出内容会直接展示在shell窗口。过程如下: - -下列操作假定已按照2.4节的步骤搭建OpenHarmony,挂载并进入nfs目录: - -1. 执行下列命令 - - ``` - ./test - ``` - -2. 复制\*.xml内容到shell - - 以[test目录](#table115941423164318)下pi01.xml为例,内容如下,输入到shell并回车: - - ``` - - ``` - -3. 比较shell中输出的内容与[test目录](#table115941423164318)中对应的\*.out文件是否一致 - - 输出结果如下: - - ``` - pistart SomePI - picontent abc - piend - elemstart a - elemend - ok - ``` - - 经比较与[test目录](#table115941423164318)下pi01.out内容一致,测试通过。 - - -## 将该库编译添加到OpenHarmony工程中 - -yxml库添加的过程除了适配文件build.gn和config.gni有些许变化外,其他和double-conversion库完全一致,参考[CMake方式组织编译的库移植](CMake方式组织编译的库移植.md#section1651053153715)的配置过程。要修改的适配文件及添加后的目录结构如下: - -- yxml库新增的BUILD.gn实现如下: - -``` -import("config.gni") -group("yxml") { - if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - deps = [":make"] - } -} -if (ohos_build_thirdparty_migrated_from_fuchisa == true) { - action("make") { - script = "//third_party/yxml/build_thirdparty.py" - outputs = ["$target_out_dir/log_yxml.txt"] - exec_path = rebase_path(rebase_path("./yxml", root_build_dir)) - command = "make clean && $MAKE_COMMAND" - args = [ - "--path=$exec_path", - "--command=${command}" - ] - } -} -``` - -- yxml库新增的config.gni配置如下: - -``` -TEST_ENABLE = "YES" - -if (TEST_ENABLE == "YES") { - MAKE_COMMAND = "make test OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" -} else { - MAKE_COMMAND = "make OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" -} -``` - -- 添加完成后目录结构示意: - -**表 4** 添加到工程后的目录结构 - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

openHarmony/third_party/yxml/BUILD.gn

-

将三方库加入工程的gn适配文件

-

openHarmony/third_party/yxml/build_thirdpaty.py

-

GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转Makefile

-

openHarmony/third_party/yxml/config.gni

-

三方库编译配置文件,可修改该文件来配置用例是否参与构建等

-

openHarmony/third_party/yxml/yxml/

-

要移植的三方库目录

-
- diff --git a/zh-cn/device-dev/porting/Readme-CN.md b/zh-cn/device-dev/porting/Readme-CN.md index 0dca00c895f6172ce990465be705745d7b8965db..6e960a48da33c210b7a8ef4d658021e54649d986 100755 --- a/zh-cn/device-dev/porting/Readme-CN.md +++ b/zh-cn/device-dev/porting/Readme-CN.md @@ -1,27 +1,33 @@ # 移植指南 -- [三方库移植指导](三方库移植指导.md) - - [概述](概述.md) - - [CMake方式组织编译的库移植](CMake方式组织编译的库移植.md) - - [Makefile方式组织编译的库移植](Makefile方式组织编译的库移植.md) - -- [三方芯片移植指导](三方芯片移植指导.md) - - [移植准备](移植准备.md) - - [移植须知](移植须知.md) - - [编译构建适配流程](编译构建适配流程.md) - - - [内核移植](内核移植.md) - - [移植概述](移植概述.md) - - [内核基础适配](内核基础适配.md) - - [内核移植验证](内核移植验证.md) - - - [板级系统移植](板级系统移植.md) - - [移植概述](移植概述-0.md) - - [板级驱动适配](板级驱动适配.md) - - [HAL层实现](HAL层实现.md) - - [系统组件调用](系统组件调用.md) - - [三方组件适配](三方组件适配.md) - - [XTS认证](XTS认证.md) - - - [常见问题](常见问题.md) - +- [三方库移植指导](transplant-thirdparty.md) + - [概述](transplant-thirdparty-overview.md) + - [CMake方式组织编译的库移植](transplant-thirdparty-cmake.md) + - [Makefile方式组织编译的库移植](transplant-thirdparty-makefile.md) +- [轻量系统芯片移植指导](transplant-minichip.md) + - [移植准备](transplant-chip-prepare.md) + - [移植须知](transplant-chip-prepare-knows.md) + - [编译构建适配流程](transplant-chip-prepare-process.md) + - [内核移植](transplant-chip-kernel.md) + - [移植概述](transplant-chip-kernel-overview.md) + - [内核基础适配](transplant-chip-kernel-adjustment.md) + - [内核移植验证](transplant-chip-kernel-verify.md) + - [板级系统移植](transplant-chip-board.md) + - [移植概述](transplant-chip-board-overview.md) + - [板级驱动适配](transplant-chip-board-drive.md) + - [HAL层实现](transplant-chip-board-hal.md) + - [系统组件调用](transplant-chip-board-component.md) + - [三方组件适配](transplant-chip-board-bundle.md) + - [XTS认证](transplant-chip-board-xts.md) + - [常见问题](transplant-chip-faqs.md) +- [小型系统芯片移植指导](transplant-smallchip.md) + - [移植准备](transplant-smallchip-prepare.md) + - [移植须知](transplant-smallchip-prepare-needs.md) + - [编译构建](transplant-smallchip-prepare-building.md) + - [移植内核](transplant-smallchip-kernel.md) + - [LiteOS-A内核](transplant-smallchip-kernel-a.md) + - [Linux内核](transplant-smallchip-kernel-linux.md) + - [驱动移植](transplant-smallchip-drive.md) + - [移植概述](transplant-smallchip-drive-des.md) + - [平台驱动移植](transplant-smallchip-drive-plat.md) + - [器件驱动移植](transplant-smallchip-drive-oom.md) \ No newline at end of file diff --git "a/zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" "b/zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" deleted file mode 100755 index 44b37d014423043bd25028ce5739076d44ac2e72..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/XTS\350\256\244\350\257\201.md" +++ /dev/null @@ -1,65 +0,0 @@ -# XTS认证 - -- [XTS简介](#section6725155811454) - - [将XTS认证子系统加入编译组件中](#section46981118105417) - - [执行联接类模组acts测试用例](#section9489122319819) - - -## XTS简介 - -XTS是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套。test/xts仓当前包括acts与tools软件包: - -- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -- tools,存放acts相关测试用例开发框架。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->XTS的启动依赖SAMGR系统服务。 - -适配分为两步,包括: - -1. 将XTS认证子系统加入编译组件中。 -2. 执行联接类模组acts测试用例。 - -### 将XTS认证子系统加入编译组件中 - -举例:将XTS认证子系统加入hispark\_aries产品编译组件中为例。 - -1. 在vendor/hisilicon/hispark\_aries/config.json中加入XTS认证子系统定义: - - ``` - { - "subsystem": "test", - "components": [ - { "component": "xts_acts", "features":[] }, - { "component": "xts_tools", "features":[] } - ] - }, - ``` - -2. Debug版本才会触发XTS认证子系统编译; - -### 执行联接类模组acts测试用例 - -举例:以hispark\_aries产品执行联接类模组acts测试用例为例。 - -1. 获取编译镜像。 - - 请在如下目录获取版本镜像:out/hispark\_pegasus/wifiiot\_hispark\_pegasus/。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >判断当前版本镜像是否集成acts测试套件方法:在map文件中查看对应.a是否被编译即可。 - -2. 版本镜像烧录进开发板。 -3. 测试步骤。 - - (1)使用串口工具登录开发板,并保存串口打印信息。 - - (2)重启设备,查看串口日志。 - -4. 测试结果分析指导。 - - (1)基于串口打印日志进行分析; - - (2)每个测试套件执行以“Start to run test suite”开始,以“xx Tests xx Failures xx Ignored”结束。 - - diff --git a/zh-cn/device-dev/porting/figure/HDF_WIFI.png b/zh-cn/device-dev/porting/figure/HDF_WIFI.png new file mode 100644 index 0000000000000000000000000000000000000000..56e6ab3aee9a539c76afd3edac98f21bff0766d5 Binary files /dev/null and b/zh-cn/device-dev/porting/figure/HDF_WIFI.png differ diff --git "a/zh-cn/device-dev/porting/figures/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" "b/zh-cn/device-dev/porting/figure/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figures/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" rename to "zh-cn/device-dev/porting/figure/OpenHarmony\345\220\257\345\212\250\346\210\220\345\212\237\347\225\214\351\235\242.png" diff --git a/zh-cn/device-dev/porting/figure/init.jpg b/zh-cn/device-dev/porting/figure/init.jpg new file mode 100644 index 0000000000000000000000000000000000000000..a1e7f8b695bebf395ea6cfa0aed55495c4896118 Binary files /dev/null and b/zh-cn/device-dev/porting/figure/init.jpg differ diff --git a/zh-cn/device-dev/porting/figure/shell.jpg b/zh-cn/device-dev/porting/figure/shell.jpg new file mode 100644 index 0000000000000000000000000000000000000000..efb1e17b00d37b072a3032678144984e2e13b2d6 Binary files /dev/null and b/zh-cn/device-dev/porting/figure/shell.jpg differ diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001072304191.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001072304191.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/porting/figures/zh-cn_image_0000001072304191.png rename to zh-cn/device-dev/porting/figure/zh-cn_image_0000001072304191.png diff --git a/zh-cn/device-dev/porting/figures/zh-cn_image_0000001073943511.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001073943511.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/porting/figures/zh-cn_image_0000001073943511.png rename to zh-cn/device-dev/porting/figure/zh-cn_image_0000001073943511.png diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126198996.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126198996.png new file mode 100644 index 0000000000000000000000000000000000000000..cbc70a899f77382e9e052c30f2a69b61764d2643 Binary files /dev/null and b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126198996.png differ diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126354076.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126354076.png new file mode 100644 index 0000000000000000000000000000000000000000..b241920b30fea1b2a432f6ba01045bbfbae7fb58 Binary files /dev/null and b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126354076.png differ diff --git a/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126358814.png b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126358814.png new file mode 100644 index 0000000000000000000000000000000000000000..39c6cb96611a7ced5e17bbeee96ac77ba5c1bf58 Binary files /dev/null and b/zh-cn/device-dev/porting/figure/zh-cn_image_0000001126358814.png differ diff --git "a/zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" "b/zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" new file mode 100644 index 0000000000000000000000000000000000000000..dd8e1c235633c3e42fcd1360b66b3ce3452db02d Binary files /dev/null and "b/zh-cn/device-dev/porting/figure/\345\206\205\346\240\270\345\220\257\345\212\250\346\241\206\346\236\266.jpg" differ diff --git "a/zh-cn/device-dev/porting/figure/\345\210\206\347\261\273.png" "b/zh-cn/device-dev/porting/figure/\345\210\206\347\261\273.png" new file mode 100644 index 0000000000000000000000000000000000000000..7edac54ec2fcd1fc93330d47acb2d44fceef2710 Binary files /dev/null and "b/zh-cn/device-dev/porting/figure/\345\210\206\347\261\273.png" differ diff --git "a/zh-cn/device-dev/porting/figures/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" "b/zh-cn/device-dev/porting/figure/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figures/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" rename to "zh-cn/device-dev/porting/figure/\345\215\225\346\235\277\351\251\261\345\212\250\351\200\202\351\205\215\346\265\201\347\250\213.png" diff --git "a/zh-cn/device-dev/porting/figures/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" "b/zh-cn/device-dev/porting/figure/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/figures/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" rename to "zh-cn/device-dev/porting/figure/\350\212\257\347\211\207\347\247\273\346\244\215\345\205\263\351\224\256\346\255\245\351\252\244.png" diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/porting/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/porting/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/porting/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/porting/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/porting/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/porting/public_sys-resources/icon-warning.gif and /dev/null differ diff --git a/zh-cn/device-dev/porting/transplant-chip-board-bundle.md b/zh-cn/device-dev/porting/transplant-chip-board-bundle.md new file mode 100644 index 0000000000000000000000000000000000000000..8e235f7c54dd67da05510aa4f0e80a4e71e2c183 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-bundle.md @@ -0,0 +1,57 @@ +# 三方组件适配 + +如果需要使用third\_party目录下与产品相关的三方组件,可能需要对三方组件进行适配,下面以比较常用的mbedtls为例,介绍下适配步骤,注意本小节中仅介绍如何将适配的代码与OpenHarmony的编译框架融合,不会详细介绍mbedtls本身的原理和适配代码的具体逻辑,这些内容请参考mbedtls官方网站上的适配指南。 + +1. 编写适配层代码 + + 根据mbedtls官网的适配指南,编写需要的适配层代码,以适配硬件随机数举例,下面的路径都是相对third\_party/mbedtls的路径: + + 1. 拷贝include/mbedtls/config.h到ports目录下,并修改打开MBEDTLS\_ENTROPY\_HARDWARE\_ALT开关。 + 2. 在ports目录下创建entropy\_poll\_alt.c文件include并实现entropy\_poll.h中的硬件随机数接口 + 3. 在BUILD.gn中的mbedtls\_sources中增加刚才适配的entropy\_poll\_alt.c的路径 + 4. 在BIULD.gn中的lite\_library\("mbedtls\_static"\)中增加一行MBEDTLS\_CONFIG\_FILE指定新配置文件的位置 + + ``` + lite_library("mbedtks_static") { + ... + defines += ["MBEDTLS_CONFIG_FILE=<../port/config.h>"] + ... + } + ``` + + + 注意,上面的修改最好都新建一个config或者新建一个xxx\_alt.c文件来修改,不要直接在原先的代码中修改,侵入式的修改会导致后续版本升级出现大量零散冲突,增加升级维护成本。 + +2. 制作patch + + 由于上面的适配是硬件相关的,上库代码时,不能直接放到通用的third\_party/mbedtls目录中,因此需要将上面的修改制作成patch,在编译之前通过打patch的方式注入到代码中。 + + 1. 首先增加设备的patch配置文件device///patch.yml + 2. 编辑device///patch.yml,增加要打的patch的信息: + + ``` + # 需要打patch的路径,路径均为相对代码根目录的路径 + third_party/mbedtls: + # 该路径下需要打的patch存放路径 + - device///third_party/mbedtls/adapter.patch + third_party/wpa_supplicant: + # 当一个路径下有多个patch的时候会依次执行patch + - device///third_party/wpa_supplicant/xxxxx.patch + - device///third_party/wpa_supplicant/yyyyy.patch + ... + ``` + + 3. 制作上述**步骤1**修改的patch并放到对应的目录即可 + +3. 使用带patch的编译 + + 想要在编译的时候带上patch,其他步骤不变,仅需要在触发编译的时候加上 --patch,例如全编译的命令编程 + + ``` + hb build -f --patch + ``` + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >最后一次打patch的产品信息会被记录,在进行下一次编译操作时,会对上一次的patch进行回退(即执行\`patch -p1 -R < xxx\`),回退patch失败或新增patch失败均会终止编译过程,请解决patch冲突后再次尝试编译。 + + diff --git a/zh-cn/device-dev/porting/transplant-chip-board-component.md b/zh-cn/device-dev/porting/transplant-chip-board-component.md new file mode 100644 index 0000000000000000000000000000000000000000..618fc8acfa8f796b8582551e5756c9b40d1eb934 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-component.md @@ -0,0 +1,26 @@ +# 系统组件调用 + +- [SAMGR](#section105874301910) +- [DFX](#section20064420420) + +系统组件为上层应用提供基础能力,包括SAMGR(系统服务框架子系统)、DFX子系统等。在板级系统移植过程中,只需要选择使用即可,不用对其进行适配。 + +## SAMGR + +**基本介绍** + +系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本组件在板级系统移植中必须要使用,否则其他服务组件无法运行。 + +**SAMGR使用说明,请参考:[SAMGR 使用指导](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)** + +## DFX + +**基本介绍** + +DFX子系统主要包含DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性,为开发者提供代码维测信息。 + +**DFX子系统使用说明,请参考:[DFX子系统使用指导](../subsystems/subsys-dfx-overview.md)** + diff --git "a/zh-cn/device-dev/porting/\346\235\277\347\272\247\351\251\261\345\212\250\351\200\202\351\205\215.md" b/zh-cn/device-dev/porting/transplant-chip-board-drive.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\346\235\277\347\272\247\351\251\261\345\212\250\351\200\202\351\205\215.md" rename to zh-cn/device-dev/porting/transplant-chip-board-drive.md diff --git "a/zh-cn/device-dev/porting/HAL\345\261\202\345\256\236\347\216\260.md" b/zh-cn/device-dev/porting/transplant-chip-board-hal.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/HAL\345\261\202\345\256\236\347\216\260.md" rename to zh-cn/device-dev/porting/transplant-chip-board-hal.md diff --git a/zh-cn/device-dev/porting/transplant-chip-board-overview.md b/zh-cn/device-dev/porting/transplant-chip-board-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..732872af5b5e2558bf8b298f918872b2eec030b5 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-overview.md @@ -0,0 +1,57 @@ +# 移植概述 + +- [板级移植流程](#section1283115812294) +- [板级目录规范](#section6204129143013) + +## 板级移植流程 + +最小系统移植完成后,下一步进行板级系统移植,板级系统移植包含以下几步操作: + +1. 板级驱动适配。 +2. HAL层实现。 +3. XTS测试套。 +4. 业务功能验证。 + +**图 1** 单板驱动适配流程 +![](figure/单板驱动适配流程.png "单板驱动适配流程") + +## 板级目录规范 + +板级系统编译适配参考[编译系统介绍](transplant-chip-prepare-process.md),板级相关的驱动、SDK、目录、HAL实现存放在device目录,目录结构和具体描述如下: + +``` +. +├── device --- 单板样例 +│ └── xxx --- <单板厂商名> +│ └── xxx --- <单板名>,里面包含liteos-m内核的,并且能够运行的demo +│ ├── BUILD.gn --- 定义单板的编译配置文件 +│ ├── board --- 板子特定的实现(可选,如果本单板直接提供产品级demo,则相关应用层实现放在此目录) +│ ├── liteos_m --- 根据BUILD.gn文件中的kernel_type,使用liteos_m内核 +│ │ └── config.gni --- 编译选项 +│ ├── libraries --- 板级SDK +│ │ └── include --- SDK提供对外头文件 +│ │ └── ... --- binary or source +│ ├── main.c --- main函数入口(如果产品级存在相同定义,则使用产品级配置) +│ ├── target_config.h --- 板级内核配置 +│ ├── project --- 单板级工程配置文件(如果产品级存在相同定义,则使用产品级配置) +│ └── adapter --- 单板适配上层应用组件的适配层接口,根据能力可选 +│ └── hals +│ ├── communication +│ │ └── wifi_lite +│ │ ├── ... +│ └── iot_hardware +│ ├── upgrade +│ ├── utils +│ └── wifiiot_lite +├── vendor --- 提供端到端的OpenHarmony特性产品样例 +│ └── huawei --- 厂商名字 +│ └── wifiiot --- wifiiot表示特性产品 +│ ├── app +│ │ └── main.c --- 产品的main函数入口 +│ ├── project --- 工程配置文件 +│ ├── BUILD.gn --- 工程编译入口 +│ └── config.json --- 定义产品的编译配置文件,配置产品所使用的组件等。 +└── out --- 编译过程中的输出目录 + ├── ... --- 单板/产品编译产生的bin等 +``` + diff --git a/zh-cn/device-dev/porting/transplant-chip-board-xts.md b/zh-cn/device-dev/porting/transplant-chip-board-xts.md new file mode 100644 index 0000000000000000000000000000000000000000..00253685f7583381c9a5d89bd24a57bf2a7d3dcc --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board-xts.md @@ -0,0 +1,65 @@ +# XTS认证 + +- [XTS简介](#section6725155811454) + - [将XTS认证子系统加入编译组件中](#section46981118105417) + - [执行联接类模组acts测试用例](#section9489122319819) + + +## XTS简介 + +XTS是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套。test/xts仓当前包括acts与tools软件包: + +- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 +- tools,存放acts相关测试用例开发框架。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>XTS的启动依赖SAMGR系统服务。 + +适配分为两步,包括: + +1. 将XTS认证子系统加入编译组件中。 +2. 执行联接类模组acts测试用例。 + +### 将XTS认证子系统加入编译组件中 + +举例:将XTS认证子系统加入hispark\_aries产品编译组件中为例。 + +1. 在vendor/hisilicon/hispark\_aries/config.json中加入XTS认证子系统定义: + + ``` + { + "subsystem": "test", + "components": [ + { "component": "xts_acts", "features":[] }, + { "component": "xts_tools", "features":[] } + ] + }, + ``` + +2. Debug版本才会触发XTS认证子系统编译; + +### 执行联接类模组acts测试用例 + +举例:以hispark\_aries产品执行联接类模组acts测试用例为例。 + +1. 获取编译镜像。 + + 请在如下目录获取版本镜像:out/hispark\_pegasus/wifiiot\_hispark\_pegasus/。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >判断当前版本镜像是否集成acts测试套件方法:在map文件中查看对应.a是否被编译即可。 + +2. 版本镜像烧录进开发板。 +3. 测试步骤。 + + (1)使用串口工具登录开发板,并保存串口打印信息。 + + (2)重启设备,查看串口日志。 + +4. 测试结果分析指导。 + + (1)基于串口打印日志进行分析; + + (2)每个测试套件执行以“Start to run test suite”开始,以“xx Tests xx Failures xx Ignored”结束。 + + diff --git a/zh-cn/device-dev/porting/transplant-chip-board.md b/zh-cn/device-dev/porting/transplant-chip-board.md new file mode 100644 index 0000000000000000000000000000000000000000..f5d7b754b53786192eec6ce7572833fa12329c8e --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-board.md @@ -0,0 +1,15 @@ +# 板级系统移植 + +- **[移植概述](transplant-chip-board-overview.md)** + +- **[板级驱动适配](transplant-chip-board-drive.md)** + +- **[HAL层实现](transplant-chip-board-hal.md)** + +- **[系统组件调用](transplant-chip-board-component.md)** + +- **[三方组件适配](transplant-chip-board-bundle.md)** + +- **[XTS认证](transplant-chip-board-xts.md)** + + diff --git "a/zh-cn/device-dev/porting/\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/porting/transplant-chip-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/porting/transplant-chip-faqs.md diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md b/zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md new file mode 100644 index 0000000000000000000000000000000000000000..40f82e0cd778cc360d659cba3363f5c94e560745 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel-adjustment.md @@ -0,0 +1,83 @@ +# 内核基础适配 + +- [基础适配](#section14523241594) +- [特性配置项](#section112994366592) + +芯片架构适配完成后,liteos-m提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数;了解内核配置选项,才能裁剪出适合单板的最小内核。 + +## 基础适配 + +如下图所示,基础适配主要分为以下两步: + +1. 启动文件startup.S和相应链接配置文件。 +2. main. c中的串口初始化和tick中断注册。 + +**图 1** 启动流程 + + +![](figure/zh-cn_image_0000001073943511.png) + +启动文件startup.S需要确保中断向量表的入口函数(例如reset\_vector)放在RAM的首地址,它由链接配置文件来指定。其中iar、keil和gcc工程的链接配置文件分别为xxx.icf、xxx.sct和xxx.ld,如果startup.S已经完成系统时钟初始化,并且能够引导到main函数,则启动文件不需要进行修改,采用厂商自带的startup.S即可,否则需要实现以上功能。 + +在main.c文件中,需要关注串口初始化UartInit和系统Tick的handler函数注册。 + +- UartInit函数表示单板串口的初始化,具体的函数名根据单板自行定义。这个函数是可选的,用户可以根据硬件单板是否支持串口来自行选择调用该函数。如果硬件单板支持串口,则该函数需要完成使能串口TX和RX通道,设置波特率。 +- HalTickStart设置tick中断的handler函数OsTickHandler。 + +对于中断向量表不可重定向的芯片,需要关闭LOSCFG\_PLATFORM\_HWI宏,并且在startup.S中新增tick中断的handler函数。 + +## 特性配置项 + +liteos\_m的完整配置能力及默认配置在los\_config.h定义,该头文件中的配置项可以根据不同的单板进行裁剪配置。 + +如果针对这些配置项需要进行不同的板级配置,则可将对应的配置项直接定义到对应单板的device/xxxx/target\_config.h文件中,其他未定义的配置项,采用los\_config.h中的默认值。 + +一份典型的配置参数如下: + +**表 1** 内核典型配置项说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

配置项

+

说明

+

LOSCFG_BASE_CORE_SWTMR

+

软件定时器特性开关,1表示打开,0表示关闭

+

LOSCFG_BASE_CORE_SWTMR_ALIGN

+

对齐软件定时器特性开,1表示打开,依赖软件定时器特性打开,0表示关闭

+

LOSCFG_BASE_IPC_MUX

+

mux功能开关,1表示打开,0表示关闭

+

LOSCFG_BASE_IPC_QUEUE

+

队列功能开关,1表示打开,0表示关闭

+

LOSCFG_BASE_IPC_SEM

+

信号量功能开关,1表示打开,0表示关闭

+

LOSCFG_PLATFORM_EXC

+

异常特性开关,1表示打开,0表示关闭

+

LOSCFG_KERNEL_PRINTF

+

打印特性开关,1表示打开,0表示关闭

+
+ diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel-overview.md b/zh-cn/device-dev/porting/transplant-chip-kernel-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..34095a2318d181be7604f6c4ac4ce9bd4d614db2 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel-overview.md @@ -0,0 +1,64 @@ +# 移植概述 + +- [移植场景](#section93781277367) +- [目录规范](#section18127744153119) +- [芯片架构适配点](#section137431650339) + +## 移植场景 + +芯片架构适配是可选过程,如果在liteos\_m/kernel/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 + +## 目录规范 + +模组芯片使用的内核为liteos-m,liteos-m中主要分为KAL、Components、Kernel和Utils四个模块。 + +- KAL模块作为内核对外的接口依赖Components模块和Kernel模块。 +- Components模块可插拔,它依赖Kernel模块。 + +- 在Kernel模块中,其中硬件相关的代码放在kernel的arch目录中,其余为硬件无关的代码。内核功能集(task、sem等)的实现依赖硬件相关的arch代码,例如任务上下文切换、原子操作等。 +- Utils模块作为基础代码块,被其他模块依赖。 + +**图 1** liteos-m内核模块图 + + +![](figure/zh-cn_image_0000001072304191.png) + +内核的目录结构和说明如下: + +``` +. +├── components --- 移植可选组件,依赖内核,单独对外提供头文件 +├── kal --- 内核抽象层,提供内核对外接口,当前支持cmsis接口和部分posix接口 +├── kernel --- 内核最小功能集代码 +│ ├── arch --- 内核指令架构层代码 +│ │ ├── arm --- arm32架构的代码 +│ │ │ ├── cortex-m3 --- cortex-m3架构的代码 +│ │ │ │ ├── iar --- iar编译工具链实现 +│ │ │ │ ├── keil --- keil编译工具链实现 +│ │ │ │ └── xxx --- xxx编译工具链实现 +│ │ │ └── cortex-m4 --- cortex-m4架构的代码 +│ │ │ ├── iar --- iar编译工具链实现 +│ │ │ ├── keil --- keil编译工具链实现 +│ │ │ └── xxx --- xxx编译工具链实现 +│ │ ├── include --- 所有的arch需要实现的函数定义,内核依赖 +│ │ └── risc-v --- risk-v架构 +│ │ └── gcc --- iar编译工具链实现 +│ ├── include --- 内核最小功能集代码 +│ └── src --- 内核最小功能集代码 +└──utils --- 基础代码,作为依赖的最底层,被系统依赖 +``` + +## 芯片架构适配点 + +如内核的[目录结构](#section18127744153119)所示,arch/include定义通用的芯片架构所需要实现的函数,另外芯片架构相关的代码会有部分的汇编代码,而汇编代码会因编译工具链的不同而不同,因此在具体的芯片架构下,还包含不同工具链(iar、keil、gcc等)的实现。 + +arch/include 目录定义通用的文件以及函数列表,该目录下的所有函数在新增arch组件时都需要适配,详见每一个头文件: + +``` +los_arch.h --- 定义芯片架构初始化所需要的函数 +los_atomic.h --- 定义芯片架构所需要实现的原子操作函数 +los_context.h --- 定义芯片架构所需要实现的任务上下文相关函数 +los_interrupt.h --- 定义芯片架构所需要实现的中断和异常相关的函数 +los_timer.h --- 定义芯片架构所需要实现的系统时钟相关的函数 +``` + diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel-verify.md b/zh-cn/device-dev/porting/transplant-chip-kernel-verify.md new file mode 100644 index 0000000000000000000000000000000000000000..fc16eeb224f18814ed2c114a8fe3f4a07fea59b3 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel-verify.md @@ -0,0 +1,59 @@ +# 内核移植验证 + +在工程device目录下添加编译main.c示例程序文件,此示例程序的主要目的是:LOS\_KernelInit完成之后,创建两个任务,循环调度延时并打印日志信息,通过此方法可以验证系统是否可正常调度以及时钟是否正常。 + +``` +VOID TaskSampleEntry2(VOID) // 任务2的入口函数 +{ + while(1) { + LOS_TaskDelay(10000); + printf("taskSampleEntry2 running...\n"); + } +} + +VOID TaskSampleEntry1(VOID) // 任务1的入口函数 +{ + while(1) { + LOS_TaskDelay(2000); + printf("taskSampleEntry1 running...\n"); + } +} + +UINT32 TaskSample(VOID) +{ + UINT32 uwRet; + UINT32 taskID1,taskID2; + TSK_INIT_PARAM_S stTask1={0}; + stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry1; + stTask1.uwStackSize = 0X1000; + stTask1.pcName = "taskSampleEntry1"; + stTask1.usTaskPrio = 6; //stTask1的任务优先级设定,不同于stTask2 + uwRet = LOS_TaskCreate(&taskID1, &stTask1); + + stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry2; + stTask1.uwStackSize = 0X1000; + stTask1.pcName = "taskSampleEntry2"; + stTask1.usTaskPrio = 7; + uwRet = LOS_TaskCreate(&taskID2, &stTask1); + + return LOS_OK; +} + +LITE_OS_SEC_TEXT_INIT int main(void) +{ + UINT32 ret; + UartInit(); // 硬件串口配置,通过串口输出调试日志,实际函数名根据单板实现不一样而不一样。 + printf("\n\rhello world!!\n\r"); + ret = LOS_KernelInit(); + TaskSample(); + if (ret == LOS_OK) { + LOS_Start(); // 开始系统调度,循环执行stTask1/stTask2任务,串口输出任务日志 + } + while (1) { + __asm volatile("wfi"); + } +} +``` + +第一个任务运行正常后,说明最小系统的核心流程基本OK;由于xts用例框架对外依赖较多,主要是utils、bootstrap的链接脚本和编译框架,暂时无法支撑内核单独跑xts;此处略过内核测试套的测试,可以通过[XTS测试套](transplant-chip-board-xts.md)来覆盖最小系统是否完整移植成功。 + diff --git a/zh-cn/device-dev/porting/transplant-chip-kernel.md b/zh-cn/device-dev/porting/transplant-chip-kernel.md new file mode 100644 index 0000000000000000000000000000000000000000..e27fea3d596d06af478a4b24eb46ddc8a6b81187 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-kernel.md @@ -0,0 +1,9 @@ +# 内核移植 + +- **[移植概述](transplant-chip-kernel-overview.md)** + +- **[内核基础适配](transplant-chip-kernel-adjustment.md)** + +- **[内核移植验证](transplant-chip-kernel-verify.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-chip-prepare-knows.md b/zh-cn/device-dev/porting/transplant-chip-prepare-knows.md new file mode 100644 index 0000000000000000000000000000000000000000..6c0282c492baf353133e15ad5fb6c24da7a2e8d9 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-prepare-knows.md @@ -0,0 +1,84 @@ +# 移植须知 + +- [移植目录](#section284217487490) +- [移植流程](#section639315306506) +- [移植规范](#section187870185219) + +本文为OpenHarmony平台系统开发人员和芯片(或模组)制造商提供基础的开发移植指导,典型的芯片架构例如cortex-m系列、risc-v系列等都可以按照本文进行移植,暂时不支持蓝牙服务。OpenHarmony是个持续演进的复杂项目,随着版本和API的改变,本文将会不断更新。 + +本文要求读者具有一定的嵌入式系统开发经验,因此它的重点未放在基本的OS基础介绍,而更多地描述OpenHarmony平台移植过程中主要操作和所需要关注的方面。 + +## 移植目录 + +OpenHarmony整体工程较为复杂,目录及实现为系统本身功能,如果不涉及复杂的特性增强,不需要关注每一层实现,移植过程中重点关注如下目录即可: + +**表 1** 移植过程中的重点目录 + + + + + + + + + + + + + + + + + + + +

目录名称

+

描述

+

/build/lite

+

OpenHarmony基础编译构建框架

+

/kernel/liteos_m

+

基础内核,其中芯片架构相关实现在arch目录下

+

/device

+

板级相关实现,各个三方厂商按照OpenHarmony规范适配实现,device下具体目录结构及移植过程参见板级系统移植

+

/vendor

+

产品级相关实现,主要由华为或者产品厂商贡献

+
+ +device目录规则:device/\{芯片解决方案厂商\}/\{开发板\}。以hisilicon的hispark\_taurus为例: + +``` +device +└── hisilicon # 芯片解决方案厂商名 + ├── common # 芯片解决方案开发板公共部分 + └── hispark_taurus # 开发板名称 + ├── BUILD.gn # 开发板编译入口 + ├── hals # 芯片解决方案厂商OS硬件适配 + ├── linux # linux版本 + │ └── config.gni # linux版本编译工具链和编译选项配置 + └── liteos_a # liteos-a版本 + └── config.gni # liteos_a版本编译工具链和编译选项配置 +``` + +vendor目录规则:vendor/\{产品解决方案厂商\}/\{产品名称\}。以华为的wifiiot产品为例: + +``` +vendor # 产品解决方案厂商 +└── huawei # 产品解决方案厂商名称 + └── wifiiot # 产品名称 + ├── hals # 产品解决方案厂商OS适配 + ├── BUILD.gn # 产品编译脚本 + └── config.json # 产品配置文件 +``` + +## 移植流程 + +OpenHarmony的device目录是基础芯片的适配目录,如果在三方芯片应用过程中发现此目录下已经有完整的芯片适配,则不需要再额外移植,直接跳过移植过程进行系统应用开发即可,如果该目录下无对应的芯片移植实现,则根据本文完成移植过程。OpenHarmony三方芯片移植主要过程如下: + +**图 1** 芯片移植关键步骤 +![](figure/芯片移植关键步骤.png "芯片移植关键步骤") + +## 移植规范 + +- 满足OpenHarmony[开源贡献基本规范和准则](https://gitee.com/openharmony/docs/blob/master/zh-cn/contribute/%E5%8F%82%E4%B8%8E%E8%B4%A1%E7%8C%AE.md)。 +- 三方芯片适配所需要贡献的代码主要在device、vendor和arch三个目录,参照[内核目录规范](transplant-chip-kernel-overview.md)和[板级目录规范](transplant-chip-board-overview.md#section6204129143013)满足基本目录命名和使用规范。 + diff --git "a/zh-cn/device-dev/porting/\347\274\226\350\257\221\346\236\204\345\273\272\351\200\202\351\205\215\346\265\201\347\250\213.md" b/zh-cn/device-dev/porting/transplant-chip-prepare-process.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\347\274\226\350\257\221\346\236\204\345\273\272\351\200\202\351\205\215\346\265\201\347\250\213.md" rename to zh-cn/device-dev/porting/transplant-chip-prepare-process.md diff --git a/zh-cn/device-dev/porting/transplant-chip-prepare.md b/zh-cn/device-dev/porting/transplant-chip-prepare.md new file mode 100644 index 0000000000000000000000000000000000000000..358da845b74ef9ce278a3bff22ee09be59501cb2 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip-prepare.md @@ -0,0 +1,7 @@ +# 移植准备 + +- **[移植须知](transplant-chip-prepare-knows.md)** + +- **[编译构建适配流程](transplant-chip-prepare-process.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-chip.md b/zh-cn/device-dev/porting/transplant-chip.md new file mode 100644 index 0000000000000000000000000000000000000000..d0fbee119dd00fe8fb475196714a9a253e676f2b --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-chip.md @@ -0,0 +1,11 @@ +# 三方芯片移植指导 + +- **[移植准备](transplant-chip-prepare.md)** + +- **[内核移植](transplant-chip-kernel.md)** + +- **[板级系统移植](transplant-chip-board.md)** + +- **[常见问题](transplant-chip-faqs.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-minichip.md b/zh-cn/device-dev/porting/transplant-minichip.md new file mode 100644 index 0000000000000000000000000000000000000000..58bebe026e881c23d1d2aa1cd173cc6bc86ea777 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-minichip.md @@ -0,0 +1,11 @@ +# 轻量系统芯片移植指导 + +- **[移植准备](transplant-chip-prepare.md)** + +- **[内核移植](transplant-chip-kernel.md)** + +- **[板级系统移植](transplant-chip-board.md)** + +- **[常见问题](transplant-chip-faqs.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive-des.md b/zh-cn/device-dev/porting/transplant-smallchip-drive-des.md new file mode 100644 index 0000000000000000000000000000000000000000..bba3736632bc974821981b0e4839f629ab4d1551 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive-des.md @@ -0,0 +1,11 @@ +# 移植概述 + +驱动主要包含两部分,平台驱动和器件驱动。平台驱动主要包括通常在SOC内的GPIO、I2C、SPI等;器件驱动则主要包含通常在SOC外的器件,如 LCD、TP、WLAN等。 + +**图 1** OpenHarmony 驱动分类 + + +![](figure/分类.png) + +HDF驱动被设计为可以跨OS使用的驱动程序,HDF驱动框架会为驱动达成这个目标提供有力的支撑。开发HDF驱动中,请尽可能只使用HDF驱动框架提供的接口,否则会导致驱动丧失跨OS使用的特性。在开始驱动开发前,建议先了解[HDF驱动框架](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/HDF%E9%A9%B1%E5%8A%A8%E6%A1%86%E6%9E%B6.md)。 + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md b/zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md new file mode 100644 index 0000000000000000000000000000000000000000..353aa15d2a8b5b84c66b3192fc30ccc8c6975694 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive-oom.md @@ -0,0 +1,390 @@ +# 器件驱动移植 + +- [LCD驱动移植](#section1574513454119) +- [TP驱动移植](#section20284142116422) +- [WLAN驱动移植](#section0969448164217) + +本章节讲解如何移植各类器件驱动。 + +## LCD驱动移植 + +移植LCD驱动的主要工作是编写一个驱动,在驱动中生成模型的实例,并完成注册。 + +这些LCD的驱动被放置在源码目录//drivers/framework/model/display/driver/panel中。 + +1. 创建Panel驱动 + + 创建HDF驱动,在驱动初始化中调用RegisterPanel接口注册模型实例。如: + + ``` + int32_t LCDxxEntryInit(struct HdfDeviceObject *object) + { + struct PanelData *panel = CreateYourPanel(); + // 注册模型实例 + if (RegisterPanel(panel) != HDF_SUCCESS) { + HDF_LOGE("%s: RegisterPanel failed", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_xxxxDevEntry = { + .moduleVersion = 1, + .moduleName = "LCD_XXXX", + .Init = LCDxxEntryInit, + }; + + HDF_INIT(g_xxxxDevEntry); + ``` + +2. 配置加载panel驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在display的host中,名为device\_lcd的device中增加配置。 + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >moduleName 要与panel驱动中的moduleName相同。 + + ``` + root { + ... + display :: host { + device_lcd :: device { + deviceN :: deviceNode { + policy = 0; + priority = 100; + preload = 2; + moduleName = "LCD_XXXX"; + } + } + } + } + ``` + + +## TP驱动移植 + +本节描述如何移植触摸屏驱动。触摸屏的器件驱动被放置在源码目录//drivers/framework/model/input/driver/touchscreen中。 移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。 + +详细的驱动开发指导,请参考 [TOUCHSCREEN开发指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/TOUCHSCREEN.md)。 + +1. 创建触摸屏器件驱动 + + 在上述touchscreen目录中创建名为touch\_ic\_name.c的文件。编写如下内容 + + ``` + #include "hdf_touch.h" + + static int32_t HdfXXXXChipInit(struct HdfDeviceObject *device) + { + ChipDevice *tpImpl = CreateXXXXTpImpl(); + if(RegisterChipDevice(tpImpl) != HDF_SUCCESS) { // 注册ChipDevice模型 + ReleaseXXXXTpImpl(tpImpl); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_touchXXXXChipEntry = { + .moduleVersion = 1, + .moduleName = "HDF_TOUCH_XXXX", // 注意这里的moduleName要与后续的配置完全一致 + .Init = HdfXXXXChipInit, + }; + + HDF_INIT(g_touchXXXXChipEntry); + ``` + + 其中ChipDevice中要实现如下方法: + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

实现说明

+

int32_t (*Init)(ChipDevice *device)

+

实现器件初始化

+

int32_t (*Detect)(ChipDevice *device)

+

实现器件探测

+

int32_t (*Suspend)(ChipDevice *device)

+

实现器件休眠

+

int32_t (*Resume)(ChipDevice *device)

+

实现器件唤醒

+

int32_t (*DataHandle)(ChipDevice *device)

+

需要实现从器件读取数据,将触摸点数据填写入device->driver->frameData中

+

int32_t (*UpdateFirmware)(ChipDevice *device)

+

实现固件升级

+
+ +2. 配置产品,加载器件驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在名为input的host中,名为device\_touch\_chip的device中增加配置。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >moduleName 要与触摸屏驱动中的moduleName相同。 + + ``` + deviceN :: deviceNode { + policy = 0; + priority = 130; + preload = 0; + permission = 0660; + moduleName = "HDF_TOUCH_XXXX"; + deviceMatchAttr = "touch_XXXX_configs"; + } + ``` + + +## WLAN驱动移植 + +WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负责处理WLAN流量。 + +**图 1** OpenHarmony WLAN结构示意图 + + +![](figure/HDF_WIFI.png) + +如图1,左半部分负责管理WLAN设备,右半部分负责WLAN流量。HDF WLAN分别为这两部分做了抽象,驱动的移植过程可以看做分别实现这两部分所需接口。这些接口有: + + + + + + + + + + + + + + + + + + + + +

接口

+

定义头文件

+

接口说明

+

HdfChipDriverFactory

+

drivers\framework\include\wifi\hdf_wlan_chipdriver_manager.h

+

ChipDriver的Factory,用于支持一个芯片多个WLAN端口

+

HdfChipDriver

+

drivers\framework\include\wifi\wifi_module.h

+

每个WLAN端口对应一个HdfChipDriver,用来管理一个特定端口

+

NetDeviceInterFace

+

drivers\framework\include\wifi\net_device.h

+

与协议栈之间的接口,如发送数据、设置网络接口状态等

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>详细的接口开发指导,请参考[WLAN开发](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/WLAN.md)。 + +具体的移植步骤如下: + +1. 创建HDF WLAN 芯片驱动 + + 在目录/device/vendor\_name/peripheral/wifi/chip\_name/ 创建文件 hdf\_wlan\_chip\_name.c。内容模板如下: + + ``` + static int32_t HdfWlanHisiChipDriverInit(struct HdfDeviceObject *device) { + static struct HdfChipDriverFactory factory = CreateChipDriverFactory(); // 需要移植者实现的方法 + struct HdfChipDriverManager *driverMgr = HdfWlanGetChipDriverMgr(); + if (driverMgr->RegChipDriver(&factory) != HDF_SUCCESS) { // 注册驱动工厂 + HDF_LOGE("%s fail: driverMgr is NULL!", __func__); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + struct HdfDriverEntry g_hdfXXXChipEntry = { + .moduleVersion = 1, + .Init = HdfWlanXXXChipDriverInit, + .Release = HdfWlanXXXChipRelease, + .moduleName = "HDF_WIFI_CHIP_XXX" // 注意:这个名字要与配置一致 + }; + + HDF_INIT(g_hdfXXXChipEntry); + ``` + + 在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口

+

说明

+

const char *driverName

+

当前driverName

+

int32_t (*InitChip)(struct HdfWlanDevice *device)

+

初始化芯片

+

int32_t (*DeinitChip)(struct HdfWlanDevice *device)

+

去初始化芯片

+

void (*ReleaseFactory)(struct HdfChipDriverFactory *factory)

+

释放HdfChipDriverFactory对象

+

struct HdfChipDriver *(*Build)(struct HdfWlanDevice *device, uint8_t ifIndex)

+

创建一个HdfChipDriver;输入参数中,device是设备信息,ifIndex是当前创建的接口在这个芯片中的序号

+

void (*Release)(struct HdfChipDriver *chipDriver)

+

释放chipDriver

+

uint8_t (*GetMaxIFCount)(struct HdfChipDriverFactory *factory)

+

获取当前芯片支持的最大接口数

+
+ + 其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver 。该对象需要提供方法: + + + + + + + + + + + + + + + + + + + + + + +

接口

+

说明

+

int32_t (*init)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

+

初始化当前网络接口,这里需要向netDev提供接口NetDeviceInterFace

+

int32_t (*deinit)(struct HdfChipDriver *chipDriver, NetDevice *netDev)

+

去初始化当前网络接口

+

struct HdfMac80211BaseOps *ops

+

WLAN基础能力接口集

+

struct HdfMac80211STAOps *staOps

+

支持STA模式所需的接口集

+

struct HdfMac80211APOps *apOps

+

支持AP模式所需要的接口集

+
+ +2. 编写配置文件描述驱动支持的芯片 + + 在产品配置目录下创建芯片的配置文件,保存至源码路径//vendor/vendor\_name/product\_name/config/wifi/wlan\_chip\_chip\_name.hcs + + 该文件模板如下: + + ``` + root { + wlan_config { + chip_name :& chipList { + chip_name :: chipInst { + match_attr = "hdf_wlan_chips_chip_name"; /* 这是配置匹配属性,用于提供驱动的配置根 */ + driverName = "driverName"; /* 需要与HdfChipDriverFactory中的driverName相同*/ + sdio { + vendorId = 0xXXXX; /* your vendor id */ + deviceId = [0xXXXX]; /*your supported devices */ + } + } + } + } + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >路径和文件中的vendor\_name、product\_name、chip\_name请替换成实际名称 + >vendorId 和 deviceId需要根据实际芯片的识别码进行填写。 + +3. 编写配置文件,加载驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。修改该文件,在名为network的host中,名为device\_wlan\_chips的device中增加配置。模板如下: + + ``` + deviceN :: deviceNode { + policy = 0; + preload = 2; + moduleName = "HDF_WLAN_CHIPS"; + deviceMatchAttr = "hdf_wlan_chips_chip_name"; + serviceName = "driverName"; + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >moduleName 要与HDF WLAN 芯片驱动中的moduleName相同。 + +4. 修改Kconfig文件,让移植的WLAN模组出现再内核配置中 + + 在device/vendor\_name/drivers/Kconfig中增加配置菜单,模板如下 + + ``` + config DRIVERS_HDF_WIFI_chip_name + bool "Enable chip_name Host driver" + default n + depends on DRIVERS_HDF_WLAN help + Answer Y to enable chip_name Host driver. + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >请替换模板中的chip\_name为实际的芯片名称 + +5. 修改构建脚本,让驱动参与内核构建 + + 在源码文件//device/vendor\_name/drivers/lite.mk末尾追加如下内容 + + ``` + ifeq ($(LOSCFG_DRIVERS_HDF_WIFI_chip_name), y) + # 构建完成要链接一个叫hdf_wlan_chipdriver_chip_name的对象,建议按这个命名,防止冲突 + LITEOS_BASELIB += -lhdf_wlan_chipdriver_chip_name + # 增加构建目录gpio + LIB_SUBDIRS += ../peripheral/wifi/chip_name + endif + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >请替换模板中的chip\_name为实际的芯片名称 + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md b/zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md new file mode 100644 index 0000000000000000000000000000000000000000..a28bc2faf3fae4cb54a85094e10a185d20b34041 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive-plat.md @@ -0,0 +1,165 @@ +# 平台驱动移植 + +在这一步,我们会在源码目录//device/vendor\_name/soc\_name/drivers 目录下创建平台驱动,如果你要移植的SOC的厂商还没有创建仓库的话,请联系[sig-devboard](https://gitee.com/openharmony/community/blob/master/sig/sig-devboard/sig_devboard_cn.md)创建。 + +建议的目录结构: + +``` +device +├── vendor_name +│ ├── drivers +│ │ │ ├── common +│ │ │ ├── Kconfig # 厂商驱动内核菜单入口 +│ │ │ └── lite.mk # 构建的入口 +│ ├── soc_name +│ │ ├── drivers +│ │ │ ├── dmac +│ │ │ ├── gpio +│ │ │ ├── i2c +│ │ │ ├── LICENSE +│ │ │ ├── mipi_dsi +│ │ │ ├── mmc +│ │ │ ├── pwm +│ │ │ ├── README.md # docs 如果需要的话 +│ │ │ ├── README_zh.md +│ │ │ ├── rtc +│ │ │ ├── spi +│ │ │ ├── uart +│ │ │ └── watchdog +│ ├── board_name +``` + +HDF为所有的平台驱动都创建了驱动模型,移植平台驱动的主要工作是向模型注入实例。 这些模型你可以在源码目录//drivers/framework/support/platform/include中找到定义。 + +本节我们会以GPIO为例,讲解如何移植平台驱动,移植过程包含以下步骤: + +1. 创建GPIO驱动 + + 在源码目录//device/vendor\_name/soc\_name/drivers/gpio中创建文件soc\_name\_gpio.c 内容模板如下: + + ``` + #include "gpio_core.h" + + // 定义GPIO结构体,如果需要的话 + struct SocNameGpioCntlr { + struct GpioCntlr cntlr; // 这是HDF GPIO驱动框架需要的结构体 + int myData; // 以下是当前驱动自身需要的 + }; + + // Bind 方法在HDF驱动中主要用户对外发布服务,这里我们不需要,直接返回成功即可 + static int32_t GpioBind(struct HdfDeviceObject *device) + { + (void)device; + return HDF_SUCCESS; + } + + // Init方法时驱动初始化的入口,我们需要在Init方法中完成模型实例的注册 + static int32_t GpioInit(struct HdfDeviceObject *device) + { + SocNameGpioCntlr *impl = CreateGpio(); // 你的创建代码 + ret = GpioCntlrAdd(&impl->cntlr); // 注册GPIO模型实例 + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: err add controller:%d", __func__, ret); + return ret; + } + return HDF_SUCCESS; + } + + // Release方法会在驱动卸载时被调用,这里主要完成资源回收 + static void GpioRelease(struct HdfDeviceObject *device) + { + // GpioCntlrFromDevice 方法能从抽象的设备对象中获得init方法注册进去的模型实例。 + struct GpioCntlr *cntlr = GpioCntlrFromDevice(device); + //资源释放... + } + + struct HdfDriverEntry g_gpioDriverEntry = { + .moduleVersion = 1, + .Bind = GpioBind, + .Init = GpioInit, + .Release = GpioRelease, + .moduleName = "SOC_NAME_gpio_driver", // 这个名字我们稍后会在配置文件中用到,用来加载驱动。 + }; + HDF_INIT(g_gpioDriverEntry); // 注册一个GPIO的驱动入口 + ``` + +2. 创建厂商驱动构建入口 + + 如前所述device/vendor\_name/drivers/lite.mk是厂商驱动的构建的入口。我们需要从这个入口开始,进行构建 + + ``` + #文件device/vendor_name/drivers/lite.mk + + SOC_VENDOR_NAME := $(subst $/",,$(LOSCFG_DEVICE_COMPANY)) + SOC_NAME := $(subst $/",,$(LOSCFG_PLATFORM)) + BOARD_NAME := $(subst $/",,$(LOSCFG_PRODUCT_NAME)) + + # 指定SOC进行构建 + LIB_SUBDIRS += $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ + ``` + +3. 创建SOC驱动构建入口 + + ``` + #文件device/vendor_name/soc_name/drivers/lite.mk + + SOC_DRIVER_ROOT := $(LITEOSTOPDIR)/../../device/$(SOC_VENDOR_NAME)/$(SOC_NAME)/drivers/ + + # 判断如果打开了GPIO的内核编译开关 + ifeq ($(LOSCFG_DRIVERS_HDF_PLATFORM_GPIO), y) + # 构建完成要链接一个叫hdf_gpio的对象 + LITEOS_BASELIB += -lhdf_gpio + # 增加构建目录gpio + LIB_SUBDIRS += $(SOC_DRIVER_ROOT)/gpio + endif + + # 后续其他驱动在此基础上追加 + ``` + +4. 创建GPIO构建入口 + + ``` + include $(LITEOSTOPDIR)/config.mk + include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk + + # 指定输出对象的名称,注意要与SOC驱动构建入口里的LITEOS_BASELIB 保持一致 + MODULE_NAME := hdf_gpio + + # 增加HDF框架的INCLUDE + LOCAL_CFLAGS += $(HDF_INCLUDE) + + # 要编译的文件 + LOCAL_SRCS += soc_name_gpio.c + + # 编译参数 + LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char -fno-strict-aliasing -fno-common + + include $(HDF_DRIVER) + ``` + +5. 配置产品加载驱动 + + 产品的所有设备信息被定义在源码文件//vendor/vendor\_name/product\_name/config/device\_info/device\_info.hcs中。 + + 平台驱动请添加到platform的host中。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >moduleName要与驱动定义中的相同。 + + ``` + root { + ... + platform :: host { + device_gpio :: device { + device0 :: deviceNode { + policy = 0; + priority = 10; + permission = 0644; + moduleName = "SOC_NAME_gpio_driver"; + } + } + } + } + ``` + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-drive.md b/zh-cn/device-dev/porting/transplant-smallchip-drive.md new file mode 100644 index 0000000000000000000000000000000000000000..8d265ae4d089593010d0ddd7ef6bcbc0ab327f99 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-drive.md @@ -0,0 +1,9 @@ +# 驱动移植 + +- **[移植概述](transplant-smallchip-drive-des.md)** + +- **[平台驱动移植](transplant-smallchip-drive-plat.md)** + +- **[器件驱动移植](transplant-smallchip-drive-oom.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md b/zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md new file mode 100644 index 0000000000000000000000000000000000000000..f4de2f397dbc53de27f711e7bfa1e909a35b222c --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-kernel-a.md @@ -0,0 +1,265 @@ +# LiteOS-A内核 + +- [移植概述](#section14876256185510) + - [移植场景](#section1986014410569) + - [目录规范](#section10916181716564) + +- [基础适配](#section814974018565) + - [编程样例](#section10854481825) + +- [验证](#section646410453212) + +## 移植概述 + +### 移植场景 + +LiteOS-A当前支持ARMv7-a指令集架构,如果三方芯片为ARMv7-a架构,可以进行内核基础适配;否则还需要先根据芯片的架构来新增内核对该芯片架构的支持,这个工作较为复杂,不在这篇文章范围内。 + +### 目录规范 + +LiteOS-A目录规范参考[LiteOS-A 简介](https://gitee.com/openharmony/kernel_liteos_a)。 + +## 基础适配 + +LiteOS-A提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数。 + +如下图所示,LiteOS-A的初始化流程主要包含以下五步: + +1. 新增target\_config.h文件,并且编写单板内存相关的配置宏DDR\_MEM\_ADDR和DDR\_MEM\_SIZE,分别表示内存起始地址和内存的长度,预链接脚本board.ld.S会根据这两个宏进行展开生成链接脚本board.ld。 +2. 链接阶段根据链接脚本board.ld生成内核镜像。 +3. 单核CPU镜像运行入口为汇编文件reset\_vector\_up.S,多核CPU的入口为reset\_vector\_mp.S,在汇编文件中进行中断向量表初始化、MMU页表初始化等操作。 +4. reset\_vector.S汇编代码最终会跳转到C语言的main函数,进行硬件时钟、软件定时器、内存和任务等初始化,这个过程会依赖target\_config.h的特性宏配置,最后会创建SystemInit任务,并且开启任务调度OsSchedStart\(\)。 +5. SystemInit任务在单板代码中实现,其中调用DeviceManagerStart函数进行HDF驱动初始化,这个过程会调用单板代码中的驱动配置文件hdf.hcs以及drivers源码实现。 + +整体启动流程如下图所示: + +**图 1** 整体启动流程 + + +![](figure/zh-cn_image_0000001126358814.png) + +从图1中可以看到,内核基础适配需要单板进行适配的代码包含三部分: + +- 新增target\_config.h文件,其中新增单板硬件配置参数和特性开关的配置参数,具体说明如下: + + **表 1** target\_config.h配置项说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

配置项

+

说明

+

OS_SYS_CLOCK

+

系统cycle的频率

+

DDR_MEM_ADDR

+

系统内存的起始地址

+

DDR_MEM_SIZE

+

系统内存的大小

+

PERIPH_PMM_BASE

+

外设寄存器的起始地址

+

PERIPH_PMM_SIZE

+

外设寄存器的长度大小

+

OS_HWI_MIN

+

系统中断最小值

+

OS_HWI_MAX

+

系统中断最大值

+

NUM_HAL_INTERRUPT_UART0

+

UART0中断号

+

UART0_REG_BASE

+

UART0寄存器基址

+

GIC_BASE_ADDR

+

GIC中断寄存器基址

+

GICD_OFFSET

+

GICD相对GIC基址的偏移地址

+

GICC_OFFSET

+

GICC相对GIC基址的偏移地址

+
+ +- SystemInit函数用于单板用户态业务初始化,典型的初始化场景如图2所示: + + **图 1** 业务启动流程 + + + ![](figure/zh-cn_image_0000001126198996.png) + +- main函数用于内核基础初始化和单板内核态业务初始化,流程如下图3所示,整体由内核启动框架主导初始化流程,图中浅蓝色部分为启动框架中可接受外部模块注册启动的阶段。 + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >同一层级内的模块不能有依赖关系。 + + **图 2** 内核启动框架 + ![](figure/内核启动框架.jpg "内核启动框架") + + **表 2** 启动框架层级 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

层级

+

说明

+

LOS_INIT_LEVEL_EARLIEST

+

最早期初始化

+

说明:不依赖架构,单板以及后续模块会对其有依赖的纯软件模块初始化

+

例如:Trace模块

+

LOS_INIT_LEVEL_ARCH_EARLY

+

架构早期初始化

+

说明:架构相关,后续模块会对其有依赖的模块初始化,如启动过程中非必需的功能,建议放到LOS_INIT_LEVEL_ARCH层

+

LOS_INIT_LEVEL_PLATFORM_EARLY

+

平台早期初始化

+

说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化,如启动过程中必需的功能,建议放到LOS_INIT_LEVEL_PLATFORM层

+

例如:uart模块

+

LOS_INIT_LEVEL_KMOD_PREVM

+

内存初始化前的内核模块初始化

+

说明:在内存初始化之前需要使能的模块初始化

+

LOS_INIT_LEVEL_VM_COMPLETE

+

基础内存就绪后的初始化

+

说明:此时内存初始化完毕,需要进行使能且不依赖进程间通讯机制与系统进程的模块初始化

+

例如:共享内存功能

+

LOS_INIT_LEVEL_ARCH

+

架构后期初始化

+

说明:架构拓展功能相关,后续模块会对其有依赖的模块初始化

+

LOS_INIT_LEVEL_PLATFORM

+

平台后期初始化

+

说明:单板平台、驱动相关,后续模块会对其有依赖的模块初始化

+

例如:驱动内核抽象层初始化(mmc、mtd)

+

LOS_INIT_LEVEL_KMOD_BASIC

+

内核基础模块初始化

+

说明:内核可拆卸的基础模块初始化

+

例如:VFS初始化

+

LOS_INIT_LEVEL_KMOD_EXTENDED

+

内核扩展模块初始化

+

说明:内核可拆卸的扩展模块初始化

+

例如:系统调用初始化、ProcFS初始化、Futex初始化、HiLog初始化、HiEvent初始化、LiteIPC初始化

+

LOS_INIT_LEVEL_KMOD_TASK

+

内核任务创建

+

说明:进行内核任务的创建(内核线程,软件定时器任务)

+

例如:资源回收系统常驻任务的创建、SystemInit任务创建、CPU占用率统计任务创建

+
+ + 进行单板移植适配,推荐关注LOS\_INIT\_LEVEL\_ARCH至LOS\_INIT\_LEVEL\_KMOD\_TASK之间的层级,且尽可能拆分初始化行为进行细化阶段注册。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >启动框架中同一层级内的注册模块不能有依赖关系,建议新增模块按照上述启动阶段进行模块初始化的拆分,按需注册启动。 + >可通过查看系统编译生成文件OHOS\_Image.map中.rodata.init.kernel.\*段内的符号表来了解当前已注册进内核启动框架中的各个模块初始化入口,以及检查新注册的模块初始化入口是否生效。 + + +### 编程样例 + +在单板SDK文件中 + +``` +/* 内核启动框架头文件 */ +#include "los_init.h" +...... + +/* 新增模块的初始化函数 */ +unsigned int OsSampleModInit(void) +{ + PRINTK("OsSampleModInit SUCCESS!\n"); + ...... +} +...... +/* 在启动框架的目标层级中注册新增模块 */ +LOS_MODULE_INIT(OsSampleModInit, LOS_INIT_LEVEL_KMOD_EXTENDED); +``` + +## 验证 + +``` +main core booting up... +OsSampleModInit SUCCESS! +releasing 1 secondary cores +cpu 1 entering scheduler +cpu 0 entering scheduler +``` + +根据上述系统启动阶段的打印可知,内核在启动时进行了该注册模块的初始化函数调用,完成该模块的初始化操作。 + +系统启动完毕后进入内核态shell,能够运行task命令能够正常显示即可。 + +``` +OHOS # help +*******************shell commands:************************* + +arp cat cd chgrp chmod chown cp cpup +date dhclient dmesg dns format free help hwi +ifconfig ipdebug kill log ls lsfd memcheck mkdir +mount netstat oom partinfo partition ping ping6 pmm +pwd reset rm rmdir sem shm stack statfs +su swtmr sync systeminfo task telnet touch umount +uname v2p virstatfs vmm watch writeproc + +``` + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md b/zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md new file mode 100644 index 0000000000000000000000000000000000000000..911329dbd1b9971e422b9242171c031102a137b0 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-kernel-linux.md @@ -0,0 +1,125 @@ +# Linux内核 + +- [移植概述](#section6282121355111) + - [基本信息](#section19589322515) + - [Bootloader](#section19062510518) + +- [适配编译和烧录启动](#section11112101695215) +- [验证](#section17318153325311) + +## 移植概述 + +Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后,进行基础的内核编译构建及验证。 + +### 基本信息 + +当前Linux内核基线是基于Linux社区 4.19 LTS版本演进,合入CVE及bugfix补丁。具体信息参考[代码库](https://gitee.com/openharmony/kernel_linux),对应repo工程代码路径为kernel/linux-4.19。 + +### Bootloader + +可以使用芯片厂商自带的Bootloader,或者是开源Uboot等加载内核镜像。比如为支持Hi3516DV300开发板,OpenHarmony引入的开源[Uboot](https://gitee.com/openharmony/device_hisilicon_third_party_uboot)。 + +## 适配编译和烧录启动 + +1. 准备内核config(特别是芯片相关的config)。 + + config文件所在源码目录:kernel/linux/config/ + + 以hi3516dv300芯片为例,可在对应的linux-4.19/arch/arm/configs/目录下新建\_small\_defconfig,如hi3516dv300\_small\_defconfig表示针对hi3516dv300小型系统的defconfig。该config文件可以由基础defconfig文件small\_common\_defconfig与该芯片相关的config组合生成。 + +2. 准备芯片补丁。 + + 补丁文件所在源码目录:kernel/linux/patches/linux-4.19 + + 以hi3516dv300芯片为例,参考已有的patch目录hi3516dv300\_small\_patch目录,新建\_patch目录,放置相关芯片补丁,注意hdf.patch等驱动补丁。 + +3. 编译。 + + 具体内核编译入口脚本位于工程目录kernel/linux/patches/下面,版本级整编命令会通过BUILD.gn进入kernel\_module\_build.sh和kernel.mk,需要在这2个文件中针对性进行patch及defconfig文件路径、编译器、芯片架构、内核Image格式等的适配。 + + 通过编译错误日志调整补丁,典型错误场景: + + (1)补丁合入失败,出现冲突,需要进行上下文适配修改。 + + (2)编译失败,内核版本差异(函数实现调整等)需要针对性进行内核适配。 + + >![](../public_sys-resources/icon-caution.gif) **注意:** + >- 参考kernel.mk,在OpenHarmony工程的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用版本级编译命令前,需要kernel/linux-4.19保持原代码环境。 + >- 对应拷贝后的目录位于: out/<\*\*\*\>/kernel/linux-4.19,可以在该目录下进行补丁的修改适配。 + +4. 烧录启动。 + + 由于不同芯片的开发板的烧录方式不一样,此处不表述具体的烧录方式。需要注意烧录的各镜像的大小及启动参数的配置,参考hi3516dv300采用uboot启动参数: + + ``` + setenv bootargs 'mem=128M console=ttyAMA0,115200 root=/dev/mmcblk0p3 ro rootfstype=ext4 rootwait blkdevparts=mmcblk0:1M(boot),9M(kernel),50M(rootfs),50M(userfs)' + ``` + + +## 验证 + +调试init进程、启动shell和运行简单的用户态程序,验证内核移植是否成功。OpenHarmony[小型系统](https://device.harmonyos.com/cn/docs/start/introduce/oem_start_guide-0000001054913231)的OS镜像结构以及linux用户态的启动流程如下图1所示: + +**图 1** 基于linux内核的OS镜像结构和用户态程序启动流程 + + +![](figure/zh-cn_image_0000001126354076.png) + +基于上述流程,推荐按以下步骤完成验证: + +1. 制作根文件系统镜像。 + + 请参考[新建芯片解决方案和产品解决方案](https://device.harmonyos.com/cn/docs/develop/subsystems/oem_subsys_build_guide-0000001060378721)生成根文件系统镜像rootfs.img。从上图可以看到启动过程与产品配置强相关,在制作rootfs.img过程中请完成如下四种配置: + + - 组件配置 + + 产品组件配置文件vendor/\{company\}/\{product\}/config.json需配置启动恢复子系统\(startup\)的init\_lite组件和内核子系统的linux\_4\_1\_9组件。 + + - 系统服务配置 + + 系统服务配置文件vendor/\{company\}/\{product\}/init\_configs/init\_xxx.cfg需要启动shell服务。 + + - 文件系统配置 + + 文件系统配置vendor/\{company\}/\{product\}/fs.yml中需要创建“/bin/sh -\> mksh“和“/lib/ld-musl-arm.so.1 -\> libc.so“软连接,这两个文件分别是shell可执行程序和可执行程序依赖的c库。 + + - 启动配置 + + 启动配置在vendor/\{company\}/\{product\}/init\_configs/etc目录下,包括fstab、rsS和Sxxx文件,请按开发板实际情况配置。 + + + 编译完成后,可通过检查产品编译输出目录下的rootfs内容,确认rootfs.img文件生成是否符合预期。 + +2. 调试init进程和shell。 + + 烧录rootfs.img并调试init进程和shell,不同厂商的开发板的烧录工具和流程可能不同,请按芯片解决方案提供的流程进行烧录。烧录rootfs.img前请确认bootloader和linux内核启动正常。如果rootfs.img被内核正常挂载,接着将运行/bin/init程序,init进程为用户态的第一个应用程序,它的运行意味着用户态的开始。 + + init程序首先会调用/etc/init.d/rcS脚本,rcS脚本执行第一条命令为"/bin/mount -a”,该命令会加载fstab文件,在fstab中的命令执行完后rcS将顺序调用Sxxx脚本完成设备节点创建和扫描、文件权限配置等操作。 + + 最后,init程序会读取init.cfg系统服务配置文件。根据步骤1中的设置,init程序将会启动shell。如果上述流程运行正常,系统则会进入shell。 + + 若串口有如下版本号日志打印,则表示init程序启动正常: + + **图 2** init启动正常日志 + + + ![](figure/init.jpg) + + 正常进入shell后执行ls命令,串口打印信息如下图: + + **图 3** 正常进入shell后输入ls命令串口打印 + + + ![](figure/shell.jpg) + +3. 配置NFS。 + + init进程和shell正常启动后,以服务端IP为192.168.1.22、客户端IP为192.168.1.4为例,可在根目录执行如下命令开启NFS: + + ``` + ifconfig eth0 192.168.1.4 netmask 255.255.255.0 + mkdir -p /storgage/nfs + mount -t nfs -o nolock,addr=192.168.1.22 192.168.1.22:/nfs /storage/nfs + ``` + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-kernel.md b/zh-cn/device-dev/porting/transplant-smallchip-kernel.md new file mode 100644 index 0000000000000000000000000000000000000000..a1adc2dde7e4c576f8fc9137c42217474a15311e --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-kernel.md @@ -0,0 +1,7 @@ +# 移植内核 + +- **[LiteOS-A内核](transplant-smallchip-kernel-a.md)** + +- **[Linux内核](transplant-smallchip-kernel-linux.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md b/zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md new file mode 100644 index 0000000000000000000000000000000000000000..6ca5022e46a9574c8856578edc48294feffee89c --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-prepare-building.md @@ -0,0 +1,142 @@ +# 编译构建 + +- [编译环境搭建](#section3336103410314) +- [编译构建系统介绍](#section354343816319) +- [新建芯片解决方案](#section18612153175011) + +## 编译环境搭建 + +首先请搭建OpenHarmony基础环境,步骤请参考轻量和小型系统入门[linux环境搭建](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_environment_lin-0000001105407498)。用户态和LiteOS-A的内核态编译均使用llvm编译器编译,安装方法在搭建基础环境中已提供。若选择移植linux内核,请执行如下命令安装gcc-arm-linux-gnueabi交叉编译工具链,用于编译linux内核态镜像: + +``` +sudo apt-get install gcc-arm-linux-gnueabi +``` + +## 编译构建系统介绍 + +编译构建流程、编译脚本编写、目录规则、独立编译单个组件、独立编译芯片解决方案等介绍请见[编译构建子系统介绍](https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/subsystems/%E7%BC%96%E8%AF%91%E6%9E%84%E5%BB%BA.md)。 + +## 新建芯片解决方案 + +了解编译框架和搭建完编译环境后,请参考如下步骤新建芯片解决方案: + +1. 新建目录 + + 芯片解决方案的目录规则为:device/\{芯片解决方案厂商\}/\{开发板\}。以海思的hispark\_taurus开发板为例,在代码根目录执行如下命令建立目录: + + ``` + mkdir -p device/hisilicon/hispark_taurus + ``` + + 芯片解决方案目录树的规则如下: + + ``` + device + └── company # 芯片解决方案厂商 + └── board # 开发板名称 + ├── BUILD.gn # 编译脚本 + ├── hals # OS南向接口适配 + ├── linux # 可选,linux内核版本 + │ └── config.gni # linux版本编译配置 + └── liteos_a # 可选,liteos内核版本 + └── config.gni # liteos_a版本编译配置 + ``` + + 以hispark\_taurus移植linux内核为例,目录树应该如下: + + ``` + device + └── hisilicon + └── hispark_tautus + ├── BUILD.gn + ├── hals + ├── ...... + └── linux + └── config.gni + ``` + + 目录树建立后开发板相关的源码放到hispark\_taurus目录下。 + +2. 配置开发板编译选项 + + [步骤1](#li20894101862)中的config.gni可配置开发板相关的编译选项,编译构建框架将会遵照该配置文件中的参数编译所有用户态OS组件。其中关键的字段说明如下: + + ``` + kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 + kernel_version: 开发板使用的内核版本,例如:“4.19”。 + board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 + board_arch: 开发板芯片arch, 例如: “armv7-a”, “rv32imac”。 + board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 + board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 + board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 + board_cflags: 开发板配置的c文件编译选项。 + board_cxx_flags: 开发板配置的cpp文件编译选项。 + board_ld_flags: 开发板配置的链接选项。 + ``` + + 还以海思的hispark\_taurus开发板为例,对应的device/hisilicon/hispark\_taurus/config.gni内容如下: + + ``` + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "cortex-a7" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "mips-linux-gnu-gcc" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "arm-linux-ohoseabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [ + ] + board_cxx_flags = [ + ] + board_ld_flags = [] + + # Board related headfiles search path. + board_include_dirs = [] + board_include_dirs += [ rebase_path( + "//prebuilts/gcc/linux-x86/arm/arm-linux-ohoseabi-gcc/target/usr/include", + root_build_dir) ] + + # Board adapter dir for OHOS components. + board_adapter_dir = "" + + # Sysroot path. + board_configed_sysroot = "" + + # Board storage type, it used for file system generation. + storage_type = "emmc" + ``` + +3. 编写开发板编译脚本 + + 步骤1中的BUILD.gn为新增的开发板的编译入口,主要用于编译开发板相关的代码,主要为设备侧驱动、设备侧接口适配\(媒体,图形等\)和开发板的SDK等等。 + + 海思的hispark\_taurus开发板的device/hisilicon/hispark\_taurus/BUILD.gn可写成: + + ``` + # group名称建议与开发板名称一致 + group("hispark_taurus") { + deps = [ "//kernel/linux/patches:linux_kernel" ] # 拉起内核编译 + deps += [ + ...... # 开发板其他编译单元 + ] + } + ``` + +4. 编译调试 + + 在开发板目录下执行hb set和hb build即可启动芯片解决方案的编译,编译框架会以开发板下的BUILD.gn为入口启动编译。 + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md b/zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md new file mode 100644 index 0000000000000000000000000000000000000000..afe392369f2eb34c0c5a8dcf5a6204850347dd11 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-prepare-needs.md @@ -0,0 +1,98 @@ +# 移植须知 + +本文详细介绍如何将OpenHarmony[小型系统](https://device.harmonyos.com/cn/docs/start/introduce/oem_start_guide-0000001054913231)的linux和LiteOS-A内核移植到新的开发板上,要求读者具有一定的嵌入式系统开发经验。建议先查看[入门指导](https://gitee.com/openharmony/docs/blob/master/zh-cn/OpenHarmony-Overview_zh.md),以了解OpenHarmony软件架构、目录结构、内核子系统和驱动子系统相关知识。当前小型系统已适配的开发板如下表所示: + +**表 1** OpenHarmony小型系统已适配的开发板 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

开发板

+

内核

+

arch

+

ROM

+

RAM

+

文件系统

+

Flash 类型

+

hispark_taurus

+

LiteOS-A和linux-4.19

+

ARM cortex-a7

+

8G

+

1GB

+

VFAT、EXT4

+

eMMC4.5

+

hispark_aries

+

LiteOS-A

+

ARM cortex-a7

+

16M

+

512M

+

JFFS2

+

SPI NOR

+
+ +表1中的开发板可作为待移植开发板的参考,当前LiteOS-A和linux-4.19支持的arch、ROM占用、支持的文件系统和支持的Flash类型如下表所示: + +**表 2** OpenHarmony小型系统内核移植信息表 + + + + + + + + + + + + + + + + + + + + + + +

内核

+

支持的arch

+

ROM

+

文件系统

+

Flash类型

+

LiteOS-A

+

ARMv7

+

> 2M

+

VFAT、JFFS2、YAFFS2

+

SPI NOR、NAND、EMMC

+

linux-4.19

+

ARM, ARM64、 MIPS、 X86等

+

> 5M

+

VFAT、JFFS2、YAFFS、EXT/2/3/4、NFS等等

+

NOR、NAND、EMMC等

+
+ diff --git a/zh-cn/device-dev/porting/transplant-smallchip-prepare.md b/zh-cn/device-dev/porting/transplant-smallchip-prepare.md new file mode 100644 index 0000000000000000000000000000000000000000..6ec4b45dff790140fe40830288b5c0bb961ceddb --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip-prepare.md @@ -0,0 +1,7 @@ +# 移植准备 + +- **[移植须知](transplant-smallchip-prepare-needs.md)** + +- **[编译构建](transplant-smallchip-prepare-building.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-smallchip.md b/zh-cn/device-dev/porting/transplant-smallchip.md new file mode 100644 index 0000000000000000000000000000000000000000..4ba38ff4484d56d07681a0dce923d1839b80df87 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-smallchip.md @@ -0,0 +1,9 @@ +# 小型系统芯片移植指导 + +- **[移植准备](../porting/transplant-smallchip-prepare.md)** + +- **[移植内核](../porting/transplant-smallchip-kernel.md)** + +- **[驱动移植](../porting/transplant-smallchip-drive.md)** + + diff --git a/zh-cn/device-dev/porting/transplant-thirdparty-cmake.md b/zh-cn/device-dev/porting/transplant-thirdparty-cmake.md new file mode 100644 index 0000000000000000000000000000000000000000..fb23041d28a62d9768390ecdf41c6cc3acd4c4e2 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-thirdparty-cmake.md @@ -0,0 +1,435 @@ +# CMake方式组织编译的库移植 + +- [源码获取](#section1771132116245) +- [移植思路](#section9737174410328) +- [交叉编译](#section38205577332) + - [编译参考](#section1088111263418) + - [设置执行交叉编译](#section8168182883515) + +- [测试](#section6686144293611) +- [将该库编译添加到OpenHarmony工程中](#section1651053153715) + +以double-conversion库为例,其移植过程如下文所示 + +## 源码获取 + +从仓库[获取double-conversion源码](https://github.com/google/double-conversion),其目录结构如下表: + +**表 1** 源码目录结构 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

double-conversion/cmake/

+

CMake组织编译使用到的模板

+

double-conversion/double-conversion/

+

源文件目录

+

double-conversion/msvc/

+

-

+

double-conversion/test/

+

测试用例源文件

+

double-conversion/.gitignore

+

-

+

double-conversion/AUTHORS

+

-

+

double-conversion/BUILD

+

-

+

double-conversion/CMakeLists.txt

+

CMake方式顶层编译组织文件

+

double-conversion/COPYING

+

-

+

double-conversion/Changelog

+

-

+

double-conversion/LICENSE

+

-

+

double-conversion/Makefile

+

-

+

double-conversion/README.md

+

-

+

double-conversion/SConstruct

+

-

+

double-conversion/WORKSPACE

+

-

+
+ +## 移植思路 + +移植思路:通过修改工具链,交叉编译该三方库,生成OpenHarmony平台的可执行文件,最后再通过GN调用CMake的方式添加到OpenHarmony工程中。 + +## 交叉编译 + +### 编译参考 + +代码仓库的[README.md](https://github.com/google/double-conversion/blob/master/README.md)中详细介绍了使用CMake编译double-conversion库的步骤,以及测试方法。本文参考该指导设置该库的编译配置,并完成测试。若开发人员在移植过程中对该库的编译选项配置有疑惑的地方,可参考该指导。对于其他使用CMake可独立编译的三方库,在移植时可以参考其自带的编译指导。 + +### 设置执行交叉编译 + +CMake方式可通过指定工具链进行交叉编译,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: + +1. 设置工具链 + + 将下列clang工具链配置添加到该工程的顶层CMakeLists.txt(即[表1中的该文件](#table824211132418))中即可。 + + ``` + set(CMAKE_CROSSCOMPILING TRUE) + set(CMAKE_SYSTEM_NAME Generic) + set(CMAKE_CXX_COMPILER_ID Clang) + set(CMAKE_TOOLCHAIN_PREFIX llvm-) + #指定c编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,使用clang编译时标志中必须指定--target,否则无法交叉编译。 + set(CMAKE_C_COMPILER clang) + set(CMAKE_C_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") + #指定c++编译工具(确保工具链所在路径已经添加到了PATH环境变量中)和编译标志,必须指定--target,否则无法交叉编译。 + set(CMAKE_CXX_COMPILER clang++) + set(CMAKE_CXX_FLAGS "--target=arm-liteos -D__clang__ -march=armv7-a -w") + #指定链接工具和链接标志,必须指定--target和--sysroot,其中OHOS_ROOT_PATH可通过cmake命令后缀参数来指定。 + set(MY_LINK_FLAGS "--target=arm-liteos --sysroot=${OHOS_SYSROOT_PATH}") + set(CMAKE_LINKER clang) + set(CMAKE_CXX_LINKER clang++) + set(CMAKE_C_LINKER clang) + set(CMAKE_C_LINK_EXECUTABLE "${CMAKE_C_LINKER} + ${MY_LINK_FLAGS} -o ") + set(CMAKE_CXX_LINK_EXECUTABLE "${CMAKE_CXX_LINKER} + ${MY_LINK_FLAGS} -o ") + #指定链接库的查找路径。 + set(CMAKE_SYSROOT ${OHOS_SYSROOT_PATH}) + ``` + +2. 执行编译 + + linux命令行中进入double-conversion的源文件目录(即[表1所示目录](#table824211132418)),执行下列命令: + + ``` + mkdir build && cd build + cmake .. -DBUILD_TESTING=ON -DOHOS_SYSROOT_PATH="..." + make -j + ``` + + 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot目录的位置,以OpenHarmony为例即目录openHarmony/prebuilts/lite/sysroot的绝对路径。 + +3. 查看结果 + + 步骤2操作完成后,build目录下会生成静态库文件和测试用例: + + **表 2** 编译生成文件目录结构 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

double-conversion/build/libdouble-conversion.a

+

生成的静态库文件

+

double-conversion/build/test/

+

目录下存放生成的测试用例和相关CMake缓存文件

+

double-conversion/build/CMakeCache.txt

+

CMake构建过程中的缓存文件

+

double-conversion/build/CMakeFiles/

+

-

+

double-conversion/build/cmake_install.cmake

+

-

+

double-conversion/build/CTestTestfile.cmake

+

-

+

double-conversion/build/DartConfiguration.tcl

+

-

+

double-conversion/build/generated/

+

-

+

double-conversion/build/Makefile

+

-

+

double-conversion/build/Testing/

+

-

+
+ + +## 测试 + +1. 搭建OpenHarmony环境 + + 以hi3518ev300为例,编译出OpenHarmony镜像,烧写到开发板,参考[开发Hi3518第一个示例程序](../quick-start/quickstart-lite-steps-board3518-running.md)。 + + 进入系统如下所示: + + **图 1** OpenHarmony启动成功界面 + ![](figure/OpenHarmony启动成功界面.png "OpenHarmony启动成功界面") + +2. 挂载nfs目录,将[表2](#table1452412391911)中test目录下cctest可执行文件放入nfs目录 +3. 执行用例 + + 该库采用非交叉编译时用例是通过make test执行,CMake会有相关的执行结果统计;交叉编译时无法使用该方法,因此可直接执行生成的测试文件完成测试。 + + - 挂载成功后执行下列命令可列出用例所有条目: + + ``` + cd nfs + ./cctest --list + ``` + + 上述命令执行结果部分展示: + + ``` + test-bignum/Assign< + test-bignum/ShiftLeft< + test-bignum/AddUInt64< + test-bignum/AddBignum< + test-bignum/SubtractBignum< + test-bignum/MultiplyUInt32< + test-bignum/MultiplyUInt64< + test-bignum/MultiplyPowerOfTen< + test-bignum/DivideModuloIntBignum< + test-bignum/Compare< + test-bignum/PlusCompare< + test-bignum/Square< + test-bignum/AssignPowerUInt16< + test-bignum-dtoa/BignumDtoaVariousDoubles< + test-bignum-dtoa/BignumDtoaShortestVariousFloats< + test-bignum-dtoa/BignumDtoaGayShortest< + test-bignum-dtoa/BignumDtoaGayShortestSingle< + test-bignum-dtoa/BignumDtoaGayFixed< + test-bignum-dtoa/BignumDtoaGayPrecision< + test-conversions/DoubleToShortest< + test-conversions/DoubleToShortestSingle< + ... + ``` + + - 以test-bignum条目为例,执行下列命令开始测试: + + ``` + ./cctest test-bignum + ``` + + 测试结果如下则表示通过: + + ``` + Ran 13 tests. + ``` + + +## 将该库编译添加到OpenHarmony工程中 + +1. 复制库到OpenHarmony工程中 + + 拷贝已经能够成功交叉编译的库到OpenHarmony的third\_party目录,为了不修改要移植的三方库目录下的BUILD.gn文件,再添加一层目录放置新增的gn转CMake编译适配文件,新增的文件有BUILD.gn、build\_thirdparty.py、 config.gni,新增后的目录结构如下所示。 + + **表 3** 添加到工程后的目录结构 + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

openHarmony/third_party/double-conversion/BUILD.gn

+

将三方库加入工程的gn适配文件

+

openHarmony/third_party/double-conversion/build_thirdparty.py

+

GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转CMake

+

openHarmony/third_party/double-conversion/config.gni

+

三方库编译配置文件,可修改该文件来配置用例是否参与构建等

+

openHarmony/third_party/double-conversion/double-conversion/

+

要移植的三方库目录

+
+ +2. 添加gn到CMake适配文件 + + - **新增的BUILD.gn文件实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony平台时只需修改路径即可**。 + + ``` + import("config.gni") + group("double-conversion") { + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + deps = [":make"] + } + } + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + action("make") { + script = "//third_party/double-conversion/build_thirdparty.py" + outputs = ["$root_out_dir/log_dc.txt"] + exec_path = rebase_path(rebase_path("./build", ohos_third_party_dir)) + command = "rm * .* -rf && $CMAKE_TOOLS_PATH/cmake .. $CMAKE_FLAG $CMAKE_TOOLCHAIN_FLAG && make -j" + args = [ + "--path=$exec_path", + "--command=${command}" + ] + } + } + ``` + + - **新增的config.gni用于配置该库,实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时只需修改CMAKE\_FLAG的配置即可。** + + ``` + #CMAKE_FLAG: config compile feature + CMAKE_FLAG = "-DBUILD_TESTING=ON -DCMAKE_CXX_STANDARD=11" + + #toolchain:follow up-layer,depend on $ohos_build_compiler + if (ohos_build_compiler == "clang") { + CMAKE_TOOLCHAIN_FLAG = "-DOHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" + } else { + CMAKE_TOOLCHAIN_FLAG = "" + } + + #CMake tools path,no need setting if this path already joined to $PATH. + CMAKE_TOOLS_PATH = "setting CMake tools path..." + ``` + + - **新增的build\_thirdparty.py实现如下,其他采用CMake方式可独立编译的三方库移植到OpenHarmony时无需修改即可使用。** + + ``` + import os + import sys + from subprocess import Popen + import argparse + import shlex + + def cmd_exec(command): + cmd = shlex.split(command) + proc = Popen(cmd) + proc.wait() + ret_code = proc.returncode + if ret_code != 0: + raise Exception("{} failed, return code is {}".format(cmd, ret_code)) + + def main(): + parser = argparse.ArgumentParser() + parser.add_argument('--path', help='Build path.') + parser.add_argument('--command', help='Build command.') + parser.add_argument('--enable', help='enable python.', nargs='*') + args = parser.parse_args() + + if args.enable: + if args.enable[0] == 'false': + return + + if args.path: + curr_dir = os.getcwd() + os.chdir(args.path) + if args.command: + if '&&' in args.command: + command = args.command.split('&&') + for data in command: + cmd_exec(data) + else: + cmd_exec(args.command) + os.chdir(curr_dir) + + if __name__ == '__main__': + sys.exit(main()) + ``` + + - 在配置文件中添加开关控制该库编译,默认设为关闭 + + 在//build/lite/ohos\_var.gni文件中添加下列配置: + + ``` + declare_args() { + ohos_build_thirdparty_migrated_from_fuchisa = true + } + ``` + +3. 编译构建 + + - 手动单独构建: + + 执行下列命令 + + ``` + hb build -T //third_party/double-conversion:double-conversion + ``` + + 编译成功则[build](#li15717101715249)目录下会生成静态库文件和测试用例 + + diff --git a/zh-cn/device-dev/porting/transplant-thirdparty-makefile.md b/zh-cn/device-dev/porting/transplant-thirdparty-makefile.md new file mode 100644 index 0000000000000000000000000000000000000000..ddabc1ef30ae29930bea14394ced65ec43e227a2 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-thirdparty-makefile.md @@ -0,0 +1,309 @@ +# Makefile方式组织编译的库移植 + +- [源码获取](#section114115321416) +- [设置交叉编译](#section81263255384) +- [测试](#section1830015913391) +- [将该库编译添加到OpenHarmony工程中](#section1898016213406) + +以yxml库为例,其移植过程如下文所示 + +## 源码获取 + +从仓库[获取yxml源码](https://github.com/getdnsapi/yxml),其目录结构如下表: + +**表 1** 源码目录结构 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

yxml/bench/

+

benchmark相关代码

+

yxml/test/

+

测试输入输出文件,及测试脚本

+

yxml/Makefile

+

编译组织文件

+

yxml/.gitattributes

+

-

+

yxml/.gitignore

+

-

+

yxml/COPYING

+

-

+

yxml/yxml.c

+

-

+

yxml/yxml.c.in

+

-

+

yxml/yxml-gen.pl

+

-

+

yxml/yxml.h

+

-

+

yxml/yxml.md

+

-

+

yxml/yxml-states

+

-

+
+ +## 设置交叉编译 + +设置Makefile的交叉编译工具链,修改并编译该库,生成OpenHarmony平台的可执行文件,步骤如下: + +1. 设置工具链 + + 将下列clang工具链配置替换掉yxml库根目录的MakeFile(即[表1中的文件](#table16520154171813))中的原有配置。 + + clang工具链配置 + + ``` + #设置交叉编译工具链,确保工具链所在路径已经添加到了PATH环境变量中 + CC:=clang + AR:=llvm-ar + #cflags中必须要添加--target及--sysroot选项 + CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g --target=arm-liteos -march=armv7-a --sysroot=$(OHOS_ROOT_PATH)prebuilts/lite/sysroot + ``` + + 原有配置 + + ``` + CC:=gcc + AR:=ar + CFLAGS:=-Wall -Wextra -Wno-unused-parameter -O2 -g + ``` + +2. 执行编译 + + linux命令行中进入yxml的源文件目录(即图1所示目录),执行下列命令: + + ``` + make test OHOS_SYSROOT_PATH=... + ``` + + 其中OHOS\_SYSROOT\_PATH需用绝对路径指定出sysroot所在目录,以OpenHarmony为例即源码根目录prebuilts/lite/sysroot/所在的绝对路径。 + +3. 查看结果 + + 步骤2操作完成后,yxml下会生成out目录,里面有静态库文件和测试用例: + + **表 2** yxml编译生成目录 + + + + + + + + + + + + + +

名称

+

描述

+

openHarmony/third_party/yxml/yxml/out/lib/

+

编译生成的静态库的存放目录

+

openHarmony/third_party/yxml/yxml/out/test/

+

编译生成的测试用例及其输入输出等文件的存放目录

+
+ + +## 测试 + +yxml库测试步骤与double-conversion库基本一致,可参考[CMake方式组织编译的库移植](transplant-thirdparty-cmake.md#section6686144293611)的测试过程,以下内容介绍yxml库测试用例的使用方法: + +**表 3** 生成的test目录结构示意 + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

openHarmony/third_party/yxml/yxml/out/test/test.sh

+

自动化测试脚本,由于OpenHarmony不支持脚本运行,因此无法使用,可参考其内容手动测试

+

openHarmony/third_party/yxml/yxml/out/test/test

+

用于测试的可执行文件

+

openHarmony/third_party/yxml/yxml/out/test/*.xml

+

测试输入文件

+

openHarmony/third_party/yxml/yxml/out/test/*.out

+

期望的输出文件

+
+ +test.sh内容如下所示: + +``` +#!/bin/sh +for i in *.xml; do + b=`basename $i .xml` + o=${b}.out + t=${b}.test + ./test <$i >$t + if [ -n "`diff -q $o $t`" ]; then + echo "Test failed for $i:" + diff -u $o $t + exit 1 + fi +done +echo "All tests completed successfully." +``` + +由于OpenHarmony的shell中暂不支持输入输出重定向(<和\>),所以测试时需要将输入\*.xml文件内容直接复制进shell后回车,输出内容会直接展示在shell窗口。过程如下: + +下列操作假定已按照2.4节的步骤搭建OpenHarmony,挂载并进入nfs目录: + +1. 执行下列命令 + + ``` + ./test + ``` + +2. 复制\*.xml内容到shell + + 以[test目录](#table115941423164318)下pi01.xml为例,内容如下,输入到shell并回车: + + ``` + + ``` + +3. 比较shell中输出的内容与[test目录](#table115941423164318)中对应的\*.out文件是否一致 + + 输出结果如下: + + ``` + pistart SomePI + picontent abc + piend + elemstart a + elemend + ok + ``` + + 经比较与[test目录](#table115941423164318)下pi01.out内容一致,测试通过。 + + +## 将该库编译添加到OpenHarmony工程中 + +yxml库添加的过程除了适配文件build.gn和config.gni有些许变化外,其他和double-conversion库完全一致,参考[CMake方式组织编译的库移植](transplant-thirdparty-cmake.md#section1651053153715)的配置过程。要修改的适配文件及添加后的目录结构如下: + +- yxml库新增的BUILD.gn实现如下: + +``` +import("config.gni") +group("yxml") { + if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + deps = [":make"] + } +} +if (ohos_build_thirdparty_migrated_from_fuchisa == true) { + action("make") { + script = "//third_party/yxml/build_thirdparty.py" + outputs = ["$target_out_dir/log_yxml.txt"] + exec_path = rebase_path(rebase_path("./yxml", root_build_dir)) + command = "make clean && $MAKE_COMMAND" + args = [ + "--path=$exec_path", + "--command=${command}" + ] + } +} +``` + +- yxml库新增的config.gni配置如下: + +``` +TEST_ENABLE = "YES" + +if (TEST_ENABLE == "YES") { + MAKE_COMMAND = "make test OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" +} else { + MAKE_COMMAND = "make OHOS_SYSROOT_PATH=${ohos_root_path}prebuilts/lite/sysroot/" +} +``` + +- 添加完成后目录结构示意: + +**表 4** 添加到工程后的目录结构 + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

openHarmony/third_party/yxml/BUILD.gn

+

将三方库加入工程的gn适配文件

+

openHarmony/third_party/yxml/build_thirdparty.py

+

GN调用shell命令脚本文件,由上面GN文件将相关命令传入,实现GN转Makefile

+

openHarmony/third_party/yxml/config.gni

+

三方库编译配置文件,可修改该文件来配置用例是否参与构建等

+

openHarmony/third_party/yxml/yxml/

+

要移植的三方库目录

+
+ diff --git "a/zh-cn/device-dev/porting/\346\246\202\350\277\260.md" b/zh-cn/device-dev/porting/transplant-thirdparty-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/porting/\346\246\202\350\277\260.md" rename to zh-cn/device-dev/porting/transplant-thirdparty-overview.md diff --git a/zh-cn/device-dev/porting/transplant-thirdparty.md b/zh-cn/device-dev/porting/transplant-thirdparty.md new file mode 100644 index 0000000000000000000000000000000000000000..ca27b2d33989ef22f963d59881cc0d317a337b35 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant-thirdparty.md @@ -0,0 +1,9 @@ +# 三方库移植指导 + +- **[概述](transplant-thirdparty-overview.md)** + +- **[CMake方式组织编译的库移植](transplant-thirdparty-cmake.md)** + +- **[Makefile方式组织编译的库移植](transplant-thirdparty-makefile.md)** + + diff --git a/zh-cn/device-dev/porting/transplant.md b/zh-cn/device-dev/porting/transplant.md new file mode 100644 index 0000000000000000000000000000000000000000..bc8d8a3ad12bef77aaf9e3f74738efe311ecb464 --- /dev/null +++ b/zh-cn/device-dev/porting/transplant.md @@ -0,0 +1,9 @@ +# 移植 + +- **[三方库移植指导](transplant-thirdparty.md)** + +- **[轻量系统芯片移植指导](transplant-minichip.md)** + +- **[小型系统芯片移植指导](transplant-smallchip.md)** + + diff --git "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" "b/zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" deleted file mode 100755 index e54970ed8fef38469f2388b352fa7df719eea4b9..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\345\272\223\347\247\273\346\244\215\346\214\207\345\257\274.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 三方库移植指导 - -- **[概述](概述.md)** - -- **[CMake方式组织编译的库移植](CMake方式组织编译的库移植.md)** - -- **[Makefile方式组织编译的库移植](Makefile方式组织编译的库移植.md)** - - diff --git "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" "b/zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" deleted file mode 100644 index 0999f32a530ac987759134af1fd23344c25eeb86..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\347\273\204\344\273\266\351\200\202\351\205\215.md" +++ /dev/null @@ -1,57 +0,0 @@ -# 三方组件适配 - -如果需要使用third\_party目录下与产品相关的三方组件,可能需要对三方组件进行适配,下面以比较常用的mbedtls为例,介绍下适配步骤,注意本小节中仅介绍如何将适配的代码与OpenHarmony的编译框架融合,不会详细介绍mbedtls本身的原理和适配代码的具体逻辑,这些内容请参考mbedtls官方网站上的适配指南。 - -1. 编写适配层代码 - - 根据mbedtls官网的适配指南,编写需要的适配层代码,以适配硬件随机数举例,下面的路径都是相对third\_party/mbedtls的路径: - - 1. 拷贝include/mbedtls/config.h到ports目录下,并修改打开MBEDTLS\_ENTROPY\_HARDWARE\_ALT开关。 - 2. 在ports目录下创建entropy\_poll\_alt.c文件include并实现entropy\_poll.h中的硬件随机数接口 - 3. 在BUILD.gn中的mbedtls\_sources中增加刚才适配的entropy\_poll\_alt.c的路径 - 4. 在BIULD.gn中的lite\_library\("mbedtls\_static"\)中增加一行MBEDTLS\_CONFIG\_FILE指定新配置文件的位置 - - ``` - lite_library("mbedtks_static") { - ... - defines += ["MBEDTLS_CONFIG_FILE=<../port/config.h>"] - ... - } - ``` - - - 注意,上面的修改最好都新建一个config或者新建一个xxx\_alt.c文件来修改,不要直接在原先的代码中修改,侵入式的修改会导致后续版本升级出现大量零散冲突,增加升级维护成本。 - -2. 制作patch - - 由于上面的适配是硬件相关的,上库代码时,不能直接放到通用的third\_party/mbedtls目录中,因此需要将上面的修改制作成patch,在编译之前通过打patch的方式注入到代码中。 - - 1. 首先增加设备的patch配置文件device///patch.yml - 2. 编辑device///patch.yml,增加要打的patch的信息: - - ``` - # 需要打patch的路径,路径均为相对代码根目录的路径 - third_party/mbedtls: - # 该路径下需要打的patch存放路径 - - device///third_party/mbedtls/adapter.patch - third_party/wpa_supplicant: - # 当一个路径下有多个patch的时候会依次执行patch - - device///third_party/wpa_supplicant/xxxxx.patch - - device///third_party/wpa_supplicant/yyyyy.patch - ... - ``` - - 3. 制作上述**步骤1**修改的patch并放到对应的目录即可 - -3. 使用带patch的编译 - - 想要在编译的时候带上patch,其他步骤不变,仅需要在触发编译的时候加上 --patch,例如全编译的命令编程 - - ``` - hb build -f --patch - ``` - - >![](public_sys-resources/icon-caution.gif) **注意:** - >最后一次打patch的产品信息会被记录,在进行下一次编译操作时,会对上一次的patch进行回退(即执行\`patch -p1 -R < xxx\`),回退patch失败或新增patch失败均会终止编译过程,请解决patch冲突后再次尝试编译。 - - diff --git "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" "b/zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" deleted file mode 100755 index c6c7b4103e7cd7eb49b8945cebf7f247a0866662..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\344\270\211\346\226\271\350\212\257\347\211\207\347\247\273\346\244\215\346\214\207\345\257\274.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 三方芯片移植指导 - -- **[移植准备](移植准备.md)** - -- **[内核移植](内核移植.md)** - -- **[板级系统移植](板级系统移植.md)** - -- **[常见问题](常见问题.md)** - - diff --git "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" "b/zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" deleted file mode 100755 index a4eaf54ec519a7bccaedea0c0295abf7029f0dd9..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\345\237\272\347\241\200\351\200\202\351\205\215.md" +++ /dev/null @@ -1,83 +0,0 @@ -# 内核基础适配 - -- [基础适配](#section14523241594) -- [特性配置项](#section112994366592) - -芯片架构适配完成后,liteos-m提供系统运行所需的系统初始化流程和定制化配置选项。移植过程中,需要关注初始化流程中跟硬件配置相关的函数;了解内核配置选项,才能裁剪出适合单板的最小内核。 - -## 基础适配 - -如下图所示,基础适配主要分为以下两步: - -1. 启动文件startup.S和相应链接配置文件。 -2. main. c中的串口初始化和tick中断注册。 - -**图 1** 启动流程 - - -![](figures/zh-cn_image_0000001073943511.png) - -启动文件startup.S需要确保中断向量表的入口函数(例如reset\_vector)放在RAM的首地址,它由链接配置文件来指定。其中iar、keil和gcc工程的链接配置文件分别为xxx.icf、xxx.sct和xxx.ld,如果startup.S已经完成系统时钟初始化,并且能够引导到main函数,则启动文件不需要进行修改,采用厂商自带的startup.S即可,否则需要实现以上功能。 - -在main.c文件中,需要关注串口初始化UartInit和系统Tick的handler函数注册。 - -- UartInit函数表示单板串口的初始化,具体的函数名根据单板自行定义。这个函数是可选的,用户可以根据硬件单板是否支持串口来自行选择调用该函数。如果硬件单板支持串口,则该函数需要完成使能串口TX和RX通道,设置波特率。 -- HalTickStart设置tick中断的handler函数OsTickHandler。 - -对于中断向量表不可重定向的芯片,需要关闭LOSCFG\_PLATFORM\_HWI宏,并且在startup.S中新增tick中断的handler函数。 - -## 特性配置项 - -liteos\_m的完整配置能力及默认配置在los\_config.h定义,该头文件中的配置项可以根据不同的单板进行裁剪配置。 - -如果针对这些配置项需要进行不同的板级配置,则可将对应的配置项直接定义到对应单板的device/xxxx/target\_config.h文件中,其他未定义的配置项,采用los\_config.h中的默认值。 - -一份典型的配置参数如下: - -**表 1** 内核典型配置项说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

配置项

-

说明

-

LOSCFG_BASE_CORE_SWTMR

-

软件定时器特性开关,1表示打开,0表示关闭

-

LOSCFG_BASE_CORE_SWTMR_ALIGN

-

对齐软件定时器特性开,1表示打开,依赖软件定时器特性打开,0表示关闭

-

LOSCFG_BASE_IPC_MUX

-

mux功能开关,1表示打开,0表示关闭

-

LOSCFG_BASE_IPC_QUEUE

-

队列功能开关,1表示打开,0表示关闭

-

LOSCFG_BASE_IPC_SEM

-

信号量功能开关,1表示打开,0表示关闭

-

LOSCFG_PLATFORM_EXC

-

异常特性开关,1表示打开,0表示关闭

-

LOSCFG_KERNEL_PRINTF

-

打印特性开关,1表示打开,0表示关闭

-
- diff --git "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" deleted file mode 100755 index 1dfe36434a1c3eca30a3dc75f0016a61730ef9e0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 内核移植 - -- **[移植概述](移植概述.md)** - -- **[内核基础适配](内核基础适配.md)** - -- **[内核移植验证](内核移植验证.md)** - - diff --git "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" "b/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" deleted file mode 100755 index 4604f13ad9b270efb67c33f186b469222f343f78..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\345\206\205\346\240\270\347\247\273\346\244\215\351\252\214\350\257\201.md" +++ /dev/null @@ -1,59 +0,0 @@ -# 内核移植验证 - -在工程device目录下添加编译main.c示例程序文件,此示例程序的主要目的是:LOS\_KernelInit完成之后,创建两个任务,循环调度延时并打印日志信息,通过此方法可以验证系统是否可正常调度以及时钟是否正常。 - -``` -VOID TaskSampleEntry2(VOID) // 任务2的入口函数 -{ - while(1) { - LOS_TaskDelay(10000); - printf("taskSampleEntry2 running...\n"); - } -} - -VOID TaskSampleEntry1(VOID) // 任务1的入口函数 -{ - while(1) { - LOS_TaskDelay(2000); - printf("taskSampleEntry1 running...\n"); - } -} - -UINT32 TaskSample(VOID) -{ - UINT32 uwRet; - UINT32 taskID1,taskID2; - TSK_INIT_PARAM_S stTask1={0}; - stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry1; - stTask1.uwStackSize = 0X1000; - stTask1.pcName = "taskSampleEntry1"; - stTask1.usTaskPrio = 6; //stTask1的任务优先级设定,不同于stTask2 - uwRet = LOS_TaskCreate(&taskID1, &stTask1); - - stTask1.pfnTaskEntry = (TSK_ENTRY_FUNC)TaskSampleEntry2; - stTask1.uwStackSize = 0X1000; - stTask1.pcName = "taskSampleEntry2"; - stTask1.usTaskPrio = 7; - uwRet = LOS_TaskCreate(&taskID2, &stTask1); - - return LOS_OK; -} - -LITE_OS_SEC_TEXT_INIT int main(void) -{ - UINT32 ret; - UartInit(); // 硬件串口配置,通过串口输出调试日志,实际函数名根据单板实现不一样而不一样。 - printf("\n\rhello world!!\n\r"); - ret = LOS_KernelInit(); - TaskSample(); - if (ret == LOS_OK) { - LOS_Start(); // 开始系统调度,循环执行stTask1/stTask2任务,串口输出任务日志 - } - while (1) { - __asm volatile("wfi"); - } -} -``` - -第一个任务运行正常后,说明最小系统的核心流程基本OK;由于xts用例框架对外依赖较多,主要是utils、bootstrap的链接脚本和编译框架,暂时无法支撑内核单独跑xts;此处略过内核测试套的测试,可以通过[XTS测试套](XTS认证.md)来覆盖最小系统是否完整移植成功。 - diff --git "a/zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" "b/zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" deleted file mode 100755 index 3029464912dea8f0226d3636d6d1a3652832dbca..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\346\235\277\347\272\247\347\263\273\347\273\237\347\247\273\346\244\215.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 板级系统移植 - -- **[移植概述](移植概述-0.md)** - -- **[板级驱动适配](板级驱动适配.md)** - -- **[HAL层实现](HAL层实现.md)** - -- **[系统组件调用](系统组件调用.md)** - -- **[三方组件适配](三方组件适配.md)** - -- **[XTS认证](XTS认证.md)** - - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" deleted file mode 100755 index 1637d5d8932e73b08d50f1060df841f64cd11698..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\345\207\206\345\244\207.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 移植准备 - -- **[移植须知](移植须知.md)** - -- **[编译构建适配流程](编译构建适配流程.md)** - - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" deleted file mode 100755 index a5d18d9bd490592858e9dcd933265965d0d04187..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,57 +0,0 @@ -# 移植概述 - -- [板级移植流程](#section1283115812294) -- [板级目录规范](#section6204129143013) - -## 板级移植流程 - -最小系统移植完成后,下一步进行板级系统移植,板级系统移植包含以下几步操作: - -1. 板级驱动适配。 -2. HAL层实现。 -3. XTS测试套。 -4. 业务功能验证。 - -**图 1** 单板驱动适配流程 -![](figures/单板驱动适配流程.png "单板驱动适配流程") - -## 板级目录规范 - -板级系统编译适配参考[编译系统介绍](编译构建适配流程.md),板级相关的驱动、SDK、目录、HAL实现存放在device目录,目录结构和具体描述如下: - -``` -. -├── device --- 单板样例 -│ └── xxx --- <单板厂商名> -│ └── xxx --- <单板名>,里面包含liteos-m内核的,并且能够运行的demo -│ ├── BUILD.gn --- 定义单板的编译配置文件 -│ ├── board --- 板子特定的实现(可选,如果本单板直接提供产品级demo,则相关应用层实现放在此目录) -│ ├── liteos_m --- 根据BUILD.gn文件中的kernel_type,使用liteos_m内核 -│ │ └── config.gni --- 编译选项 -│ ├── libraries --- 板级SDK -│ │ └── include --- SDK提供对外头文件 -│ │ └── ... --- binary or source -│ ├── main.c --- main函数入口(如果产品级存在相同定义,则使用产品级配置) -│ ├── target_config.h --- 板级内核配置 -│ ├── project --- 单板级工程配置文件(如果产品级存在相同定义,则使用产品级配置) -│ └── adapter --- 单板适配上层应用组件的适配层接口,根据能力可选 -│ └── hals -│ ├── communication -│ │ └── wifi_lite -│ │ ├── ... -│ └── iot_hardware -│ ├── upgrade -│ ├── utils -│ └── wifiiot_lite -├── vendor --- 提供端到端的OpenHarmony特性产品样例 -│ └── huawei --- 厂商名字 -│ └── wifiiot --- wifiiot表示特性产品 -│ ├── app -│ │ └── main.c --- 产品的main函数入口 -│ ├── project --- 工程配置文件 -│ ├── BUILD.gn --- 工程编译入口 -│ └── config.json --- 定义产品的编译配置文件,配置产品所使用的组件等。 -└── out --- 编译过程中的输出目录 - ├── ... --- 单板/产品编译产生的bin等 -``` - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" deleted file mode 100755 index 6f6b421748893228a5a296f4219d21a61380666c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\346\246\202\350\277\260.md" +++ /dev/null @@ -1,64 +0,0 @@ -# 移植概述 - -- [移植场景](#section93781277367) -- [目录规范](#section18127744153119) -- [芯片架构适配点](#section137431650339) - -## 移植场景 - -芯片架构适配是可选过程,如果在liteos\_m/kernel/arch目录下已经支持对应芯片架构,则可以跳过芯片架构适配,进行单板适配过程,否则需要进行芯片架构移植工作。 - -## 目录规范 - -模组芯片使用的内核为liteos-m,liteos-m中主要分为KAL、Components、Kernel和Utils四个模块。 - -- KAL模块作为内核对外的接口依赖Components模块和Kernel模块。 -- Components模块可插拔,它依赖Kernel模块。 - -- 在Kernel模块中,其中硬件相关的代码放在kernel的arch目录中,其余为硬件无关的代码。内核功能集(task、sem等)的实现依赖硬件相关的arch代码,例如任务上下文切换、原子操作等。 -- Utils模块作为基础代码块,被其他模块依赖。 - -**图 1** liteos-m内核模块图 - - -![](figures/zh-cn_image_0000001072304191.png) - -内核的目录结构和说明如下: - -``` -. -├── components --- 移植可选组件,依赖内核,单独对外提供头文件 -├── kal --- 内核抽象层,提供内核对外接口,当前支持cmsis接口和部分posix接口 -├── kernel --- 内核最小功能集代码 -│ ├── arch --- 内核指令架构层代码 -│ │ ├── arm --- arm32架构的代码 -│ │ │ ├── cortex-m3 --- cortex-m3架构的代码 -│ │ │ │ ├── iar --- iar编译工具链实现 -│ │ │ │ ├── keil --- keil编译工具链实现 -│ │ │ │ └── xxx --- xxx编译工具链实现 -│ │ │ └── cortex-m4 --- cortex-m4架构的代码 -│ │ │ ├── iar --- iar编译工具链实现 -│ │ │ ├── keil --- keil编译工具链实现 -│ │ │ └── xxx --- xxx编译工具链实现 -│ │ ├── include --- 所有的arch需要实现的函数定义,内核依赖 -│ │ └── risc-v --- risk-v架构 -│ │ └── gcc --- iar编译工具链实现 -│ ├── include --- 内核最小功能集代码 -│ └── src --- 内核最小功能集代码 -└──utils --- 基础代码,作为依赖的最底层,被系统依赖 -``` - -## 芯片架构适配点 - -如内核的[目录结构](#section18127744153119)所示,arch/include定义通用的芯片架构所需要实现的函数,另外芯片架构相关的代码会有部分的汇编代码,而汇编代码会因编译工具链的不同而不同,因此在具体的芯片架构下,还包含不同工具链(iar、keil、gcc等)的实现。 - -arch/include 目录定义通用的文件以及函数列表,该目录下的所有函数在新增arch组件时都需要适配,详见每一个头文件: - -``` -los_arch.h --- 定义芯片架构初始化所需要的函数 -los_atomic.h --- 定义芯片架构所需要实现的原子操作函数 -los_context.h --- 定义芯片架构所需要实现的任务上下文相关函数 -los_interrupt.h --- 定义芯片架构所需要实现的中断和异常相关的函数 -los_timer.h --- 定义芯片架构所需要实现的系统时钟相关的函数 -``` - diff --git "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" "b/zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" deleted file mode 100755 index b28e2b5d0ff4686dcb9b31e033dc9ce1b390475b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\347\247\273\346\244\215\351\241\273\347\237\245.md" +++ /dev/null @@ -1,84 +0,0 @@ -# 移植须知 - -- [移植目录](#section284217487490) -- [移植流程](#section639315306506) -- [移植规范](#section187870185219) - -本文为OpenHarmony平台系统开发人员和芯片(或模组)制造商提供基础的开发移植指导,典型的芯片架构例如cortex-m系列、risc-v系列等都可以按照本文进行移植,暂时不支持蓝牙服务。OpenHarmony是个持续演进的复杂项目,随着版本和API的改变,本文将会不断更新。 - -本文要求读者具有一定的嵌入式系统开发经验,因此它的重点未放在基本的OS基础介绍,而更多地描述OpenHarmony平台移植过程中主要操作和所需要关注的方面。 - -## 移植目录 - -OpenHarmony整体工程较为复杂,目录及实现为系统本身功能,如果不涉及复杂的特性增强,不需要关注每一层实现,移植过程中重点关注如下目录即可: - -**表 1** 移植过程中的重点目录 - - - - - - - - - - - - - - - - - - - -

目录名称

-

描述

-

/build/lite

-

OpenHarmony基础编译构建框架

-

/kernel/liteos_m

-

基础内核,其中芯片架构相关实现在arch目录下

-

/device

-

板级相关实现,各个三方厂商按照OpenHarmony规范适配实现,device下具体目录结构及移植过程参见板级系统移植

-

/vendor

-

产品级相关实现,主要由华为或者产品厂商贡献

-
- -device目录规则:device/\{芯片解决方案厂商\}/\{开发板\}。以hisilicon的hispark\_taurus为例: - -``` -device -└── hisilicon # 芯片解决方案厂商名 - ├── common # 芯片解决方案开发板公共部分 - └── hispark_taurus # 开发板名称 - ├── BUILD.gn # 开发板编译入口 - ├── hals # 芯片解决方案厂商OS硬件适配 - ├── linux # linux版本 - │ └── config.gni # linux版本编译工具链和编译选项配置 - └── liteos_a # liteos-a版本 - └── config.gni # liteos_a版本编译工具链和编译选项配置 -``` - -vendor目录规则:vendor/\{产品解决方案厂商\}/\{产品名称\}。以华为的wifiiot产品为例: - -``` -vendor # 产品解决方案厂商 -└── huawei # 产品解决方案厂商名称 - └── wifiiot # 产品名称 - ├── hals # 产品解决方案厂商OS适配 - ├── BUILD.gn # 产品编译脚本 - └── config.json # 产品配置文件 -``` - -## 移植流程 - -OpenHarmony的device目录是基础芯片的适配目录,如果在三方芯片应用过程中发现此目录下已经有完整的芯片适配,则不需要再额外移植,直接跳过移植过程进行系统应用开发即可,如果该目录下无对应的芯片移植实现,则根据本文完成移植过程。OpenHarmony三方芯片移植主要过程如下: - -**图 1** 芯片移植关键步骤 -![](figures/芯片移植关键步骤.png "芯片移植关键步骤") - -## 移植规范 - -- 满足OpenHarmony[开源贡献基本规范和准则](https://gitee.com/openharmony/docs/blob/master/zh-cn/contribute/%E5%8F%82%E4%B8%8E%E8%B4%A1%E7%8C%AE.md)。 -- 三方芯片适配所需要贡献的代码主要在device、vendor和arch三个目录,参照[内核目录规范](移植概述.md)和[板级目录规范](移植概述-0.md#section6204129143013)满足基本目录命名和使用规范。 - diff --git "a/zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" "b/zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" deleted file mode 100755 index 5f2a6f6f6a37ddcbaa7da689cef786fe45346751..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/porting/\347\263\273\347\273\237\347\273\204\344\273\266\350\260\203\347\224\250.md" +++ /dev/null @@ -1,26 +0,0 @@ -# 系统组件调用 - -- [SAMGR](#section105874301910) -- [DFX](#section20064420420) - -系统组件为上层应用提供基础能力,包括SAMGR(系统服务框架子系统)、DFX子系统等。在板级系统移植过程中,只需要选择使用即可,不用对其进行适配。 - -## SAMGR - -**基本介绍** - -系统服务框架基于面向服务的架构,提供了服务开发、服务的子功能开发、对外接口的开发、以及多服务共进程、进程间服务调用等开发能力。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本组件在板级系统移植中必须要使用,否则其他服务组件无法运行。 - -**SAMGR使用说明,请参考:[SAMGR 使用指导](https://gitee.com/openharmony/distributedschedule_samgr_lite/blob/master/README_zh.md)** - -## DFX - -**基本介绍** - -DFX子系统主要包含DFR(Design for Reliability,可靠性)和DFT(Design for Testability,可测试性)特性,为开发者提供代码维测信息。 - -**DFX子系统使用说明,请参考:[DFX子系统使用指导](../subsystems/DFX.md)** - diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/public_sys-resources/icon-caution.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-caution.gif rename to zh-cn/device-dev/public_sys-resources/icon-caution.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/public_sys-resources/icon-danger.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-danger.gif rename to zh-cn/device-dev/public_sys-resources/icon-danger.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-note.gif b/zh-cn/device-dev/public_sys-resources/icon-note.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-note.gif rename to zh-cn/device-dev/public_sys-resources/icon-note.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/public_sys-resources/icon-notice.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-notice.gif rename to zh-cn/device-dev/public_sys-resources/icon-notice.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/public_sys-resources/icon-tip.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-tip.gif rename to zh-cn/device-dev/public_sys-resources/icon-tip.gif diff --git a/zh-cn/device-dev/bundles/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/public_sys-resources/icon-warning.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/bundles/public_sys-resources/icon-warning.gif rename to zh-cn/device-dev/public_sys-resources/icon-warning.gif diff --git "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index 1a6f14d262b1474576a3974dff7c57b205f48aaf..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,11 +0,0 @@ -# Hi3516开发板 - -- **[安装开发板环境](安装开发板环境-2.md)** - -- **[运行Hello OHOS](运行Hello-OHOS.md)** - -- **[驱动开发示例](驱动开发示例.md)** - -- **[常见问题](常见问题-3.md)** - - diff --git "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" deleted file mode 100755 index 3e24c43eb01be574c4a48c1d9a6e10d82beeca4e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Hi3516\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" +++ /dev/null @@ -1,42 +0,0 @@ -# Hi3516开发板介绍 - -- [简介](#section26131214194212) -- [开发板规格](#section15192203316533) - -## 简介 - -Hi3516DV300作为新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP\(Image Signal Processor\)、H.265视频压缩编码器,同时集成高性能NNIE引擎,使得Hi3516DV300在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 - -**图 1** Hi3516单板正面外观图 - - -![](figures/3516正面.png) - -## 开发板规格 - -**表 1** Hi3516开发板规格清单 - - - - - - - - - - - - - -

规格类型

-

规格清单

-

处理器及内部存储

-
  • Hi3516DV300芯片
  • DDR3 1GB
  • eMMC4.5,8GB容量
-

外部器件

-
  • 以太网口
  • 音频视频
    • 1路语音输入
    • 1路单声道(AC_L)输出,接3W功放(LM4871)
    • MicroHDMI(1路HDMI 1.4)
    -
  • 摄像头
    • 传感器IMX335
    • 镜头M12,焦距4mm,光圈1.8
    -
  • 显示屏
    • LCD连接器(2.35寸)
    • LCD连接器(5.5寸)
    -
  • 外部器件及接口
    • SD卡接口
    • JTAG/I2S 接口
    • ADC接口
    • 舵机接口
    • Grove连接器
    • USB2.0(Type C)
    • 功能按键3个,2个用户自定义按键,1个升级按键
    • LED指示灯,绿灯,红灯
    -
-
- diff --git "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index 61807ea64d579d2364ff6c327864f20d8d6aaa6a..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,9 +0,0 @@ -# Hi3518开发板 - -- **[安装开发板环境](安装开发板环境-4.md)** - -- **[运行Hello OHOS](运行Hello-OHOS-5.md)** - -- **[常见问题](常见问题-6.md)** - - diff --git "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" deleted file mode 100755 index 1f77aeac075607531fb98955ef218dfd00e3c6ae..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Hi3518\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" +++ /dev/null @@ -1,57 +0,0 @@ -# Hi3518开发板介绍 - -- [简介](#section14815247616) -- [开发板规格](#section765112478446) - -## 简介 - -Hi3518EV300作为新一代智慧视觉处理SOC,集成新一代ISP\(Image Signal Processor\)以及H.265视频压缩编码器,同时采用先进低功耗工艺和低功耗架构设计,使其在低码率、高画质、低功耗等方面引领行业水平。 - -**图 1** Hi3518EV300单板正面外观图 -![](figures/Hi3518EV300单板正面外观图.png "Hi3518EV300单板正面外观图") - -**图 2** Hi3518EV300单板背面外观图 - - -![](figures/Hi3518正背面.png) - -## 开发板规格 - -**表 1** Hi3518开发板规格清单 - - - - - - - - - - - - - - - - - - - - - - -

规格类型

-

规格清单

-

处理器内核

-
  • 海思3518EV300
-

成像器件

-
  • 1/2.9 F23
-

外部接口

-
  • 外置麦克风MIC
  • 外置8Ω/1.5W扬声器
-

外部存储器接口

-
  • TF卡

    最大支持128GB(通用FAT32格式)

    -
-

WLAN协议

-
  • 支持 802.11 b/g/n
-
- diff --git "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index f6c5f5833f16ede72614678ebc0483389d9120f8..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,11 +0,0 @@ -# Hi3861开发板 - -- **[安装开发板环境](安装开发板环境.md)** - -- **[WLAN联网](WLAN联网.md)** - -- **[运行Hello World](运行Hello-World.md)** - -- **[常见问题](常见问题-1.md)** - - diff --git "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" deleted file mode 100755 index ac6a21df22f9865ab77ad461ab1805404c595d0b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Hi3861\345\274\200\345\217\221\346\235\277\344\273\213\347\273\215.md" +++ /dev/null @@ -1,157 +0,0 @@ -# Hi3861开发板介绍 - -- [简介](#section19352114194115) -- [资源和约束](#section82610215014) -- [开发板规格](#section169054431017) -- [OpenHarmony关键特性](#section1317173016507) - -## 简介 - -Hi3861 WLAN模组是一片大约2cm\*5cm大小的开发板,是一款高度集成的2.4GHz WLAN SoC芯片,集成IEEE 802.11b/g/n基带和RF(Radio Frequency)电路。支持OpenHarmony,并配套提供开放、易用的开发和调试运行环境。 - -**图 1** Hi3861 WLAN模组外观图 - - -![](figures/3861正面.png) - -另外,Hi3861 WLAN模组还可以通过与Hi3861底板连接,扩充自身的外设能力,底板如下图所示。 - -**图 2** Hi3861底板外观图 - - -![](figures/zh-cn_image_0000001174350615.png) - -- RF电路包括功率放大器PA(Power Amplifier)、低噪声放大器LNA(Low Noise Amplifier)、RF Balun、天线开关以及电源管理等模块;支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s物理层速率。 -- Hi3861 WLAN基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支持IEEE 802.11 b/g/n协议的各种数据速率。 -- Hi3861芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI(Synchronous Peripheral Interface)、UART(Universal Asynchronous Receiver & Transmitter)、I2C(The Inter Integrated Circuit)、PWM(Pulse Width Modulation)、GPIO(General Purpose Input/Output)和多路ADC(Analog to Digital Converter),同时支持高速SDIO2.0(Secure Digital Input/Output)接口,最高时钟可达50MHz;芯片内置SRAM(Static Random Access Memory)和Flash,可独立运行,并支持在Flash上运行程序。 -- Hi3861芯片适用于智能家电等物联网智能终端领域。 - - **图 3** Hi3861功能框图 - - - ![](figures/zh-cn_image_0000001128311066.png) - - -## 资源和约束 - -Hi3861 WLAN模组资源十分有限,整板共2MB FLASH,352KB RAM。在编写业务代码时,需注意资源使用效率。 - -## 开发板规格 - -**表 1** Hi3861 WLAN模组规格清单 - - - - - - - - - - - - - - - - - - - - - - - - - -

规格类型

-

规格清单

-

通用规格

-
  • 1×1 2.4GHz频段(ch1~ch14)
  • PHY支持IEEE 802.11b/g/n
  • MAC支持IEEE802.11 d/e/h/i/k/v/w
-
  • 内置PA和LNA,集成TX/RX Switch、Balun等
  • 支持STA和AP形态,作为AP时最大支持6 个STA接入
  • 支持WFA WPA/WPA2 personal、WPS2.0
  • 支持与BT/BLE芯片共存的2/3/4 线PTA方案
  • 电源电压输入范围:2.3V~3.6V
-
  • IO电源电压支持1.8V和3.3V
-
  • 支持RF自校准方案
  • 低功耗:
    • Ultra Deep Sleep模式:5μA@3.3V
    • DTIM1:1.5mA@3.3V
    • DTIM3:0.8mA@3.3V
    -
-

PHY特性

-
  • 支持IEEE802.11b/g/n单天线所有的数据速率
  • 支持最大速率:72.2Mbps@HT20 MCS7
  • 支持标准20MHz带宽和5M/10M窄带宽
  • 支持STBC
  • 支持Short-GI
-

MAC特性

-
  • 支持A-MPDU,A-MSDU
  • 支持Blk-ACK
  • 支持QoS,满足不同业务服务质量需求
-

CPU子系统

-
  • 高性能 32bit微处理器,最大工作频率160MHz
  • 内嵌SRAM 352KB、ROM 288KB
  • 内嵌 2MB Flash
-

外围接口

-
  • 1个SDIO接口、2个SPI接口、2个I2C接口、3个UART接口、15个GPIO接口、7路ADC输入、6路PWM、1个I2S接口(注:上述接口通过复用实现)
  • 外部主晶体频率40M或24M
-

其他信息

-
  • 封装:QFN-32,5mm×5mm
  • 工作温度:-40℃ ~ +85℃
-
- -## OpenHarmony关键特性 - -OpenHarmony基于Hi3861平台提供了多种开放能力,提供的关键组件如下表所示。 - -**表 2** OpenHarmony关键组件列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

组件名

-

能力介绍

-

WLAN服务

-

提供WLAN服务能力。包括:station和hotspot模式的连接、断开、状态查询等。

-

模组外设控制

-

提供操作外设的能力。包括:I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。

-

分布式软总线

-

OpenHarmony分布式网络中,提供设备被发现、数据传输的能力。

-

设备安全绑定

-

提供在设备互联场景中,数据在设备之间的安全流转的能力。

-

基础加解密

-

提供密钥管理、加解密等能力。

-

系统服务管理

-

系统服务管理基于面向服务的架构,提供了OpenHarmony统一化的系统服务开发框架。

-

启动引导

-

提供系统服务的启动入口标识。在系统服务管理启动时,调用boostrap标识的入口函数,并启动系统服务。

-

系统属性

-

提供获取与设置系统属性的能力。

-

基础库

-

提供公共基础库能力。包括:文件操作、KV存储管理等。

-

DFX

-

提供DFX能力。包括:流水日志、时间打点等。

-

XTS

-

提供OpenHarmony生态认证测试套件的集合能力。

-
- diff --git a/zh-cn/device-dev/quick-start/Readme-CN.md b/zh-cn/device-dev/quick-start/Readme-CN.md index 69991d66becb3cfef2d8980b923dc38cdd43f790..f7f7e0d9315fa2fec5ec4fa267994c5b91084c84 100644 --- a/zh-cn/device-dev/quick-start/Readme-CN.md +++ b/zh-cn/device-dev/quick-start/Readme-CN.md @@ -1,41 +1,41 @@ # 快速入门 -- [轻量和小型系统入门](轻量和小型系统入门.md) - - [概述](概述.md) - - [了解开发板](了解开发板.md) - - [Hi3861开发板介绍](Hi3861开发板介绍.md) - - [Hi3516开发板介绍](Hi3516开发板介绍.md) - - [Hi3518开发板介绍](Hi3518开发板介绍.md) +- [轻量和小型系统入门](quickstart-lite.md) + - [概述](quickstart-lite-overview.md) + - [了解开发板](quickstart-lite-introduction.md) + - [Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md) + - [Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md) + - [Hi3518开发板介绍](quickstart-lite-introduction-hi3518.md) - - [搭建系统环境](搭建系统环境.md) - - [概述](概述-0.md) - - [Windows开发环境准备](Windows开发环境准备.md) - - [Ubuntu编译环境准备](Ubuntu编译环境准备.md) - - [常见问题](常见问题.md) + - [搭建系统环境](quickstart-lite-env-setup.md) + - [概述](quickstart-lite-env-setup-des.md) + - [Windows开发环境准备](quickstart-lite-env-setup-win.md) + - [Ubuntu编译环境准备](quickstart-lite-env-setup-lin.md) + - [常见问题](quickstart-lite-env-setup-faqs.md) - - [开发步骤](开发步骤.md) - - [Hi3861开发板](Hi3861开发板.md) - - [安装开发板环境](安装开发板环境.md) - - [WLAN联网](WLAN联网.md) - - [运行Hello World](运行Hello-World.md) - - [常见问题](常见问题-1.md) + - [开发步骤](quickstart-lite-steps.md) + - [Hi3861开发板](quickstart-lite-steps-board3861.md) + - [安装开发板环境](quickstart-lite-steps-board3861-setting.md) + - [WLAN联网](quickstart-lite-steps-board3861-connection.md) + - [运行Hello World](quickstart-lite-steps-board3861-running.md) + - [常见问题](quickstart-lite-steps-board3861-faqs.md) - - [Hi3516开发板](Hi3516开发板.md) - - [安装开发板环境](安装开发板环境-2.md) - - [运行Hello OHOS](运行Hello-OHOS.md) - - [驱动开发示例](驱动开发示例.md) - - [常见问题](常见问题-3.md) + - [Hi3516开发板](quickstart-lite-steps-board3516.md) + - [安装开发板环境](quickstart-lite-steps-board3516-setting.md) + - [运行Hello OHOS](quickstart-lite-steps-board3516-running.md) + - [驱动开发示例](quickstart-lite-steps-board3516-program.md) + - [常见问题](quickstart-lite-steps-board3516-faqs.md) - - [Hi3518开发板](Hi3518开发板.md) - - [安装开发板环境](安装开发板环境-4.md) - - [运行Hello OHOS](运行Hello-OHOS-5.md) - - [常见问题](常见问题-6.md) + - [Hi3518开发板](quickstart-lite-steps-board3518.md) + - [安装开发板环境](quickstart-lite-steps-board3518-setting.md) + - [运行Hello OHOS](quickstart-lite-steps-board3518-running.md) + - [常见问题](quickstart-lite-steps-board3518-faqs.md) -- [标准系统入门](标准系统入门.md) - - [入门介绍](入门介绍.md) - - [Windows开发环境准备](Windows开发环境准备-7.md) - - [搭建Ubuntu环境及编译(Docker方式)](搭建Ubuntu环境及编译(Docker方式).md) - - [搭建Ubuntu环境及编译(安装包方式)](搭建Ubuntu环境及编译(安装包方式).md) - - [镜像烧录](镜像烧录.md) - - [常见问题](常见问题-8.md) +- [标准系统入门](quickstart-standard.md) + - [常见问题](quickstart-lite-env-setup-faqs.md) + - [Windows开发环境准备](quickstart-standard-windows-environment.md) + - [搭建Ubuntu环境及编译(Docker方式)](quickstart-standard-docker-environment.md) + - [搭建Ubuntu环境及编译(安装包方式)](quickstart-standard-package-environment.md) + - [镜像烧录](quickstart-standard-burn.md) + - [常见问题](quickstart-standard-faq.md) diff --git "a/zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100755 index 168c6184821b7c892def48d2f4c3ad5b6f055218..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Ubuntu\347\274\226\350\257\221\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,361 +0,0 @@ -# Ubuntu编译环境准备 - -- [获取软件](#section1897711811517) -- [获取源码](#section1545225464016) -- [安装和配置Python](#section1238412211211) -- [安装gn](#section29216201423) -- [安装ninja](#section8762358731) -- [安装LLVM](#section12202192215415) -- [安装hb](#section15794154618411) - - [前提条件](#section1083283711515) - - [安装方法](#section11518484814) - - [卸载方法](#section3512551574) - -- [安装其他工具](#section830511218494) - - [安装方法](#section54409586499) - - -系统要求:Ubuntu16.04及以上64位系统版本。 - -编译环境搭建分为如下几步: - -1. 获取源码 -2. 安装和配置python -3. 安装gn -4. 安装ninja -5. 安装LLVM -6. 安装hb - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 针对Ubuntu编译环境我们提供了对应的Docker,该Docker封装了相关编译工具,选择使用Docker的开发者可跳过此章节。Docker使用可参考[Docker方式获取编译环境](../get-code/Docker编译环境.md)。 ->- 通常系统默认安装samba、vim等常用软件,需要做适当适配以支持Linux服务器与Windows工作台之间的文件共享。 ->- 想要详细了解OpenHarmony编译构建模块功能的开发者可参考[编译构建使用指南](../subsystems/编译构建.md)。 - -## 获取软件 - -Linux服务器通用环境配置需要的工具及其获取途径如下表所示: - -**表 1** Linux服务器开发工具及获取途径 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

开发工具

-

用途

-

获取途径

-

源码

-

功能开发

-

参考源码获取

-

Python3.7+

-

编译构建工具

-

通过互联网获取

-

gn

-

产生ninja编译脚本

-

https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz

-

ninja

-

执行ninja编译脚本

-

https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar

-

-

LLVM

-

-

-

编译工具链

-

-

Master及OpenHarmony_v2.x分支/标签,请使用以下10.0.1版本:

-

https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz

-

OpenHarmony_v1.x分支/标签,请使用以下9.0.0版本:

-

https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar

-

hb

-

OpenHarmony编译构建命令行工具

-

通过互联网获取

-

其他工具

-

编译构建中依赖的其他工具(如打包、镜像制作等)

-

通过互联网获取

-
- ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果后续通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gn、ninja编译工具。 ->- (推荐)如果后续通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gn、ninja、LLVM编译工具。安装gn、ninja、LLVM编译工具时,请确保编译工具的环境变量路径唯一。 - -## 获取源码 - -开发者需要在Linux服务器上下载并解压一套源代码,请参见[源码获取](../get-code/源码获取.md)。 - -## 安装和配置Python - -1. 打开Linux编译服务器终端。 -2. 输入如下命令,查看python版本号,需使用python3.7以上版本。 - - ``` - python3 --version - ``` - - 如果低于python3.7版本,不建议直接升级,请按照如下步骤重新安装。以python3.8为例,按照以下步骤安装python。 - - 1. 运行如下命令,查看Ubuntu版本: - - ``` - cat /etc/issue - ``` - - 1. 根据Ubuntu不同版本,安装python。 - - 如果Ubuntu 版本为18+,运行如下命令。 - - ``` - sudo apt-get install python3.8 - ``` - - - 如果Ubuntu版本为16。 - - a. 安装依赖包 - - ``` - sudo apt update && sudo apt install software-properties-common - ``` - - b. 添加deadsnakes PPA 源,然后按回车键确认安装。 - - ``` - sudo add-apt-repository ppa:deadsnakes/ppa - ``` - - c. 安装python3.8 - - ``` - sudo apt upgrade && sudo apt install python3.8 - ``` - - - -3. 设置python和python3软链接为python3.8。 - - ``` - sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 - sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 - ``` - -4. 安装并升级Python包管理工具(pip3),任选如下一种方式。 - - **命令行方式:** - - ``` - sudo apt-get install python3-setuptools python3-pip -y - sudo pip3 install --upgrade pip - ``` - - - **安装包方式:** - - ``` - curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py - python get-pip.py - ``` - - - -## 安装gn - -1. 打开Linux编译服务器终端。 -2. [下载gn工具](https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz)。 -3. 在根目录下创建gn文件夹。 - - ``` - mkdir ~/gn - ``` - -4. 解压gn安装包至\~/gn路径下。 - - ``` - tar -xvf gn-linux-x86-1717.tar.gz -C ~/gn - ``` - -5. 设置环境变量。 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/gn:$PATH - ``` - -6. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - - -## 安装ninja - -1. 打开Linux编译服务器终端。 -2. [下载ninja工具](https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar)。 -3. 解压ninja安装包至\~/ninja路径下。 - - ``` - tar -xvf ninja.1.9.0.tar -C ~/ - ``` - -4. 设置环境变量。 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/ninja:$PATH - ``` - -5. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - - -## 安装LLVM - -1. 打开Linux编译服务器终端。 -2. [下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz)。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >针对OpenHarmony\_v1.x分支/标签,使用此链接[下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar)。 - -3. 解压LLVM安装包至\~/llvm路径下。 - - ``` - tar -zxvf llvm.tar.gz -C ~/ - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >针对OpenHarmony\_v1.x分支/标签,使用如下命令解压: - >``` - >tar -xvf llvm-linux-9.0.0-36191.tar -C ~/ - >``` - -4. 设置环境变量。 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/llvm/bin:$PATH - ``` - -5. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - - -## 安装hb - -### 前提条件 - -请先安装Python 3.7.4及以上版本,请见[安装和配置Python](#section1238412211211)。 - -### 安装方法 - -1. 运行如下命令安装hb - - ``` - python3 -m pip install --user ohos-build - ``` - -2. 设置环境变量 - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/.local/bin:$PATH - ``` - - 执行如下命令更新环境变量。 - - ``` - source ~/.bashrc - ``` - -3. 执行"hb -h",有打印以下信息即表示安装成功: - - ``` - 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 - ``` - - -### 卸载方法 - -``` -python3 -m pip uninstall ohos-build -``` - ->![](public_sys-resources/icon-notice.gif) **须知:** ->如果安装hb的过程中遇到问题,请参见下文[常见问题](常见问题.md)进行解决。 - -## 安装其他工具 - -### 安装方法 - -1. apt安装全部依赖的工具 - - ``` - sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils - ``` - - diff --git "a/zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" "b/zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" deleted file mode 100755 index ab20f083f914b8a49bf99109750a3f6dd9cb1e0e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/WLAN\350\201\224\347\275\221.md" +++ /dev/null @@ -1,142 +0,0 @@ -# WLAN联网 - -- [源码编译](#section191121332125319) -- [镜像烧录](#section19458165166) -- [WLAN模组联网](#section194671619167) - -本示例将演示如何通过AT命令完成WLAN模组与网关联网。 - -## 源码编译 - -本节描述如何在Linux服务器上进行WLAN模组版本的编译。 - -如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/Docker编译环境.md)的编译操作。如果Linux编译环境通过软件包方式安装,请参考如下步骤。 - -1. 打开DevEco Device Tool工具,点击“View \> Terminal”,进入终端界面。 - - **图 1** IDE终端工具打开方法 - - - ![](figures/1.png) - - 在终端界面使用ssh命令连接linux服务器,如“ssh user@ipaddr”。 - - **图 2** 终端界面示意图 - - - ![](figures/2.png) - -2. 进入代码根路径,并在终端窗口,执行脚本命令“hb set”、“.”,选择需要编译的版本“wifiiot\_hispark\_pegasus”。 - - **图 3** 在终端界面选择目标构建版本示意图 - - - ![](figures/3.png) - -3. 执行“hb build”启动版本构建。 - - **图 4** 在终端界面执行编译命令示意图 - - - ![](figures/4.png) - -4. 编译结束后,如果出现“wifiiot\_hispark\_pegasus build success”字样,则证明构建成功,如下图所示。 - - **图 5** 编译成功示意图 - - - ![](figures/5.png) - -5. 构建成功后,会在./out/wifiiot/路径中生成以下文件,使用如下命令可以查看,至此编译构建流程结束。 - - ``` - ls -l out/hispark_pegasus/wifiiot_hispark_pegasus/ - ``` - - **图 6** 编译文件存放目录示意图 - - - ![](figures/3-0.png) - - -## 镜像烧录 - -Hi3861 WLAN模组的镜像烧录可以通过OpenHarmony IDE工具DevEco完成,工具的基本使用请参考[DevEco Device Tool使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),烧录过程包含如下步骤。 - -1. 请连接好电脑和待烧录开发板,需要连接USB口,具体可参考[Hi3861开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3861-0000001105041324)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3861系列开发板串口驱动安装](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3861-drivers-0000001058153433)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001128311118.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/zh-cn_image_0000001128311116.png) - -4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3861系列开发板进行适配,无需单独修改。 -5. 在“hi3861”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001056563976_li848662117291)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“burn-serial”。 - - upload\_partitions:选择待烧录的文件,默认选择hi3861\_app。 - - ![](figures/zh-cn_image_0000001128470922.png) - -6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -7. 打开工程文件,在DevEco Device Tool界面的“PROJECT TASKS”中,点击hi3861下的**Upload**按钮,启动烧录。 - - ![](figures/zh-cn_image_0000001174270749.png) - -8. 启动烧录后,显示如下提示信息时,请按开发板上的RST按钮重启开发板。 - - ![](figures/zh-cn_image_0000001174270751.png) - -9. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001174350669.png) - - -## WLAN模组联网 - -完成版本构建及烧录后,下面开始介绍如何在串口终端上执行AT命令,使WLAN模组联网。 - -1. 保持Windows工作台和WLAN模组的连接状态,在DevEco工具最下方,点击“DevEco:Serial Monitor”按钮。 - - **图 7** 打开DevEco串口终端示意图 - - - ![](figures/5-1.png) - -2. 复位WLAN模组,终端界面显示“ready to OS start”,则启动成功。 - - **图 8** WLAN复位成功示意图 - - - ![](figures/6.png) - -3. 在DevEco的串口终端中,依次执行如下AT命令,启动STA模式,连接指定AP热点,并开启DHCP功能。 - - ``` - AT+STARTSTA # 启动STA模式 - AT+SCAN # 扫描周边AP - AT+SCANRESULT # 显示扫描结果 - AT+CONN="SSID",,2,"PASSWORD" # 连接指定AP,其中SSID/PASSWORD为待连接的热点名称和密码 - AT+STASTAT # 查看连接结果 - AT+DHCP=wlan0,1 # 通过DHCP向AP请求wlan0的IP地址 - ``` - -4. 查看WLAN模组与网关联通是否正常,如下图所示。 - - ``` - AT+IFCFG # 查看模组接口IP - AT+PING=X.X.X.X # 检查模组与网关的联通性,其中X.X.X.X需替换为实际的网关地址 - ``` - - **图 9** WLAN模组联网成功示意图 - - - ![](figures/截图.png) - - diff --git "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" "b/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" deleted file mode 100644 index bb7588a5ce8be87185e5d16a0a815ba8c342c87c..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207-7.md" +++ /dev/null @@ -1,176 +0,0 @@ -# Windows开发环境准备 - -- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) -- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) -- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) -- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) -- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) -- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) - -系统要求:Windows 10 64位系统。 - -DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: - -1. 安装Visual Studio Code -2. 安装Python -3. 安装Node.js -4. 安装hpm -5. 安装DevEco Device Tool插件 - -## 获取软件 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

工具名称

-

用途说明

-

版本要求

-

获取渠道

-

Visual Studio Code

-

代码编辑工具

-

V1.53及以上 64位版本。

-

https://code.visualstudio.com/Download

-

Python

-

编译构建工具

-

V3.7.4~V3.8.x 64位版本

-

https://www.python.org/downloads/

-

Node.js

-

提供npm环境

-

v12.0.0及以上 64位版本

-

https://nodejs.org/zh-cn/download/

-

hpm

-

包管理工具

-

最新版

-

请参考安装hpm

-

DevEco Device Tool

-

OpenHarmony源码的编译、烧录、调试插件工具

-

v2.2 Beta1

-

https://device.harmonyos.com/cn/ide#download

-

下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

-
- -## 安装Visual Studio Code - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 - -1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 - - ![](figures/zh-cn_image_0000001057335403.png) - -2. 安装完成后,打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 - -## 安装Python - -1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 - - ![](figures/zh-cn_image_0000001176317561.png) - -2. 等待安装完成后,点击**Close**。 - - ![](figures/zh-cn_image_0000001142794291.png) - -3. 打开命令行工具,输入python --version,检查安装结果。 - - ![](figures/zh-cn_image_0000001130278040.png) - -4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 - - ``` - pip config set global.trusted-host repo.huaweicloud.com - pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple - pip config set global.timeout 120 - ``` - - -## 安装Node.js - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 - -1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 -2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 - -## 安装hpm - -该方式需先确保**Node.js**安装成功。 - -在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 - -1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 - - ``` - npm config set registry https://repo.huaweicloud.com/repository/npm/ - ``` - -2. 打开命令行工具,执行如下命令安装最新版本hpm。 - - ``` - npm install -g @ohos/hpm-cli - ``` - - ![](figures/zh-cn_image_0000001073840162.png) - -3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 - - ``` - hpm -V - ``` - - -## 安装DevEco Device Tool插件 - -安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 - -DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->安装DevEco Device Tool时,请先关闭Visual Studio Code。 - -1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 -2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 - - ![](figures/zh-cn_image_0000001072468991.png) - -3. 安装完成后,会自动关闭命令行工具窗口。 -4. 启动Visual Studio Code,点击左侧的![](figures/zh-cn_image_0000001072757874.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 - - ![](figures/zh-cn_image_0000001142802505.png) - - diff --git "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" "b/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" deleted file mode 100755 index cffea83cad92e78f19cdb4222117b2c8c75902f0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/Windows\345\274\200\345\217\221\347\216\257\345\242\203\345\207\206\345\244\207.md" +++ /dev/null @@ -1,182 +0,0 @@ -# Windows开发环境准备 - -- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) -- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) -- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) -- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) -- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) -- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) - -系统要求:Windows 10 64位系统。 - -DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: - -1. 安装Visual Studio Code -2. 安装Python -3. 安装Node.js -4. 安装hpm -5. 安装DevEco Device Tool插件 - -## 获取软件 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

工具名称

-

用途说明

-

版本要求

-

获取渠道

-

Visual Studio Code

-

代码编辑工具

-

V1.53及以上 64位版本。

-

https://code.visualstudio.com/Download

-

Python

-

编译构建工具

-

V3.7.4~V3.8.x 64位版本

-

推荐下载:https://www.python.org/downloads/release/python-388/

-

Node.js

-

提供npm环境

-

v12.0.0及以上 64位版本

-

https://nodejs.org/zh-cn/download/

-

hpm

-

包管理工具

-

最新版

-

请参考安装hpm

-

DevEco Device Tool

-

OpenHarmony源码的编译、烧录、调试插件工具

-

v2.2 Beta1

-

https://device.harmonyos.com/cn/ide#download

-

下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

-
- -## 安装Visual Studio Code - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 - -1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 - - ![](figures/zh-cn_image_0000001174350653.png) - -2. 安装完成后,重启计算机,使Visual Studio Code的环境变量生效。 -3. 打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 - -## 安装Python - -1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 - - ![](figures/zh-cn_image_0000001128470908.png) - -2. 等待安装完成后,点击**Close**。 - - ![](figures/zh-cn_image_0000001128311104.png) - -3. 打开命令行工具,输入python --version,检查安装结果。 - - ![](figures/zh-cn_image_0000001174350655.png) - -4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 - - ``` - pip config set global.trusted-host repo.huaweicloud.com - pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple - pip config set global.timeout 120 - ``` - - -## 安装Node.js - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 - -1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 -2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 - - ![](figures/zh-cn_image_0000001128311096.png) - - -## 安装hpm - -该方式需先确保**Node.js**安装成功。 - -在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 - -1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 - - ``` - npm config set registry https://repo.huaweicloud.com/repository/npm/ - ``` - -2. 打开命令行工具,执行如下命令安装最新版本hpm。 - - ``` - npm install -g @ohos/hpm-cli - ``` - - ![](figures/zh-cn_image_0000001128311100.png) - -3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 - - ``` - hpm -V - ``` - - ![](figures/zh-cn_image_0000001174270735.png) - - -## 安装DevEco Device Tool插件 - -安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 - -DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->安装DevEco Device Tool时,请先关闭Visual Studio Code。 - -1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 -2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 - - ![](figures/zh-cn_image_0000001128470902.png) - -3. 安装完成后,会自动关闭命令行工具窗口。 -4. 启动Visual Studio Code,点击左侧的![](figures/zh-cn_image_0000001174350651.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 - - ![](figures/zh-cn_image_0000001174270727.png) - - diff --git a/zh-cn/device-dev/quick-start/figures/1.png b/zh-cn/device-dev/quick-start/figure/1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/1.png rename to zh-cn/device-dev/quick-start/figure/1.png diff --git a/zh-cn/device-dev/quick-start/figures/10.png b/zh-cn/device-dev/quick-start/figure/10.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/10.png rename to zh-cn/device-dev/quick-start/figure/10.png diff --git a/zh-cn/device-dev/quick-start/figures/2.png b/zh-cn/device-dev/quick-start/figure/2.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2.png rename to zh-cn/device-dev/quick-start/figure/2.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334-17.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334-16.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334-17.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334-16.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334-2.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334-2.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334-2.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334-2.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334-5.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334-5.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334-5.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334-5.png diff --git a/zh-cn/device-dev/quick-start/figures/2021-01-27_170334.png b/zh-cn/device-dev/quick-start/figure/2021-01-27_170334.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/2021-01-27_170334.png rename to zh-cn/device-dev/quick-start/figure/2021-01-27_170334.png diff --git a/zh-cn/device-dev/quick-start/figures/3-0.png b/zh-cn/device-dev/quick-start/figure/3-0.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/3-0.png rename to zh-cn/device-dev/quick-start/figure/3-0.png diff --git a/zh-cn/device-dev/quick-start/figures/3.png b/zh-cn/device-dev/quick-start/figure/3.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/3.png rename to zh-cn/device-dev/quick-start/figure/3.png diff --git "a/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242.png" "b/zh-cn/device-dev/quick-start/figure/3516\346\255\243\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242.png" rename to "zh-cn/device-dev/quick-start/figure/3516\346\255\243\351\235\242.png" diff --git "a/zh-cn/device-dev/quick-start/figures/3861\346\255\243\351\235\242.png" "b/zh-cn/device-dev/quick-start/figure/3861\346\255\243\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/3861\346\255\243\351\235\242.png" rename to "zh-cn/device-dev/quick-start/figure/3861\346\255\243\351\235\242.png" diff --git a/zh-cn/device-dev/quick-start/figures/4.png b/zh-cn/device-dev/quick-start/figure/4.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/4.png rename to zh-cn/device-dev/quick-start/figure/4.png diff --git a/zh-cn/device-dev/quick-start/figures/5-1.png b/zh-cn/device-dev/quick-start/figure/5-1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/5-1.png rename to zh-cn/device-dev/quick-start/figure/5-1.png diff --git a/zh-cn/device-dev/quick-start/figures/5.png b/zh-cn/device-dev/quick-start/figure/5.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/5.png rename to zh-cn/device-dev/quick-start/figure/5.png diff --git a/zh-cn/device-dev/quick-start/figures/6.png b/zh-cn/device-dev/quick-start/figure/6.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/6.png rename to zh-cn/device-dev/quick-start/figure/6.png diff --git "a/zh-cn/device-dev/quick-start/figures/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/Hi3518EV300\345\215\225\346\235\277\346\255\243\351\235\242\345\244\226\350\247\202\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/Hi3518\346\255\243\350\203\214\351\235\242.png" "b/zh-cn/device-dev/quick-start/figure/Hi3518\346\255\243\350\203\214\351\235\242.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/Hi3518\346\255\243\350\203\214\351\235\242.png" rename to "zh-cn/device-dev/quick-start/figure/Hi3518\346\255\243\350\203\214\351\235\242.png" diff --git "a/zh-cn/device-dev/quick-start/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" "b/zh-cn/device-dev/quick-start/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" rename to "zh-cn/device-dev/quick-start/figure/SCons\345\256\211\350\243\205\346\210\220\345\212\237\347\225\214\351\235\242-\347\211\210\346\234\254\350\246\201\346\261\2023-0-4\344\273\245\344\270\212.png" diff --git "a/zh-cn/device-dev/quick-start/figures/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/U-boot\347\203\247\345\206\231\345\256\214\346\210\220\344\270\262\345\217\243\346\230\276\347\244\272\345\233\276.png" diff --git a/zh-cn/device-dev/quick-start/figures/changjian1-10.png b/zh-cn/device-dev/quick-start/figure/changjian1-10.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/changjian1-10.png rename to zh-cn/device-dev/quick-start/figure/changjian1-10.png diff --git a/zh-cn/device-dev/quick-start/figures/changjian1.png b/zh-cn/device-dev/quick-start/figure/changjian1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/changjian1.png rename to zh-cn/device-dev/quick-start/figure/changjian1.png diff --git a/zh-cn/device-dev/quick-start/figures/chuankou1-6.png b/zh-cn/device-dev/quick-start/figure/chuankou1-6.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/chuankou1-6.png rename to zh-cn/device-dev/quick-start/figure/chuankou1-6.png diff --git a/zh-cn/device-dev/quick-start/figures/chuankou1.png b/zh-cn/device-dev/quick-start/figure/chuankou1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/chuankou1.png rename to zh-cn/device-dev/quick-start/figure/chuankou1.png diff --git a/zh-cn/device-dev/quick-start/figures/qi1.png b/zh-cn/device-dev/quick-start/figure/qi1.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/qi1.png rename to zh-cn/device-dev/quick-start/figure/qi1.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001057335403.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001057335403.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001057335403.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001057335403.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072468991.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072468991.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072468991.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072468991.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072757874.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072757874.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001072757874.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001072757874.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001073840162.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001073840162.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001073840162.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001073840162.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001113969542.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001113969542.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001113969542.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001113969542.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129428.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129428.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129428.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129428.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129432.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129432.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001114129432.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001114129432.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117463460.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117463460.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117463460.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117463460.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117621400.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117621400.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001117621400.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001117621400.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311066.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311066.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311066.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311066.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311070.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311070.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311070.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311070.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311072.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311072.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311072.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311072.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311090.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311090.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311090.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311090.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311092.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311092.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311092.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311092.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311094.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311094.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311094.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311094.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311096.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311096.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311096.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311096.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311098.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311098.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311098.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311098.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311100.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311100.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311100.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311100.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311104.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311104.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311104.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311104.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311116.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311116.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311116.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311116.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311118.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311118.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128311118.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128311118.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470864.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470864.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470864.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470864.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470880.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470880.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470880.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470880.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470900.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470900.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470900.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470900.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470902.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470902.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470902.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470902.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470904.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470904.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470904.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470904.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470906.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470906.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470906.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470906.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470908.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470908.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470908.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470908.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470922.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470922.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001128470922.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001128470922.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130278040.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130278040.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130278040.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130278040.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130584312.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130584312.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001130584312.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001130584312.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142794291.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142794291.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142794291.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142794291.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142802505.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142802505.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001142802505.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001142802505.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270699.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270699.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270699.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270699.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270713.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270713.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270713.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270713.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270715.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270715.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270715.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270715.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270727.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270727.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270727.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270727.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270729.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270729.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270729.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270729.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270731.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270731.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270731.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270731.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270733.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270733.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270733.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270733.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270735.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270735.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270735.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270735.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270737.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270737.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270737.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270737.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270739.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270739.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270739.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270739.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270743.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270743.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270743.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270743.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270749.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270749.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270749.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270749.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270751.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270751.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174270751.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174270751.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350615.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350615.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350615.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350615.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350623.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350623.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350623.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350623.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350633.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350633.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350633.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350633.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350641.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350641.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350641.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350641.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350643.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350643.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350643.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350643.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350647.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350647.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350647.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350647.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350649.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350649.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350649.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350649.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350651.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350651.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350651.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350651.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350653.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350653.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350653.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350653.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350655.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350655.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350655.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350655.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350659.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350659.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350659.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350659.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350661.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350661.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350661.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350661.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350669.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350669.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001174350669.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001174350669.png diff --git a/zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001176317561.png b/zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001176317561.png similarity index 100% rename from zh-cn/device-dev/quick-start/figures/zh-cn_image_0000001176317561.png rename to zh-cn/device-dev/quick-start/figure/zh-cn_image_0000001176317561.png diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234-15.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\201\350\256\270Visual-Studio-Code\345\272\224\347\224\250\350\256\277\351\227\256\347\275\221\347\273\234.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257-9.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" "b/zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" rename to "zh-cn/device-dev/quick-start/figure/\345\205\263\351\227\255\344\270\262\345\217\243\347\273\210\347\253\257.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\345\271\266\346\210\220\345\212\237\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\345\220\257\345\212\250\346\210\220\345\212\237\345\271\266\346\211\247\350\241\214\345\272\224\347\224\250\347\250\213\345\272\217\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\210\252\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\346\210\252\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\210\252\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\346\210\252\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" "b/zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" rename to "zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276-7.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\346\211\223\345\274\200\344\270\262\345\217\243\345\244\261\350\264\245\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276-14.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276Visual-Studio-Code\345\272\224\347\224\250\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257-8.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" "b/zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" rename to "zh-cn/device-dev/quick-start/figure/\346\237\245\346\211\276\346\230\257\345\220\246\345\255\230\345\234\250\345\215\240\347\224\250\344\270\262\345\217\243\347\232\204\347\273\210\347\253\257.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" "b/zh-cn/device-dev/quick-start/figure/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" rename to "zh-cn/device-dev/quick-start/figure/\347\237\251\345\275\242\345\244\207\344\273\275-292.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" "b/zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" rename to "zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276-3.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\347\241\254\344\273\266\350\277\236\347\272\277\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276-11.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\344\270\215\351\200\232-\345\215\225\346\235\277\346\227\240\346\263\225\350\216\267\345\217\226\346\226\207\344\273\266\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276-12.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\347\275\221\347\273\234\351\230\262\347\201\253\345\242\231\350\256\276\347\275\256\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" "b/zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" rename to "zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213-4.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213.png" "b/zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\350\256\276\347\275\256\345\233\276\344\276\213.png" rename to "zh-cn/device-dev/quick-start/figure/\350\256\276\347\275\256\345\233\276\344\276\213.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" "b/zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" rename to "zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276-13.png" diff --git "a/zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" "b/zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/figures/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" rename to "zh-cn/device-dev/quick-start/figure/\351\230\262\347\201\253\345\242\231\345\222\214\347\275\221\347\273\234\344\277\235\346\212\244\347\225\214\351\235\242\345\233\276.png" diff --git "a/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242-16.png" "b/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242-16.png" deleted file mode 100644 index 6975fb5fef92e35dec2de84b7e7035a39794bdf4..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/quick-start/figures/3516\346\255\243\351\235\242-16.png" and /dev/null differ diff --git "a/zh-cn/device-dev/quick-start/figures/\346\240\207\345\207\206\347\216\257\345\242\203\345\277\253\351\200\237\345\205\245\351\227\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/quick-start/figures/\346\240\207\345\207\206\347\216\257\345\242\203\345\277\253\351\200\237\345\205\245\351\227\250\346\265\201\347\250\213.png" deleted file mode 100644 index 587b414d787f36de3494760e14313e0ff18f896b..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/quick-start/figures/\346\240\207\345\207\206\347\216\257\345\242\203\345\277\253\351\200\237\345\205\245\351\227\250\346\265\201\347\250\213.png" and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-note.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/quick-start/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/quick-start/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/quick-start/public_sys-resources/icon-warning.gif and /dev/null differ diff --git "a/zh-cn/device-dev/quick-start/\346\246\202\350\277\260-0.md" b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-des.md similarity index 100% rename from "zh-cn/device-dev/quick-start/\346\246\202\350\277\260-0.md" rename to zh-cn/device-dev/quick-start/quickstart-lite-env-setup-des.md diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/quick-start/quickstart-lite-env-setup-faqs.md diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md new file mode 100644 index 0000000000000000000000000000000000000000..ddd8fd5f4fb8249098c4bf7d00ecb4d697e9cbaf --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-lin.md @@ -0,0 +1,361 @@ +# Ubuntu编译环境准备 + +- [获取软件](#section1897711811517) +- [获取源码](#section1545225464016) +- [安装和配置Python](#section1238412211211) +- [安装gn](#section29216201423) +- [安装ninja](#section8762358731) +- [安装LLVM](#section12202192215415) +- [安装hb](#section15794154618411) + - [前提条件](#section1083283711515) + - [安装方法](#section11518484814) + - [卸载方法](#section3512551574) + +- [安装其他工具](#section830511218494) + - [安装方法](#section54409586499) + + +系统要求:Ubuntu16.04及以上64位系统版本。 + +编译环境搭建分为如下几步: + +1. 获取源码 +2. 安装和配置python +3. 安装gn +4. 安装ninja +5. 安装LLVM +6. 安装hb + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 针对Ubuntu编译环境我们提供了对应的Docker,该Docker封装了相关编译工具,选择使用Docker的开发者可跳过此章节。Docker使用可参考[Docker方式获取编译环境](../get-code/gettools-acquire.md)。 +>- 通常系统默认安装samba、vim等常用软件,需要做适当适配以支持Linux服务器与Windows工作台之间的文件共享。 +>- 想要详细了解OpenHarmony编译构建模块功能的开发者可参考[编译构建使用指南](../subsystems/subsys-build-mini-lite.md)。 + +## 获取软件 + +Linux服务器通用环境配置需要的工具及其获取途径如下表所示: + +**表 1** Linux服务器开发工具及获取途径 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

开发工具

+

用途

+

获取途径

+

源码

+

功能开发

+

参考源码获取

+

Python3.7+

+

编译构建工具

+

通过互联网获取

+

gn

+

产生ninja编译脚本

+

https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz

+

ninja

+

执行ninja编译脚本

+

https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar

+

+

LLVM

+

+

+

编译工具链

+

+

Master及OpenHarmony_v2.x分支/标签,请使用以下10.0.1版本:

+

https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz

+

OpenHarmony_v1.x分支/标签,请使用以下9.0.0版本:

+

https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar

+

hb

+

OpenHarmony编译构建命令行工具

+

通过互联网获取

+

其他工具

+

编译构建中依赖的其他工具(如打包、镜像制作等)

+

通过互联网获取

+
+ +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果后续通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gn、ninja编译工具。 +>- (推荐)如果后续通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gn、ninja、LLVM编译工具。安装gn、ninja、LLVM编译工具时,请确保编译工具的环境变量路径唯一。 + +## 获取源码 + +开发者需要在Linux服务器上下载并解压一套源代码,请参见[源码获取](../get-code/sourcecode-acquire.md)。 + +## 安装和配置Python + +1. 打开Linux编译服务器终端。 +2. 输入如下命令,查看python版本号,需使用python3.7以上版本。 + + ``` + python3 --version + ``` + + 如果低于python3.7版本,不建议直接升级,请按照如下步骤重新安装。以python3.8为例,按照以下步骤安装python。 + + 1. 运行如下命令,查看Ubuntu版本: + + ``` + cat /etc/issue + ``` + + 1. 根据Ubuntu不同版本,安装python。 + - 如果Ubuntu 版本为18+,运行如下命令。 + + ``` + sudo apt-get install python3.8 + ``` + + - 如果Ubuntu版本为16。 + + a. 安装依赖包 + + ``` + sudo apt update && sudo apt install software-properties-common + ``` + + b. 添加deadsnakes PPA 源,然后按回车键确认安装。 + + ``` + sudo add-apt-repository ppa:deadsnakes/ppa + ``` + + c. 安装python3.8 + + ``` + sudo apt upgrade && sudo apt install python3.8 + ``` + + + +3. 设置python和python3软链接为python3.8。 + + ``` + sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.8 1 + sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.8 1 + ``` + +4. 安装并升级Python包管理工具(pip3),任选如下一种方式。 + - **命令行方式:** + + ``` + sudo apt-get install python3-setuptools python3-pip -y + sudo pip3 install --upgrade pip + ``` + + - **安装包方式:** + + ``` + curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py + python get-pip.py + ``` + + + +## 安装gn + +1. 打开Linux编译服务器终端。 +2. [下载gn工具](https://repo.huaweicloud.com/harmonyos/compiler/gn/1717/linux/gn-linux-x86-1717.tar.gz)。 +3. 在根目录下创建gn文件夹。 + + ``` + mkdir ~/gn + ``` + +4. 解压gn安装包至\~/gn路径下。 + + ``` + tar -xvf gn-linux-x86-1717.tar.gz -C ~/gn + ``` + +5. 设置环境变量。 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/gn:$PATH + ``` + +6. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + + +## 安装ninja + +1. 打开Linux编译服务器终端。 +2. [下载ninja工具](https://repo.huaweicloud.com/harmonyos/compiler/ninja/1.9.0/linux/ninja.1.9.0.tar)。 +3. 解压ninja安装包至\~/ninja路径下。 + + ``` + tar -xvf ninja.1.9.0.tar -C ~/ + ``` + +4. 设置环境变量。 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/ninja:$PATH + ``` + +5. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + + +## 安装LLVM + +1. 打开Linux编译服务器终端。 +2. [下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/10.0.1-62608/linux/llvm.tar.gz)。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >针对OpenHarmony\_v1.x分支/标签,使用此链接[下载LLVM工具](https://repo.huaweicloud.com/harmonyos/compiler/clang/9.0.0-36191/linux/llvm-linux-9.0.0-36191.tar)。 + +3. 解压LLVM安装包至\~/llvm路径下。 + + ``` + tar -zxvf llvm.tar.gz -C ~/ + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >针对OpenHarmony\_v1.x分支/标签,使用如下命令解压: + >``` + >tar -xvf llvm-linux-9.0.0-36191.tar -C ~/ + >``` + +4. 设置环境变量。 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/llvm/bin:$PATH + ``` + +5. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + + +## 安装hb + +### 前提条件 + +请先安装Python 3.7.4及以上版本,请见[安装和配置Python](#section1238412211211)。 + +### 安装方法 + +1. 运行如下命令安装hb + + ``` + python3 -m pip install --user ohos-build + ``` + +2. 设置环境变量 + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/.local/bin:$PATH + ``` + + 执行如下命令更新环境变量。 + + ``` + source ~/.bashrc + ``` + +3. 执行"hb -h",有打印以下信息即表示安装成功: + + ``` + 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 + ``` + + +### 卸载方法 + +``` +python3 -m pip uninstall ohos-build +``` + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>如果安装hb的过程中遇到问题,请参见下文[常见问题](quickstart-lite-env-setup-faqs.md)进行解决。 + +## 安装其他工具 + +### 安装方法 + +1. apt安装全部依赖的工具 + + ``` + sudo apt-get install build-essential gcc g++ make zlib* libffi-dev e2fsprogs pkg-config flex bison perl bc openssl libssl-dev libelf-dev libc6-dev-amd64 binutils binutils-dev libdwarf-dev u-boot-tools mtd-utils gcc-arm-linux-gnueabi + ``` + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md new file mode 100644 index 0000000000000000000000000000000000000000..7f51e21e0b4a80f2d6044c50c05f83b4885fa31f --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup-win.md @@ -0,0 +1,182 @@ +# Windows开发环境准备 + +- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) +- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) +- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) +- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) +- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) +- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) + +系统要求:Windows 10 64位系统。 + +DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: + +1. 安装Visual Studio Code +2. 安装Python +3. 安装Node.js +4. 安装hpm +5. 安装DevEco Device Tool插件 + +## 获取软件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

工具名称

+

用途说明

+

版本要求

+

获取渠道

+

Visual Studio Code

+

代码编辑工具

+

V1.53及以上 64位版本。

+

https://code.visualstudio.com/Download

+

Python

+

编译构建工具

+

V3.7.4~V3.8.x 64位版本

+

推荐下载:https://www.python.org/downloads/release/python-388/

+

Node.js

+

提供npm环境

+

v12.0.0及以上 64位版本

+

https://nodejs.org/zh-cn/download/

+

hpm

+

包管理工具

+

最新版

+

请参考安装hpm

+

DevEco Device Tool

+

OpenHarmony源码的编译、烧录、调试插件工具

+

v2.2 Beta1

+

https://device.harmonyos.com/cn/ide#download

+

下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

+
+ +## 安装Visual Studio Code + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 + +1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 + + ![](figure/zh-cn_image_0000001174350653.png) + +2. 安装完成后,重启计算机,使Visual Studio Code的环境变量生效。 +3. 打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 + +## 安装Python + +1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 + + ![](figure/zh-cn_image_0000001128470908.png) + +2. 等待安装完成后,点击**Close**。 + + ![](figure/zh-cn_image_0000001128311104.png) + +3. 打开命令行工具,输入python --version,检查安装结果。 + + ![](figure/zh-cn_image_0000001174350655.png) + +4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 + + ``` + pip config set global.trusted-host repo.huaweicloud.com + pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple + pip config set global.timeout 120 + ``` + + +## 安装Node.js + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 + +1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 +2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 + + ![](figure/zh-cn_image_0000001128311096.png) + + +## 安装hpm + +该方式需先确保**Node.js**安装成功。 + +在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 + +1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 + + ``` + npm config set registry https://repo.huaweicloud.com/repository/npm/ + ``` + +2. 打开命令行工具,执行如下命令安装最新版本hpm。 + + ``` + npm install -g @ohos/hpm-cli + ``` + + ![](figure/zh-cn_image_0000001128311100.png) + +3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 + + ``` + hpm -V + ``` + + ![](figure/zh-cn_image_0000001174270735.png) + + +## 安装DevEco Device Tool插件 + +安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 + +DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>安装DevEco Device Tool时,请先关闭Visual Studio Code。 + +1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 +2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 + + ![](figure/zh-cn_image_0000001128470902.png) + +3. 安装完成后,会自动关闭命令行工具窗口。 +4. 启动Visual Studio Code,点击左侧的![](figure/zh-cn_image_0000001174350651.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 + + ![](figure/zh-cn_image_0000001174270727.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md new file mode 100644 index 0000000000000000000000000000000000000000..f5782f2a9f8bfcd10518821f6e700751928e9491 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-env-setup.md @@ -0,0 +1,11 @@ +# 搭建系统环境 + +- **[概述](quickstart-lite-env-setup-des.md)** + +- **[Windows开发环境准备](quickstart-lite-env-setup-win.md)** + +- **[Ubuntu编译环境准备](quickstart-lite-env-setup-lin.md)** + +- **[常见问题](quickstart-lite-env-setup-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md new file mode 100644 index 0000000000000000000000000000000000000000..1224e4f34641a9e46d69354db9acf0a7d5cf06a3 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3516.md @@ -0,0 +1,42 @@ +# Hi3516开发板介绍 + +- [简介](#section26131214194212) +- [开发板规格](#section15192203316533) + +## 简介 + +Hi3516DV300作为新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP\(Image Signal Processor\)、H.265视频压缩编码器,同时集成高性能NNIE引擎,使得Hi3516DV300在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 + +**图 1** Hi3516单板正面外观图 + + +![](figure/3516正面.png) + +## 开发板规格 + +**表 1** Hi3516开发板规格清单 + + + + + + + + + + + + + +

规格类型

+

规格清单

+

处理器及内部存储

+
  • Hi3516DV300芯片
  • DDR3 1GB
  • eMMC4.5,8GB容量
+

外部器件

+
  • 以太网口
  • 音频视频
    • 1路语音输入
    • 1路单声道(AC_L)输出,接3W功放(LM4871)
    • MicroHDMI(1路HDMI 1.4)
    +
  • 摄像头
    • 传感器IMX335
    • 镜头M12,焦距4mm,光圈1.8
    +
  • 显示屏
    • LCD连接器(2.35寸)
    • LCD连接器(5.5寸)
    +
  • 外部器件及接口
    • SD卡接口
    • JTAG/I2S 接口
    • ADC接口
    • 舵机接口
    • Grove连接器
    • USB2.0(Type C)
    • 功能按键3个,2个用户自定义按键,1个升级按键
    • LED指示灯,绿灯,红灯
    +
+
+ diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md new file mode 100644 index 0000000000000000000000000000000000000000..211dffba8a9df92bdec701f63e94a84e98fc1a90 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3518.md @@ -0,0 +1,57 @@ +# Hi3518开发板介绍 + +- [简介](#section14815247616) +- [开发板规格](#section765112478446) + +## 简介 + +Hi3518EV300作为新一代智慧视觉处理SOC,集成新一代ISP\(Image Signal Processor\)以及H.265视频压缩编码器,同时采用先进低功耗工艺和低功耗架构设计,使其在低码率、高画质、低功耗等方面引领行业水平。 + +**图 1** Hi3518EV300单板正面外观图 +![](figure/Hi3518EV300单板正面外观图.png "Hi3518EV300单板正面外观图") + +**图 2** Hi3518EV300单板背面外观图 + + +![](figure/Hi3518正背面.png) + +## 开发板规格 + +**表 1** Hi3518开发板规格清单 + + + + + + + + + + + + + + + + + + + + + + +

规格类型

+

规格清单

+

处理器内核

+
  • 海思3518EV300
+

成像器件

+
  • 1/2.9 F23
+

外部接口

+
  • 外置麦克风MIC
  • 外置8Ω/1.5W扬声器
+

外部存储器接口

+
  • TF卡

    最大支持128GB(通用FAT32格式)

    +
+

WLAN协议

+
  • 支持 802.11 b/g/n
+
+ diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md new file mode 100644 index 0000000000000000000000000000000000000000..84549ecc121b4df54275fb870af729d55ae2010b --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction-hi3861.md @@ -0,0 +1,157 @@ +# Hi3861开发板介绍 + +- [简介](#section19352114194115) +- [资源和约束](#section82610215014) +- [开发板规格](#section169054431017) +- [OpenHarmony关键特性](#section1317173016507) + +## 简介 + +Hi3861 WLAN模组是一片大约2cm\*5cm大小的开发板,是一款高度集成的2.4GHz WLAN SoC芯片,集成IEEE 802.11b/g/n基带和RF(Radio Frequency)电路。支持OpenHarmony,并配套提供开放、易用的开发和调试运行环境。 + +**图 1** Hi3861 WLAN模组外观图 + + +![](figure/3861正面.png) + +另外,Hi3861 WLAN模组还可以通过与Hi3861底板连接,扩充自身的外设能力,底板如下图所示。 + +**图 2** Hi3861底板外观图 + + +![](figure/zh-cn_image_0000001174350615.png) + +- RF电路包括功率放大器PA(Power Amplifier)、低噪声放大器LNA(Low Noise Amplifier)、RF Balun、天线开关以及电源管理等模块;支持20MHz标准带宽和5MHz/10MHz窄带宽,提供最大72.2Mbit/s物理层速率。 +- Hi3861 WLAN基带支持正交频分复用(OFDM)技术,并向下兼容直接序列扩频(DSSS)和补码键控(CCK)技术,支持IEEE 802.11 b/g/n协议的各种数据速率。 +- Hi3861芯片集成高性能32bit微处理器、硬件安全引擎以及丰富的外设接口,外设接口包括SPI(Synchronous Peripheral Interface)、UART(Universal Asynchronous Receiver & Transmitter)、I2C(The Inter Integrated Circuit)、PWM(Pulse Width Modulation)、GPIO(General Purpose Input/Output)和多路ADC(Analog to Digital Converter),同时支持高速SDIO2.0(Secure Digital Input/Output)接口,最高时钟可达50MHz;芯片内置SRAM(Static Random Access Memory)和Flash,可独立运行,并支持在Flash上运行程序。 +- Hi3861芯片适用于智能家电等物联网智能终端领域。 + + **图 3** Hi3861功能框图 + + + ![](figure/zh-cn_image_0000001128311066.png) + + +## 资源和约束 + +Hi3861 WLAN模组资源十分有限,整板共2MB FLASH,352KB RAM。在编写业务代码时,需注意资源使用效率。 + +## 开发板规格 + +**表 1** Hi3861 WLAN模组规格清单 + + + + + + + + + + + + + + + + + + + + + + + + + +

规格类型

+

规格清单

+

通用规格

+
  • 1×1 2.4GHz频段(ch1~ch14)
  • PHY支持IEEE 802.11b/g/n
  • MAC支持IEEE802.11 d/e/h/i/k/v/w
+
  • 内置PA和LNA,集成TX/RX Switch、Balun等
  • 支持STA和AP形态,作为AP时最大支持6 个STA接入
  • 支持WFA WPA/WPA2 personal、WPS2.0
  • 支持与BT/BLE芯片共存的2/3/4 线PTA方案
  • 电源电压输入范围:2.3V~3.6V
+
  • IO电源电压支持1.8V和3.3V
+
  • 支持RF自校准方案
  • 低功耗:
    • Ultra Deep Sleep模式:5μA@3.3V
    • DTIM1:1.5mA@3.3V
    • DTIM3:0.8mA@3.3V
    +
+

PHY特性

+
  • 支持IEEE802.11b/g/n单天线所有的数据速率
  • 支持最大速率:72.2Mbps@HT20 MCS7
  • 支持标准20MHz带宽和5M/10M窄带宽
  • 支持STBC
  • 支持Short-GI
+

MAC特性

+
  • 支持A-MPDU,A-MSDU
  • 支持Blk-ACK
  • 支持QoS,满足不同业务服务质量需求
+

CPU子系统

+
  • 高性能 32bit微处理器,最大工作频率160MHz
  • 内嵌SRAM 352KB、ROM 288KB
  • 内嵌 2MB Flash
+

外围接口

+
  • 1个SDIO接口、2个SPI接口、2个I2C接口、3个UART接口、15个GPIO接口、7路ADC输入、6路PWM、1个I2S接口(注:上述接口通过复用实现)
  • 外部主晶体频率40M或24M
+

其他信息

+
  • 封装:QFN-32,5mm×5mm
  • 工作温度:-40℃ ~ +85℃
+
+ +## OpenHarmony关键特性 + +OpenHarmony基于Hi3861平台提供了多种开放能力,提供的关键组件如下表所示。 + +**表 2** OpenHarmony关键组件列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

组件名

+

能力介绍

+

WLAN服务

+

提供WLAN服务能力。包括:station和hotspot模式的连接、断开、状态查询等。

+

模组外设控制

+

提供操作外设的能力。包括:I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。

+

分布式软总线

+

OpenHarmony分布式网络中,提供设备被发现、数据传输的能力。

+

设备安全绑定

+

提供在设备互联场景中,数据在设备之间的安全流转的能力。

+

基础加解密

+

提供密钥管理、加解密等能力。

+

系统服务管理

+

系统服务管理基于面向服务的架构,提供了OpenHarmony统一化的系统服务开发框架。

+

启动引导

+

提供系统服务的启动入口标识。在系统服务管理启动时,调用boostrap标识的入口函数,并启动系统服务。

+

系统属性

+

提供获取与设置系统属性的能力。

+

基础库

+

提供公共基础库能力。包括:文件操作、KV存储管理等。

+

DFX

+

提供DFX能力。包括:流水日志、时间打点等。

+

XTS

+

提供OpenHarmony生态认证测试套件的集合能力。

+
+ diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-introduction.md b/zh-cn/device-dev/quick-start/quickstart-lite-introduction.md new file mode 100644 index 0000000000000000000000000000000000000000..65e4fde55ca286b55fb1980a6cd7b67929cb9544 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-introduction.md @@ -0,0 +1,9 @@ +# 了解开发板 + +- **[Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md)** + +- **[Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md)** + +- **[Hi3518开发板介绍](quickstart-lite-introduction-hi3518.md)** + + diff --git "a/zh-cn/device-dev/quick-start/\346\246\202\350\277\260.md" b/zh-cn/device-dev/quick-start/quickstart-lite-overview.md similarity index 100% rename from "zh-cn/device-dev/quick-start/\346\246\202\350\277\260.md" rename to zh-cn/device-dev/quick-start/quickstart-lite-overview.md diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..ff748404f05d31f54d19fcd4744fa76fdc7febfe --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-faqs.md @@ -0,0 +1,175 @@ +# 常见问题 + +- [烧写选择串口后提示失败](#section627268185113) +- [Windows电脑与单板网络连接失败](#section195391036568) +- [烧写失败](#section571164016565) +- [编译构建过程中,提示找不到“python”](#section1039835245619) +- [串口无回显](#section14871149155911) + +## 烧写选择串口后提示失败 + +- **现象描述** + + 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 + + **图 1** 打开串口失败图 + ![](figure/打开串口失败图.png "打开串口失败图") + +- **可能原因** + + 串口已经被占用。 + +- **解决办法** + +1. 按图依次选择下拉框,查找带有serial-xx的终端 + + **图 2** 查找是否存在占用串口的终端 + ![](figure/查找是否存在占用串口的终端.png "查找是否存在占用串口的终端") + +2. 点击标号中的垃圾桶图标,关闭串口。 + + **图 3** 关闭串口终端 + ![](figure/关闭串口终端.png "关闭串口终端") + +3. 重新点击烧写,选择串口并开始烧写程序 + + **图 4** 重新启动烧写任务 + + + ![](figure/changjian1.png) + + +## Windows电脑与单板网络连接失败 + +- **现象描述** + + 点击烧写并选择串口后,无法获取文件。 + + **图 5** 网络不通,单板无法获取文件图 + ![](figure/网络不通-单板无法获取文件图.png "网络不通-单板无法获取文件图") + +- **可能原因** + + 单板网络与Windows电脑不联通。 + + Windows电脑防火墙未允许Visual Studio Code联网。 + +- **解决方法** + +1. 检查网线是否连接。 +2. 点击Windows防火墙。 + + **图 6** 网络防火墙设置图 + ![](figure/网络防火墙设置图.png "网络防火墙设置图") + +3. 点击“允许应用通过防火墙”。 + + **图 7** 防火墙和网络保护界面图 + ![](figure/防火墙和网络保护界面图.png "防火墙和网络保护界面图") + +4. 查找Visual Studio Code应用。 + + **图 8** 查找Visual Studio Code应用图 + ![](figure/查找Visual-Studio-Code应用图.png "查找Visual-Studio-Code应用图") + +5. 勾选Visual Studio Code的专用和公用网络的访问权限。 + + **图 9** 允许Visual Studio Code应用访问网络 + ![](figure/允许Visual-Studio-Code应用访问网络.png "允许Visual-Studio-Code应用访问网络") + + +## 烧写失败 + +- **现象描述** + + 点击烧写并选择串口后,出现无法烧写的情况。 + +- **可能原因** + + 安装IDE插件DevEco后未重启。 + +- **解决方法** + + 重启IDE。 + + +## 编译构建过程中,提示找不到“python” + +- **现象描述** + + ![](figure/zh-cn_image_0000001174270715.png) + + +- **可能原因1** + + 没有装python。 + +- **解决办法** + + 请按照[安装python](quickstart-lite-env-setup-lin.md)。 + +- **可能原因2** + + ![](figure/zh-cn_image_0000001128470880.png) + +- **解决办法** + + usr/bin目录下没有python软链接,请运行以下命令: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + 例: + + ![](figure/zh-cn_image_0000001174270713.png) + + +## 串口无回显 + +- **现象描述** + + 串口显示已连接,重启单板后,回车无任何回显。 + +- **可能原因1** + + 串口连接错误。 + +- **解决办法** + + 修改串口号。 + + 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](#section627268185113)修改串口号。 + + +- **可能原因2** + + 单板U-boot被损坏。 + +- **解决办法** + + 烧写U-boot。 + + 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 + + +1. 获取引导文件U-boot。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >单板的U-boot文件请在开源包中获取: + >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin + >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin + +2. 根据USB烧写步骤烧写U-boot文件。 + + 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 + +3. 烧写完成后,登录串口如下图所示。 + + **图 10** U-boot烧写完成串口显示图 + ![](figure/U-boot烧写完成串口显示图.png "U-boot烧写完成串口显示图") + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md new file mode 100644 index 0000000000000000000000000000000000000000..7b43c52c82cf9e8f6c80568f1404af8521106edf --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-program.md @@ -0,0 +1,503 @@ +# 驱动开发示例 + +- [驱动程序介绍](#s8efc1952ebfe4d1ea717182e108c29bb) +- [编译和烧写](#section660016185110) +- [镜像运行](#section333215226219) +- [下一步学习](#section9712145420182) + +本节指导开发者在单板上运行第一个驱动程序,其中包括驱动程序介绍、编译、烧写、运行等步骤。 + +## 驱动程序介绍 + +下面基于HDF框架,提供一个简单的UART(Universal Asynchronous Receiver/Transmitter)平台驱动开发样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。驱动程序源码位于vendor/huawei/hdf/sample目录 + +1. 添加配置。 + + 在HDF框架的驱动配置文件(例如device/hisilicon/hi3516dv300/sdk\_liteos/config/uart/uart\_config.hcs)中添加该驱动的配置信息,如下所示: + + ``` + root { + platform { + uart_sample { + num = 5; // UART设备编号 + base = 0x120a0000; // UART 寄存器基地址 + irqNum = 38; + baudrate = 115200; + uartClk = 24000000; + wlen = 0x60; + parity = 0; + stopBit = 0; + match_attr = "sample_uart_5"; + } + } + } + ``` + + 在HDF框架的设备配置文件(例如vendor/hisilicon/ipcamera\_hi3516dv300\_liteos/config/device\_info/device\_info.hcs)中添加该驱动的设备节点信息,如下所示: + + ``` + root { + device_info { + platform :: host { + hostName = "platform_host"; + priority = 50; + device_uart :: device { + device5 :: deviceNode { + policy = 2; + priority = 10; + permission = 0660; + moduleName = "UART_SAMPLE"; + serviceName = "HDF_PLATFORM_UART_5"; + deviceMatchAttr = "sample_uart_5"; + } + } + } + } + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >配置文件与UART驱动示例的源码在同一个路径,需要手动添加到Hi3516DV300单板路径下。 + +2. 注册UART驱动入口。 + + 基于HDF框架注册UART驱动的入口HdfDriverEntry,代码如下: + + ``` + // 绑定UART驱动接口到HDF框架 + static int32_t SampleUartDriverBind(struct HdfDeviceObject *device) + { + struct UartHost *uartHost = NULL; + + if (device == NULL) { + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("Enter %s:", __func__); + + uartHost = UartHostCreate(device); + if (uartHost == NULL) { + HDF_LOGE("%s: UartHostCreate failed", __func__); + return HDF_FAILURE; + } + uartHost->service.Dispatch = SampleDispatch; + return HDF_SUCCESS; + } + + // 从UART驱动的HCS中获取配置信息 + static uint32_t GetUartDeviceResource( + struct UartDevice *device, const struct DeviceResourceNode *resourceNode) + { + struct UartResource *resource = &device->resource; + struct DeviceResourceIface *dri = NULL; + dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); + if (dri == NULL || dri->GetUint32 == NULL) { + HDF_LOGE("DeviceResourceIface is invalid"); + return HDF_FAILURE; + } + + if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read num fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read base fail"); + return HDF_FAILURE; + } + resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48); + if (resource->physBase == 0) { + HDF_LOGE("uart config fail to remap physBase"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read irqNum fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read baudrate fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read wlen fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read parity fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read stopBit fail"); + return HDF_FAILURE; + } + if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) { + HDF_LOGE("uart config read uartClk fail"); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // 将UART驱动的配置和接口附加到HDF驱动框架 + static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device) + { + int32_t ret; + struct UartDevice *uartDevice = NULL; + if (device->property == NULL) { + HDF_LOGE("%s: property is NULL", __func__); + return HDF_FAILURE; + } + uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice)); + if (uartDevice == NULL) { + HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__); + return HDF_ERR_MALLOC_FAIL; + } + ret = GetUartDeviceResource(uartDevice, device->property); + if (ret != HDF_SUCCESS) { + (void)OsalMemFree(uartDevice); + return HDF_FAILURE; + } + host->num = uartDevice->resource.num; + host->priv = uartDevice; + AddUartDevice(host); + return InitUartDevice(uartDevice); + } + + // 初始化UART驱动 + static int32_t SampleUartDriverInit(struct HdfDeviceObject *device) + { + int32_t ret; + struct UartHost *host = NULL; + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_OBJECT; + } + HDF_LOGI("Enter %s:", __func__); + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return HDF_FAILURE; + } + ret = AttachUartDevice(host, device); + if (ret != HDF_SUCCESS) { + HDF_LOGE("%s: attach error", __func__); + return HDF_FAILURE; + } + host->method = &g_sampleUartHostMethod; + return ret; + } + + static void DeinitUartDevice(struct UartDevice *device) + { + struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase; + /* wait for uart enter idle. */ + while (UartPl011IsBusy(regMap)); + UartPl011ResetRegisters(regMap); + uart_clk_cfg(0, false); + OsalIoUnmap((void *)device->resource.physBase); + device->state = UART_DEVICE_UNINITIALIZED; + } + + // 解绑并释放UART驱动 + static void DetachUartDevice(struct UartHost *host) + { + struct UartDevice *uartDevice = NULL; + + if (host->priv == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return; + } + uartDevice = host->priv; + DeinitUartDevice(uartDevice); + (void)OsalMemFree(uartDevice); + host->priv = NULL; + } + + // 释放UART驱动 + static void SampleUartDriverRelease(struct HdfDeviceObject *device) + { + struct UartHost *host = NULL; + HDF_LOGI("Enter %s:", __func__); + + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return; + } + host = UartHostFromDevice(device); + if (host == NULL) { + HDF_LOGE("%s: host is NULL", __func__); + return; + } + if (host->priv != NULL) { + DetachUartDevice(host); + } + UartHostDestroy(host); + } + + struct HdfDriverEntry g_sampleUartDriverEntry = { + .moduleVersion = 1, + .moduleName = "UART_SAMPLE", + .Bind = SampleUartDriverBind, + .Init = SampleUartDriverInit, + .Release = SampleUartDriverRelease, + }; + + HDF_INIT(g_sampleUartDriverEntry); + ``` + +3. 注册UART驱动接口。 + + HDF框架提供了UART驱动接口的模板方法UartHostMethod,实现UART驱动接口的代码如下: + + ``` + static int32_t SampleUartHostInit(struct UartHost *host) + { + HDF_LOGI("%s: Enter", __func__); + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; + } + + static int32_t SampleUartHostDeinit(struct UartHost *host) + { + HDF_LOGI("%s: Enter", __func__); + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + return HDF_SUCCESS; + } + + // 向UART中写入数据 + static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size) + { + HDF_LOGI("%s: Enter", __func__); + uint32_t idx; + struct UartRegisterMap *regMap = NULL; + struct UartDevice *device = NULL; + + if (host == NULL || data == NULL || size == 0) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + regMap = (struct UartRegisterMap *)device->resource.physBase; + for (idx = 0; idx < size; idx++) { + UartPl011Write(regMap, data[idx]); + } + return HDF_SUCCESS; + } + + // 设置UART的波特率 + static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate) + { + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *device = NULL; + struct UartRegisterMap *regMap = NULL; + UartPl011Error err; + + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + regMap = (struct UartRegisterMap *)device->resource.physBase; + if (device->state != UART_DEVICE_INITIALIZED) { + return UART_PL011_ERR_NOT_INIT; + } + if (baudRate == 0) { + return UART_PL011_ERR_INVALID_BAUD; + } + err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate); + if (err == UART_PL011_ERR_NONE) { + device->baudrate = baudRate; + } + return err; + } + + // 获取UART的波特率 + static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate) + { + HDF_LOGI("%s: Enter", __func__); + struct UartDevice *device = NULL; + + if (host == NULL) { + HDF_LOGE("%s: invalid parameter", __func__); + return HDF_ERR_INVALID_PARAM; + } + device = (struct UartDevice *)host->priv; + if (device == NULL) { + HDF_LOGE("%s: device is NULL", __func__); + return HDF_ERR_INVALID_PARAM; + } + *baudRate = device->baudrate; + return HDF_SUCCESS; + } + + // 在HdfUartSampleInit方法中绑定 + struct UartHostMethod g_sampleUartHostMethod = { + .Init = SampleUartHostInit, + .Deinit = SampleUartHostDeinit, + .Read = NULL, + .Write = SampleUartHostWrite, + .SetBaud = SampleUartHostSetBaud, + .GetBaud = SampleUartHostGetBaud, + .SetAttribute = NULL, + .GetAttribute = NULL, + .SetTransMode = NULL, + }; + ``` + + 在device/hisilicon/drivers/lite.mk编译脚本中增加示例UART驱动模块,代码如下: + + ``` + LITEOS_BASELIB += -lhdf_uart_sample + LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/huawei/hdf/sample/platform/uart + ``` + +4. 用户程序和驱动交互代码。 + + UART驱动成功初始化后,会创建/dev/uartdev-5设备节点,通过设备节点与UART驱动交互的代码如下: + + ``` + #include + #include + #include + #include "hdf_log.h" + + #define HDF_LOG_TAG "hello_uart" + #define INFO_SIZE 16 + + int main(void) + { + int ret; + int fd; + const char info[INFO_SIZE] = {" HELLO UART! "}; + + fd = open("/dev/uartdev-5", O_RDWR); + if (fd < 0) { + HDF_LOGE("hello_uart uartdev-5 open failed %d", fd); + return -1; + } + ret = write(fd, info, INFO_SIZE); + if (ret != 0) { + HDF_LOGE("hello_uart write uartdev-5 ret is %d", ret); + } + ret = close(fd); + if (ret != 0) { + HDF_LOGE("hello_uart uartdev-5 close failed %d", fd); + return -1; + } + return ret; + } + ``` + + 在build/lite/components/drivers.json驱动配置中hdf\_hi3516dv300\_liteos\_a组件下的targets中增加hello\_uart\_sample组件,代码如下: + + ``` + { + "components": [ + { + "component": "hdf_hi3516dv300_liteos_a", + ... + "targets": [ + "//vendor/huawei/hdf/sample/platform/uart:hello_uart_sample" + ] + } + ] + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如上代码均为示例代码,完整代码可以在vendor/huawei/hdf/sample查看。 + >示例代码默认不参与编译,需要手动添加到编译脚本中。 + + +## 编译和烧写 + +参考《运行Hello OHOS》进行编译和烧写:[编译](quickstart-lite-steps-board3516-running.md#section1077671315253)、[烧录](quickstart-lite-steps-board3516-running.md#section1347011412201) + +## 镜像运行 + +1. 连接串口。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >若无法连接串口,请参考[常见问题](quickstart-lite-steps-board3516-faqs.md)进行排查。 + + **图 1** 连接串口图 + + + ![](figure/chuankou1.png) + + 1. 单击**Monitor**打开串口。 + 2. 连续输入回车直到串口显示"hisilicon"。 + 3. 单板初次启动或修改启动参数,请进入[步骤2](quickstart-lite-steps-board3516-running.md#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](quickstart-lite-steps-board3516-running.md#ld26f18828aa44c36bfa36be150e60e49)。 + +2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 + + **表 1** U-boot修改命令 + + + + + + + + + + + + + + + + + + + +

执行命令

+

命令解释

+

setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

+

读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

+

setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

+

表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

+

“rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

+

saveenv

+

表示保存当前配置。

+

reset

+

表示复位单板。

+
+ + >![](../public_sys-resources/icon-notice.gif) **须知:** + >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 + +3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 + + **图 2** 系统启动图 + + + ![](figure/qi1.png) + +4. 根目录下,在命令行输入指令“**./bin/hello\_uart**”执行写入的demo程序,显示成功结果如下所示。 + + ``` + OHOS # ./bin/hello_uart + OHOS # HELLO UART! + ``` + + +## 下一步学习 + +恭喜,您已完成Hi3516 快速上手!建议您下一步进入[带屏摄像头产品开发](../guide/device-camera.md)的学习 。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md new file mode 100644 index 0000000000000000000000000000000000000000..336d979c20d2b4413af4c0f562bcb3621e337e6e --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-running.md @@ -0,0 +1,269 @@ +# 运行Hello OHOS + +- [新建应用程序](#section204672145202) +- [编译](#section1077671315253) +- [烧录](#section1347011412201) +- [镜像运行](#section24721014162010) +- [执行应用程序](#section5276734182615) + +本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 + +## 新建应用程序 + +1. 新建目录及源码 + + 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 + + ``` + #include + + int main(int argc, char **argv) + { + printf("\n************************************************\n"); + printf("\n\t\tHello OHOS!\n"); + printf("\n************************************************\n\n"); + + return 0; + } + ``` + +2. 新建编译组织文件 + + 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: + + ``` + 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. 添加新组件 + + 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "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. 修改单板配置文件 + + 修改文件**vendor/hisilicon/hispark\_taurus/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "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":[] } + ] + }, + ``` + + +## 编译 + +如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/gettools-acquire.md)的编译操作。如果Linux编译环境通过软件包方式安装,请进入源码根目录,执行如下命令进行编译: + +``` +hb set(设置编译路径) +.(选择当前路径) +选择ipcamera_hispark_taurus@hisilicon并回车 +hb build -f(执行编译) +``` + +**图 1** 设置图例 +![](figure/设置图例.png "设置图例") + +结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>Hi3516DV300单板的U-boot文件获取路径:device/hisilicon/hispark\_taurus/sdk\_liteos/uboot/out/boot/u-boot-hi3516dv300.bin + +## 烧录 + +Hi3516开发板的代码烧录支持USB烧录、网口烧录和串口烧录三种方式。此处仅以网口烧录为例进行说明。 + +1. 请连接好电脑和待烧录开发板,以Hi3516DV300为例,需要同时连接串口、网口和电源,具体可参考[Hi3516开发板介绍](quickstart-lite-introduction-hi3516.md)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001174350647.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/2021-01-27_170334.png) + +4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3516系列开发板进行适配,无需单独修改。 +5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li142386399535)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 + - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 + + ![](figure/zh-cn_image_0000001128470904.png) + +6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 +7. 设置网口烧录的IP地址信息,设置如下选项: + + - upload\_net\_server\_ip:选择[6](#zh-cn_topic_0000001056443961_li1558813168234)中设置的IP地址信息。例如192.168.1.2 + - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 + - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 + - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 + + ![](figure/zh-cn_image_0000001174270733.png) + +8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +9. 打开工程文件,点击![](figure/2021-01-27_170334-2.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3516dv300下的**Upload**按钮,启动烧录。 + + ![](figure/zh-cn_image_0000001174270729.png) + +10. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 + + ![](figure/zh-cn_image_0000001128470906.png) + +11. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001128311098.png) + + +## 镜像运行 + +1. 连接串口。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >若无法连接串口,请参考[常见问题](quickstart-lite-steps-board3516-faqs.md)进行排查。 + + **图 2** 连接串口图 + + + ![](figure/chuankou1.png) + + 1. 单击**Monitor**打开串口。 + 2. 连续输入回车直到串口显示"hisilicon"。 + 3. 单板初次启动或修改启动参数,请进入[步骤2](#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](#ld26f18828aa44c36bfa36be150e60e49)。 + +2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 + + **表 1** U-boot修改命令 + + + + + + + + + + + + + + + + + + + +

执行命令

+

命令解释

+

setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

+

读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

+

setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

+

表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

+

“rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

+

saveenv

+

表示保存当前配置。

+

reset

+

表示复位单板。

+
+ + >![](../public_sys-resources/icon-notice.gif) **须知:** + >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 + +3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 + + **图 3** 系统启动图 + + + ![](figure/qi1.png) + + +## 执行应用程序 + +根目录下,在命令行输入指令“**./bin/helloworld**”执行写入的demo程序,显示成功结果如下图所示。 + +**图 4** 启动并成功执行应用程序图 +![](figure/启动并成功执行应用程序图.png "启动并成功执行应用程序图") + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md new file mode 100644 index 0000000000000000000000000000000000000000..1b5e88ef8f4b11ec873afdb7c4c3116d5a6fbcb4 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516-setting.md @@ -0,0 +1,122 @@ +# 安装开发板环境 + +- [Hi3516工具要求](#section179175261196) + - [硬件要求](#section5840424125014) + - [软件要求](#section965634210501) + +- [安装Linux服务器工具](#section182916865219) + - [将Linux shell改为bash](#section1715027152617) + - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) + - [安装文件打包工具及Java虚拟机环境](#section16199102083717) + + +## Hi3516工具要求 + +### 硬件要求 + +- Hi3516DV300 IoT Camera开发板 +- USB转串口线、网线(Windows工作台通过USB转串口线、网线与Hi3516DV300 开发板连接) + +各硬件连接关系如下图所示。 + +**图 1** 硬件连线图 + + +![](figure/矩形备份-292.png) + +### 软件要求 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section182916865219)章节。 + +Hi3516开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 + +**表 1** Linux服务器开发工具及获取途径 + + + + + + + + + + + + + + + + + + + + + + + + +

开发工具

+

用途

+

获取途径

+

bash

+

命令行处理工具

+

系统配置

+

编译基础软件包(仅ubuntu 20+需要)

+

编译依赖的基础软件包

+

通过互联网获取

+

dosfstools、mtools、mtd-utils

+

文件打包工具

+

通过apt-get install安装

+

Java 虚拟机环境

+

编译、调试和运行Java程序

+

通过apt-get install安装

+
+ +## 安装Linux服务器工具 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装LLVM、hc-gen编译工具。 +>- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 + +### 将Linux shell改为bash + +查看shell是否为bash,在终端运行如下命令 + +``` +ls -l /bin/sh +``` + +如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: + +**方法一**:在终端运行如下命令,然后选择 no。 + +``` +sudo dpkg-reconfigure dash +``` + +**方法二**:先删除sh,再创建软链接。 + +``` +sudo rm -rf /bin/sh +sudo ln -s /bin/bash /bin/sh +``` + +### 安装编译依赖基础软件(仅Ubuntu 20+需要) + +执行以下命令进行安装: + +``` +sudo apt-get install build-essential gcc g++ make zlib* libffi-dev +``` + +### 安装文件打包工具及Java虚拟机环境 + +1. 打开Linux编译服务器终端 +2. 运行如下命令,安装dosfstools,mtools,mtd-utils,Java运行时环境(JRE)和Java sdk 开发工具包。 + + ``` + sudo apt-get install dosfstools mtools mtd-utils default-jre default-jdk + ``` + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md new file mode 100644 index 0000000000000000000000000000000000000000..397255079763931a2d53c5f10f472a2afd7a350b --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3516.md @@ -0,0 +1,11 @@ +# Hi3516开发板 + +- **[安装开发板环境](quickstart-lite-steps-board3516-setting.md)** + +- **[运行Hello OHOS](quickstart-lite-steps-board3516-running.md)** + +- **[驱动开发示例](quickstart-lite-steps-board3516-program.md)** + +- **[常见问题](quickstart-lite-steps-board3516-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..dc71a35fb6a0e5fdac8d3f976d58066a474f2a97 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-faqs.md @@ -0,0 +1,174 @@ +# 常见问题 + +- [烧写选择串口后提示失败](#section1498892119619) +- [Windows电脑与单板网络连接失败](#section8512971816) +- [烧写失败](#section1767804111198) +- [编译构建过程中,提示找不到“python”](#zh-cn_topic_0000001053466255_section1039835245619) +- [串口无回显](#zh-cn_topic_0000001053466255_section14871149155911) + +## 烧写选择串口后提示失败 + +- **现象描述** + + 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 + + **图 1** 打开串口失败图 + ![](figure/打开串口失败图-7.png "打开串口失败图-7") + +- **可能原因** + + 串口已经被占用。 + +- **解决办法** + +1. 按图依次选择下拉框,查找带有serial-xx的终端 + + **图 2** 查找是否存在占用串口的终端 + ![](figure/查找是否存在占用串口的终端-8.png "查找是否存在占用串口的终端-8") + +2. 点击标号中的垃圾桶图标,关闭串口。 + + **图 3** 关闭串口终端 + ![](figure/关闭串口终端-9.png "关闭串口终端-9") + +3. 重新点击烧写,选择串口并开始烧写程序 + + **图 4** 重新启动烧写任务 + + + ![](figure/changjian1-10.png) + + +## Windows电脑与单板网络连接失败 + +- **现象描述** + + 点击烧写并选择串口后,无法获取文件。 + + **图 5** 网络不通,单板无法获取文件图 + ![](figure/网络不通-单板无法获取文件图-11.png "网络不通-单板无法获取文件图-11") + +- **可能原因** + + 单板网络与Windows电脑不联通。 + + Windows电脑防火墙未允许Visual Studio Code联网。 + +- **解决方法** + +1. 检查网线是否连接。 +2. 点击Windows防火墙。 + + **图 6** 网络防火墙设置图 + ![](figure/网络防火墙设置图-12.png "网络防火墙设置图-12") + +3. 点击“允许应用通过防火墙”。 + + **图 7** 防火墙和网络保护界面图 + ![](figure/防火墙和网络保护界面图-13.png "防火墙和网络保护界面图-13") + +4. 查找Visual Studio Code应用。 + + **图 8** 查找Visual Studio Code应用图 + ![](figure/查找Visual-Studio-Code应用图-14.png "查找Visual-Studio-Code应用图-14") + +5. 勾选Visual Studio Code的专用和公用网络的访问权限。 + + **图 9** 允许Visual Studio Code应用访问网络 + ![](figure/允许Visual-Studio-Code应用访问网络-15.png "允许Visual-Studio-Code应用访问网络-15") + + +## 烧写失败 + +- **现象描述** + + 点击烧写并选择串口后,出现无法烧写的情况。 + +- **可能原因** + + 安装IDE插件DevEco后未重启。 + +- **解决方法** + + 重启IDE。 + + +## 编译构建过程中,提示找不到“python” + +- **现象描述** + + ![](figure/zh-cn_image_0000001174270743.png) + + +- **可能原因1** + + 没有装python。 + +- **解决办法** + + 请按照[安装python](quickstart-lite-env-setup-lin.md)。 + +- **可能原因2** + + ![](figure/zh-cn_image_0000001174270739.png) + +- **解决办法** + + usr/bin目录下没有python软链接,请运行以下命令: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + 例: + + ![](figure/zh-cn_image_0000001174350661.png) + + +## 串口无回显 + +- **现象描述** + + 串口显示已连接,重启单板后,回车无任何回显。 + +- **可能原因1** + + 串口连接错误。 + +- **解决办法** + + 修改串口号。 + + 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](quickstart-lite-steps-board3518-running.md)修改串口号。 + + +- **可能原因2** + + 单板U-boot被损坏。 + +- **解决办法** + + 烧写U-boot。 + + 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 + + +1. 获取引导文件U-boot。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >单板的U-boot文件请在开源包中获取: + >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin + >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin + +2. 根据USB烧写步骤烧写U-boot文件。 + + 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 + +3. 烧写完成后,登录串口如下图所示。 + + ![](figure/zh-cn_image_0000001174350659.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md new file mode 100644 index 0000000000000000000000000000000000000000..2b5a833cfc380fb2762fda0d333c8a20c8cb4239 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-running.md @@ -0,0 +1,262 @@ +# 运行Hello OHOS + +- [新建应用程序](#section1550972416485) +- [编译](#section234175193114) +- [烧录](#section7609155824819) +- [镜像运行](#section17612105814480) +- [下一步学习](#section9712145420182) + +本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 + +## 新建应用程序 + +1. 新建目录及源码 + + 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 + + ``` + #include + + int main(int argc, char **argv) + { + printf("\n************************************************\n"); + printf("\n\t\tHello OHOS!\n"); + printf("\n************************************************\n\n"); + + return 0; + } + ``` + +2. 新建编译组织文件 + + 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: + + ``` + 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. 添加新组件 + + 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "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. 修改单板配置文件 + + 修改文件**vendor/hisilicon/hispark\_aries/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): + + ``` + { + "subsystem": "applications", + "components": [ + ##start## + { "component": "hello_world_app", "features":[] }, + ##end## + { "component": "camera_sample_app", "features":[] } + + ] + }, + ``` + + +## 编译 + +如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/gettools-acquire.md)的编译操作。如果Linux编译环境通过软件包方式安装,进入源码根目录,执行如下命令进行编译: + +``` +hb set(设置编译路径) +.(选择当前路径) +选择ipcamera_hispark_aries@hisilicon并回车 +hb build -f(执行编译) +``` + +结果文件生成在out/hispark\_aries/ipcamera\_hispark\_aries目录下。 + +**图 1** 设置图例 +![](figure/设置图例-4.png "设置图例-4") + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>Hi3518EV300单板的U-boot文件获取路径:device/hisilicon/hispark\_aries/sdk\_liteos/uboot/out/boot/u-boot-hi3518ev300.bin + +## 烧录 + +Hi3518开发板的代码烧录仅支持USB烧录方式。 + +1. 请连接好电脑和待烧录开发板,以Hi3518EV300为例,需要同时连接串口和USB口,具体可参考[Hi3518开发板介绍](quickstart-lite-introduction-hi3518.md)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001128470900.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/zh-cn_image_0000001174350649.png) + +4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3518系列开发板进行适配,无需单独修改。 +5. 在“hi3518ev300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001057313128_li46411811196)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“hiburn-usb”。 + - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 + + ![](figure/zh-cn_image_0000001128311090.png) + +6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +7. 打开工程文件,点击![](figure/2021-01-27_170334-5.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3518ev300\_fastboot下的**Erase**按钮,擦除U-Boot。 + + ![](figure/zh-cn_image_0000001174270731.png) + +8. 执行**Erase**擦除操作后,显示如下提示信息时,请重启开发板(下电再上电)。 + + ![](figure/zh-cn_image_0000001128311092.png) + +9. 重新上电后,显示如下信息时,表示擦除U-Boot成功。 + + ![](figure/zh-cn_image_0000001128311094.png) + +10. 擦除完成后,点击hi3518ev300下的**Upload**按钮,启动烧录。 + + ![](figure/zh-cn_image_0000001174350641.png) + +11. 启动烧录后,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001174350643.png) + + +## 镜像运行 + +1. 连接串口。 + + >![](../public_sys-resources/icon-notice.gif) **须知:** + >若无法连接串口,请参考[常见问题](quickstart-lite-steps-board3518-faqs.md)进行排查。 + + **图 2** 连接串口图 + + + ![](figure/chuankou1-6.png) + + 1. 单击**Monitor**打开串口。 + 2. 连续输入回车直到串口显示"hisilicon"。 + 3. 单板初次启动或修改启动参数,请进入[步骤2](#li9441185382314),否则进入[步骤3](#li6442853122312)。 + +2. (初次烧写必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,可保存执行结果,但U-boot重新烧入,则需要再次执行下述步骤。 + + **表 1** U-boot修改命令 + + + + + + + + + + + + + + + + + + + + + + +

执行命令

+

命令解释

+

setenv bootcmd "sf probe 0;sf read 0x40000000 0x100000 0x600000;go 0x40000000";

+

设置bootcmd内容,选择FLASH器件0,读取FLASH起始地址为0x100000,大小为0x600000字节的内容到0x40000000的内存地址,此处0x600000为6MB,与IDE中填写OHOS_Image.bin的文件大小必须相同

+

setenv bootargs "console=ttyAMA0,115200n8 root=flash fstype=jffs2 rw rootaddr=7M rootsize=8M";

+

表示设置bootargs参数为串口输出,波特率为115200,数据位8,rootfs挂载于FLASH上,文件系统类型为jffs2 rw,以支持可读写JFFS2文件系统。“rootaddr=7M rootsize=8M”处对应填入实际rootfs.img的烧写起始位置与长度,与IDE内所填大小必须相同

+

saveenv

+

表示保存当前配置。

+

reset

+

表示复位单板。

+

pri

+

表示查看显示参数。

+
+ + >![](../public_sys-resources/icon-notice.gif) **须知:** + >**“go 0x40000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 + +3. 若启动时显示**"hisilicon \#**字样,请输入**“reset”**指令,等待系统自启动进入系统,系统启动后,显示**“OHOS”**字样,输入**”./bin/helloworld”**并回车,显示成功结果如下图所示。 + + **图 3** 启动成功并执行应用程序图 + ![](figure/启动成功并执行应用程序图.png "启动成功并执行应用程序图") + + +## 下一步学习 + +恭喜您,已完成Hi3518的快速上手!建议您下一步进入[无屏摄像头产品开发](../guide/device-iotcamera.md)的学习 。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md new file mode 100644 index 0000000000000000000000000000000000000000..b4a3556e11ce25bd050ca3d4be84ae5897f9142c --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518-setting.md @@ -0,0 +1,114 @@ +# 安装开发板环境 + +- [Hi3518环境搭建](#section1724111409282) + - [硬件要求](#section487353718276) + - [软件要求](#section17315193935817) + +- [安装Linux服务器工具](#section8831868501) + - [将Linux shell改为bash](#section434110241084) + - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section25911132141020) + - [安装文件打包工具](#section390214473129) + + +## Hi3518环境搭建 + +### 硬件要求 + +- Hi3518EV300 IoT Camera开发板 +- USB转串口线、网线(Windows工作台通过USB转串口线、网线与开发板连接) + + 各硬件连接关系如下图所示。 + + +**图 1** 硬件连线图 +![](figure/硬件连线图-3.png "硬件连线图-3") + +### 软件要求 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section8831868501)章节。 + +Hi3518开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 + +**表 1** Linux服务器开发工具及获取途径 + + + + + + + + + + + + + + + + + + + + +

开发工具

+

用途

+

获取途径

+

bash

+

命令行处理工具

+

系统配置

+

编译基础软件包(仅ubuntu 20+需要)

+

编译依赖的基础软件包

+

通过互联网获取

+

dosfstools、mtools、mtd-utils

+

文件打包工具

+

通过apt-get install安装

+
+ +## 安装Linux服务器工具 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装hc-gen编译工具。 +>- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 + +### 将Linux shell改为bash + +查看shell是否为bash,在终端运行如下命令 + +``` +ls -l /bin/sh +``` + +如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: + +**方法一**:在终端运行如下命令,然后选择 no。 + +``` +sudo dpkg-reconfigure dash +``` + +**方法二**:先删除sh,再创建软链接。 + +``` +sudo rm -rf /bin/sh +sudo ln -s /bin/bash /bin/sh +``` + +### 安装编译依赖基础软件(仅Ubuntu 20+需要) + +执行以下命令进行安装: + +``` +sudo apt-get install build-essential gcc g++ make zlib* libffi-dev +``` + +### 安装文件打包工具 + +1. 打开Linux编译服务器终端。 +2. 运行如下命令,安装dosfstools,mtools,mtd-utils。 + + ``` + sudo apt-get install dosfstools mtools mtd-utils + ``` + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md new file mode 100644 index 0000000000000000000000000000000000000000..d0f3f9a5873ef8da0b02460a5f6b9acdaa2247a1 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3518.md @@ -0,0 +1,9 @@ +# Hi3518开发板 + +- **[安装开发板环境](quickstart-lite-steps-board3518-setting.md)** + +- **[运行Hello OHOS](quickstart-lite-steps-board3518-running.md)** + +- **[常见问题](quickstart-lite-steps-board3518-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md new file mode 100644 index 0000000000000000000000000000000000000000..fe69412c06e34eae1058d50523d5dd37c2956063 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-connection.md @@ -0,0 +1,142 @@ +# WLAN联网 + +- [源码编译](#section191121332125319) +- [镜像烧录](#section19458165166) +- [WLAN模组联网](#section194671619167) + +本示例将演示如何通过AT命令完成WLAN模组与网关联网。 + +## 源码编译 + +本节描述如何在Linux服务器上进行WLAN模组版本的编译。 + +如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/sourcecode-acquire.md)的编译操作。如果Linux编译环境通过软件包方式安装,请参考如下步骤。 + +1. 打开DevEco Device Tool工具,点击“View \> Terminal”,进入终端界面。 + + **图 1** IDE终端工具打开方法 + + + ![](figure/1.png) + + 在终端界面使用ssh命令连接linux服务器,如“ssh user@ipaddr”。 + + **图 2** 终端界面示意图 + + + ![](figure/2.png) + +2. 进入代码根路径,并在终端窗口,执行脚本命令“hb set”、“.”,选择需要编译的版本“wifiiot\_hispark\_pegasus”。 + + **图 3** 在终端界面选择目标构建版本示意图 + + + ![](figure/3.png) + +3. 执行“hb build”启动版本构建。 + + **图 4** 在终端界面执行编译命令示意图 + + + ![](figure/4.png) + +4. 编译结束后,如果出现“wifiiot\_hispark\_pegasus build success”字样,则证明构建成功,如下图所示。 + + **图 5** 编译成功示意图 + + + ![](figure/5.png) + +5. 构建成功后,会在./out/wifiiot/路径中生成以下文件,使用如下命令可以查看,至此编译构建流程结束。 + + ``` + ls -l out/hispark_pegasus/wifiiot_hispark_pegasus/ + ``` + + **图 6** 编译文件存放目录示意图 + + + ![](figure/3-0.png) + + +## 镜像烧录 + +Hi3861 WLAN模组的镜像烧录可以通过OpenHarmony IDE工具DevEco完成,工具的基本使用请参考[DevEco Device Tool使用指南](https://device.harmonyos.com/cn/docs/ide/user-guides/service_introduction-0000001050166905),烧录过程包含如下步骤。 + +1. 请连接好电脑和待烧录开发板,需要连接USB口,具体可参考[Hi3861开发板介绍](quickstart-lite-introduction-hi3861.md)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3861系列开发板串口驱动安装](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3861-drivers-0000001058153433)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001128311118.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/zh-cn_image_0000001128311116.png) + +4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3861系列开发板进行适配,无需单独修改。 +5. 在“hi3861”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001056563976_li848662117291)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“burn-serial”。 + - upload\_partitions:选择待烧录的文件,默认选择hi3861\_app。 + + ![](figure/zh-cn_image_0000001128470922.png) + +6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +7. 打开工程文件,在DevEco Device Tool界面的“PROJECT TASKS”中,点击hi3861下的**Upload**按钮,启动烧录。 + + ![](figure/zh-cn_image_0000001174270749.png) + +8. 启动烧录后,显示如下提示信息时,请按开发板上的RST按钮重启开发板。 + + ![](figure/zh-cn_image_0000001174270751.png) + +9. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001174350669.png) + + +## WLAN模组联网 + +完成版本构建及烧录后,下面开始介绍如何在串口终端上执行AT命令,使WLAN模组联网。 + +1. 保持Windows工作台和WLAN模组的连接状态,在DevEco工具最下方,点击“DevEco:Serial Monitor”按钮。 + + **图 7** 打开DevEco串口终端示意图 + + + ![](figure/5-1.png) + +2. 复位WLAN模组,终端界面显示“ready to OS start”,则启动成功。 + + **图 8** WLAN复位成功示意图 + + + ![](figure/6.png) + +3. 在DevEco的串口终端中,依次执行如下AT命令,启动STA模式,连接指定AP热点,并开启DHCP功能。 + + ``` + AT+STARTSTA # 启动STA模式 + AT+SCAN # 扫描周边AP + AT+SCANRESULT # 显示扫描结果 + AT+CONN="SSID",,2,"PASSWORD" # 连接指定AP,其中SSID/PASSWORD为待连接的热点名称和密码 + AT+STASTAT # 查看连接结果 + AT+DHCP=wlan0,1 # 通过DHCP向AP请求wlan0的IP地址 + ``` + +4. 查看WLAN模组与网关联通是否正常,如下图所示。 + + ``` + AT+IFCFG # 查看模组接口IP + AT+PING=X.X.X.X # 检查模组与网关的联通性,其中X.X.X.X需替换为实际的网关地址 + ``` + + **图 9** WLAN模组联网成功示意图 + + + ![](figure/截图.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..b0dbbae1b366bc12e6e97c8d365476b2168a5217 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-faqs.md @@ -0,0 +1,292 @@ +# 常见问题 + +- [安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”](#section1221016541119) +- [安装python3过程中,提示“-bash: make: command not found”](#section1913477181213) +- [安装python3过程中,提示“zlib not available”](#section108211415131210) +- [安装python3过程中,提示“No module named '\_ctypes'”](#section2062268124) +- [编译构建过程中,提示“No module named 'Crypto'”](#section982315398121) +- [编译构建过程中,提示“No module named 'ecdsa'”](#section102035451216) +- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](#section4498158162320) +- [编译构建过程中,提示找不到“-lgcc”](#section11181036112615) +- [编译构建过程中,提示找不到“python”](#section1571810194619) +- [安装 kconfiglib时,遇到lsb\_release错误](#section691681635814) + +## 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details + ``` + +- **可能原因** + + 环境中未安装“gcc”。 + +- **解决办法** + + 1、通过命令“apt-get install gcc”在线安装。 + + 2、完成后,重新安装python3。 + + +## 安装python3过程中,提示“-bash: make: command not found” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + -bash: make: command not found + ``` + +- **可能原因** + + 环境中未安装“make”。 + +- **解决办法** + + 1、通过命令“apt-get install make”在线安装。 + + 2、完成后,重新安装python3。 + + +## 安装python3过程中,提示“zlib not available” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + zipimport.ZipImportError: can't decompress data; zlib not avaliable + ``` + +- **可能原因** + + 环境中未安装“zlib”。 + +- **解决办法** + + 方法1:通过命令“apt-get install zlib”在线安装。 + + 方法2:如果软件源中没有该软件,请从“www.zlib.net”下载版本代码,并离线安装。 + + ![](figure/10.png) + + 完成下载后,通过以下命令安装: + + ``` + # tar xvf zlib-1.2.11.tar.gz + # cd zlib-1.2.11 + # ./configure + # make && make install + ``` + + 完成后,重新安装python3。 + + +## 安装python3过程中,提示“No module named '\_ctypes'” + +- **现象描述** + + 安装python3过程中出现以下错误: + + ``` + ModuleNotFoundError:No module named ‘_ctypes’ + ``` + + +- **可能原因** + + 环境中未安装“libffi”和“libffi-devel”。 + + +- **解决办法** + + 1、通过命令“apt-get install libffi\* -y”,在线安装。 + + 2、完成后,重新安装python3。 + + +## 编译构建过程中,提示“No module named 'Crypto'” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + ModuleNotFoundError: No module named 'Crypto' + ``` + + +- **可能原因** + + 环境中未安装“Crypto”。 + + +- **解决办法** + + 方法1:通过命令“pip3 install Crypto”,在线安装。 + + 方法2:离线安装 + + 通过网页[https://pypi.org/project/pycrypto/\#files](https://pypi.org/project/pycrypto/#files),下载源码。 + + ![](figure/zh-cn_image_0000001128470864.png) + + 将源码放置在Linux服务器中,解压,并安装“python3 setup.py install”。 + + 完成上述安装后,重新构建。 + + +## 编译构建过程中,提示“No module named 'ecdsa'” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + ModuleNotFoundError:No module named 'ecdsa' + ``` + + +- **可能原因** + + 环境中未安装“ecdsa”。 + + +- **解决办法** + + 方法1:通过命令“pip3 install ecdsa”,在线安装。 + + 方法2:离线安装 + + 通过网页[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files),下载安装包。 + + ![](figure/zh-cn_image_0000001128311072.png) + + 将安装包放置Linux服务器中,并安装“pip3 install ecdsa-0.15-py2.py3-none-any.whl”。 + + 完成上述安装后,重新构建。 + + +## 编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + Could not find a version that satisfies the requirement six>=1.9.0 + ``` + + +- **可能原因** + + 环境中未安装合适的“six”。 + + +- **解决办法** + + 方法1:通过命令“pip3 install six”,在线安装。 + + 方法2:离线安装 + + 通过网页[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files),下载安装包。 + + ![](figure/zh-cn_image_0000001174270699.png) + + 将源码放置在Linux服务器中,并安装“pip3 install six-1.14.0-py2.py3-none-any.whl”。 + + 完成上述安装后,重新构建。 + + +## 编译构建过程中,提示找不到“-lgcc” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + riscv32-unknown-elf-ld: cannot find -lgcc + ``` + + +- **可能原因** + + 交叉编译器gcc\_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。 + + ``` + ~/gcc_riscv32/bin/:/data/toolchain/ + ``` + + +- **解决办法** + + 重新修改gcc\_riscv32的PATH,将多余的“/”删除。 + + ``` + ~/gcc_riscv32/bin:/data/toolchain/ + ``` + + +## 编译构建过程中,提示找不到“python” + +- **现象描述** + + 编译构建过程中出现以下错误: + + ``` + -bash: /usr/bin/python: No such file or directory + ``` + + +- **可能原因**1 + + 没有装python。 + +- **解决办法** + + 请按照 [安装Python环境](quickstart-lite-env-setup-lin.md) + +- **可能原因2** + + ![](figure/zh-cn_image_0000001128311070.png) + +- **解决办法** + + usr/bin目录下没有python软链接,请运行以下命令添加软链接: + + ``` + # cd /usr/bin/ + # which python3 + # ln -s /usr/local/bin/python3 python + # python --version + ``` + + 例: + + ![](figure/zh-cn_image_0000001174350623.png) + + +## 安装 kconfiglib时,遇到lsb\_release错误 + +- **现象描述** + + 安装kconfiglib过程中遇到如下错误打印: + + ``` + subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1. + ``` + +- **可能原因** + + lsb\_release模块基于的python版本与现有python版本不一致 + +- **解决办法** + + 执行"find / -name lsb\_release",找到lsb\_release位置并删除,如:"sudo rm -rf /usr/bin/lsb\_release" + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md new file mode 100644 index 0000000000000000000000000000000000000000..547aa5affc7e6d2081e39bc482a1d2168043840d --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-running.md @@ -0,0 +1,158 @@ +# 运行Hello World + +- [修改源码](#section79601457101015) +- [调测验证](#section1621064881419) +- [printf打印](#section1246911301217) +- [根据asm文件进行问题定位](#section199621957141014) +- [运行结果](#section18115713118) +- [下一步学习](#section9712145420182) + +本示例将演示如何编写简单业务,输出“Hello World”,初步了解OpenHarmony 如何运行在开发板上。 + +## 修改源码 + +bugfix和新增业务两种情况,涉及源码修改。下面以新增业务(my\_first\_app)为例,向开发者介绍如何进行源码修改。 + +1. 确定目录结构。 + + 开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 + + 例如:在app下新增业务my\_first\_app,其中hello\_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下: + + ``` + . + └── applications + └── sample + └── wifi-iot + └── app + │── my_first_app + │ │── hello_world.c + │ └── BUILD.gn + └── BUILD.gn + ``` + +2. 编写业务代码。 + + 新建./applications/sample/wifi-iot/app/my\_first\_app下的hello\_world.c文件,在hello\_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) + + ``` + #include + #include "ohos_init.h" + #include "ohos_types.h" + + void HelloWorld(void) + { + printf("[DEMO] Hello world.\n"); + } + SYS_RUN(HelloWorld); + ``` + +3. 编写用于将业务构建成静态库的BUILD.gn文件。 + + 新建./applications/sample/wifi-iot/app/my\_first\_app下的BUILD.gn文件,并完成如下配置。 + + 如[步骤1](#li5479332115116)所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 + + ``` + static_library("myapp") { + sources = [ + "hello_world.c" + ] + include_dirs = [ + "//utils/native/lite/include" + ] + } + ``` + + - static\_library中指定业务模块的编译结果,为静态库文件libmyapp.a,开发者根据实际情况完成填写。 + - sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。 + - include\_dirs中指定source所需要依赖的.h文件路径。 + +4. 编写模块BUILD.gn文件,指定需参与构建的特性模块。 + + 配置./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,以my\_first\_app举例,features字段配置如下。 + + ``` + import("//build/lite/config/component/lite_component.gni") + + lite_component("app") { + features = [ + "my_first_app:myapp", + ] + } + ``` + + - my\_first\_app是相对路径,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn。 + - myapp是目标,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn中的static\_library\("myapp"\)。 + + +## 调测验证 + +目前调试验证的方法有两种,分别为通过printf打印日志、通过asm文件定位panic问题,开发者可以根据具体业务情况选择。 + +由于本示例业务简单,采用printf打印日志的调试方式即可。下面开始介绍这两种调试手段的使用方法。 + +## printf打印 + +代码中增加printf维测,信息会直接打印到串口上。开发者可在业务关键路径或业务异常位置增加日志打印,如下所示。 + +``` +void HelloWorld(void) +{ + printf("[DEMO] Hello world.\n"); +} +``` + +## 根据asm文件进行问题定位 + +系统异常退出时,会在串口上打印异常退出原因调用栈信息,如下文所示。通过解析异常栈信息可以定位异常位置。 + +``` +=======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******************* +``` + +为解析上述调用栈信息,需要使用到Hi3861\_wifiiot\_app.asm文件,该文件记录了代码中函数在Flash上的符号地址以及反汇编信息。asm文件会随版本大包一同构建输出,存放在./out/wifiiot/路径下。 + +1. 将调用栈CallStack信息保存到txt文档中,以便于编辑。(可选) +2. 打开asm文件,并搜索CallStack中的地址,列出对应的函数名 信息。通常只需找出前几个栈信息对应的函数,就可明确异常代码方向。 + + ``` + 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. 根据以上调用栈信息,可以定位WadRecvCB函数中出现了异常。 + + ![](figure/zh-cn_image_0000001174270737.png) + +4. 完成代码排查及修改。 + +## 运行结果 + +示例代码编译、烧录、运行、调测后,在串口界面会显示如下结果: + +``` +ready to OS start +FileSystem mount ok. +wifi init success! +[DEMO] Hello world. +``` + +## 下一步学习 + +恭喜,您已完成Hi3861 WLAN模组快速上手!建议您下一步进入[WLAN产品开发](../guide/device-wifi.md)的学习 。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md new file mode 100644 index 0000000000000000000000000000000000000000..90998c5acf0e5b6ee722fdcb6030a34e8a83b5fb --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861-setting.md @@ -0,0 +1,367 @@ +# 安装开发板环境 + +- [Hi3861工具要求](#section466851916410) + - [硬件要求](#section19202111020215) + - [软件要求](#section727451210318) + +- [安装Linux编译工具](#section497484245614) + - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) + - [安装Scons](#section7438245172514) + - [安装python模块](#section88701892341) + - [安装gcc\_riscv32(WLAN模组类编译工具链)](#section34435451256) + +- [安装USB转串口驱动](#section1027732411513) + +## Hi3861工具要求 + +### 硬件要求 + +- Linux服务器 +- Windows工作台(主机电脑) +- Hi3861 WLAN模组 +- USB Type-C线(Windows工作台通过USB与Hi3861 WLAN模组连接) + +各硬件连接关系如下图所示。 + +**图 1** 硬件连线图 +![](figure/硬件连线图.png "硬件连线图") + +### 软件要求 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>本节描述采用安装包方式安装相关工具的操作步骤。如果是Docker方式安装,无需安装[表1](#table6299192712513)中的Linux服务器相关工具,只需安装Windows工作台工具即可。 + +Hi3861开发板需要的工具如下表所示。 + +**表 1** Hi3861开发板需要的工具 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

平台类型

+

开发工具

+

用途

+

获取途径

+

Linux服务器

+

编译基础软件包(仅ubuntu 20+需要)

+

编译依赖的基础软件包

+

通过互联网获取

+

Linux服务器

+

SCons3.0.4+

+

编译构建工具

+

通过互联网获取

+

Linux服务器

+

python模块:setuptools、kconfiglib、pycryptodome、six、ecdsa

+

编译构建工具

+

通过互联网获取

+

Linux服务器

+

gcc riscv32

+

编译构建工具

+

通过互联网获取

+

Windows工作台

+

CH341SER.EXE

+

USB转串口驱动

+

http://www.wch.cn/search?q=ch340g&t=downloads

+
+ +## 安装Linux编译工具 + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gcc\_riscv32编译工具。 +>- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gcc\_riscv32编译工具。安装gcc\_riscv32编译工具时,请确保编译工具的环境变量路径唯一。 + +### 安装编译依赖基础软件(仅Ubuntu 20+需要) + +执行以下命令进行安装: + +``` +sudo apt-get install build-essential gcc g++ make zlib* libffi-dev +``` + +### 安装Scons + +1. 打开Linux编译服务器终端。 +2. 运行如下命令,安装SCons安装包。 + + ``` + python3 -m pip install scons + ``` + +3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 + + ``` + scons -v + ``` + + **图 2** SCons安装成功界面,版本要求3.0.4以上 + ![](figure/SCons安装成功界面-版本要求3-0-4以上.png "SCons安装成功界面-版本要求3-0-4以上") + + +### 安装python模块 + +1. 运行如下命令,安装python模块setuptools。 + + ``` + pip3 install setuptools + ``` + +2. 安装GUI menuconfig工具(Kconfiglib),建议安装Kconfiglib 13.2.0+版本,任选如下一种方式。 + - **命令行方式:** + + ``` + sudo pip3 install kconfiglib + ``` + + + - **安装包方式:** + 1. 下载.whl文件(例如:kconfiglib-13.2.0-py2.py3-none-any.whl)。 + + 下载路径:“[https://pypi.org/project/kconfiglib\#files](https://pypi.org/project/kconfiglib#files)” + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install kconfiglib-13.2.0-py2.py3-none-any.whl + ``` + + + +3. 安装pycryptodome,任选如下一种方式。 + + 安装升级文件签名依赖的Python组件包,包括:pycryptodome、six、ecdsa。安装ecdsa依赖six,请先安装six,再安装ecdsa。 + + - **命令行方式:** + + ``` + sudo pip3 install pycryptodome + ``` + + - **安装包方式:** + 1. 下载.whl文件(例如:pycryptodome-3.9.9-cp38-cp38-manylinux1\_x86\_64.whl)。 + + 下载路径:“[https://pypi.org/project/pycryptodome/\#files](https://pypi.org/project/pycryptodome/#files)”。 + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl + ``` + + + +4. 安装six,任选如下一种方式。 + - **命令行方式:** + + ``` + sudo pip3 install six --upgrade --ignore-installed six + ``` + + + - **安装包方式:** + 1. 下载.whl文件(例如:six-1.12.0-py2.py3-none-any.whl)。 + + 下载路径:“[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files)” + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install six-1.12.0-py2.py3-none-any.whl + ``` + + + +5. 安装ecdsa,任选如下一种方式。 + - **命令行方式:** + + ``` + sudo pip3 install ecdsa + ``` + + - **安装包方式:** + 1. 下载.whl文件(例如:ecdsa-0.14.1-py2.py3-none-any.whl)。 + + 下载路径:“[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files)” + + + 1. 运行如下命令,安装.whl文件。 + + ``` + sudo pip3 install ecdsa-0.14.1-py2.py3-none-any.whl + ``` + + + + +### 安装gcc\_riscv32(WLAN模组类编译工具链) + +>![](../public_sys-resources/icon-notice.gif) **须知:** +>- Hi3861平台仅支持使用libgcc运行时库的静态链接,不建议开发者使用libgcc运行时库的动态链接,会导致商业分发时被GPL V3污染。 +>- 通过下述步骤2-15,我们编译好了gcc\_riscv32 镜像,提供给开发者[直接下载](https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz)使用。直接下载 gcc\_riscv32 镜像的开发者可省略下述2-15步。 + +1. 打开Linux编译服务器终端。 +2. 环境准备,请安装"gcc, g++, bison, flex, makeinfo"软件,确保工具链能正确编译。 + + ``` + sudo apt-get install gcc && sudo apt-get install g++ && sudo apt-get install flex bison && sudo apt-get install texinfo + ``` + +3. 下载riscv-gnu-toolchain交叉编译工具链。 + + ``` + git clone --recursive https://gitee.com/mirrors/riscv-gnu-toolchain.git + ``` + +4. 打开文件夹riscv-gnu-toolchain,先删除空文件夹,以防止下载newlib,binutils,gcc时冲突。 + + ``` + cd riscv-gnu-toolchain && rm -rf riscv-newlib && rm -rf riscv-binutils && rm -rf riscv-gcc + ``` + +5. 下载riscv-newlib-3.0.0。 + + ``` + git clone -b riscv-newlib-3.0.0 https://github.com/riscv/riscv-newlib.git + ``` + +6. 下载riscv-binutils-2.31.1。 + + ``` + git clone -b riscv-binutils-2.31.1 https://github.com/riscv/riscv-binutils-gdb.git + ``` + +7. 下载riscv-gcc-7.3.0。 + + ``` + git clone -b riscv-gcc-7.3.0 https://github.com/riscv/riscv-gcc + ``` + +8. 添加riscv-gcc-7.3.0补丁。 + + 访问gcc官方补丁链接[89411](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=026216a753ef0a757a9e368a59fa667ea422cf09;hp=2a23a1c39fb33df0277abd4486a3da64ae5e62c2),[86724](https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/graphite.h;h=be0a22b38942850d88feb159603bb846a8607539;hp=4e0e58c60ab83f1b8acf576e83330466775fac17;hb=b1761565882ed6a171136c2c89e597bc4dd5b6bf;hpb=fbd5f023a03f9f60c6ae36133703af5a711842a3),按照补丁链接中要求的修改,手动将变更添加到对应的.c和.h文件中,注意由于patch版本与下载的gcc版本有所偏差,行数有可能对应不上,请自行查找patch中的关键字定位到对应行。 + +9. 下载[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 + ``` + +10. 下载[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 + ``` + +11. 下载[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 + ``` + +12. 打开文件夹riscv-gnu-toolchain,新建工具链输出目录。 + + ``` + cd /opt && mkdir gcc_riscv32 + ``` + +13. 编译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 .. + ``` + +14. 编译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 .. + ``` + +15. 编译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 + ``` + +16. 设置环境变量。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果直接采用编译好的riscv32 gcc包,请参照如下步骤设置环境变量: + >1. 将压缩包解压到根目录 + > ``` + > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ + > ``` + >2. 设置环境变量。 + > ``` + > vim ~/.bashrc + > ``` + >3. 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + > ``` + > export PATH=~/gcc_riscv32/bin:$PATH + > ``` + + ``` + vim ~/.bashrc + ``` + + 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 + + ``` + export PATH=~/gcc_riscv32/bin:$PATH + ``` + +17. 生效环境变量。 + + ``` + source ~/.bashrc + ``` + +18. Shell命令行中输入如下命令,如果能正确显示编译器版本号,表明编译器安装成功。 + + ``` + riscv32-unknown-elf-gcc -v + ``` + + +## 安装USB转串口驱动 + +相关步骤在Windows工作台操作。 + +1. 点击链接[下载CH341SER USB转串口](http://www.hihope.org/download/download.aspx?mtt=8)驱动程序。 +2. 点击安装包,安装驱动程序。 +3. 驱动安装完成后,重新插拔USB接口,串口信息显示如下图所示。 + + ![](figure/zh-cn_image_0000001174350633.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md new file mode 100644 index 0000000000000000000000000000000000000000..8aca8589071142415783b378a6f932e3213722fa --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps-board3861.md @@ -0,0 +1,11 @@ +# Hi3861开发板 + +- **[安装开发板环境](quickstart-lite-steps-board3861-setting.md)** + +- **[WLAN联网](quickstart-lite-steps-board3861-connection.md)** + +- **[运行Hello World](quickstart-lite-steps-board3861-running.md)** + +- **[常见问题](quickstart-lite-steps-board3861-faqs.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite-steps.md b/zh-cn/device-dev/quick-start/quickstart-lite-steps.md new file mode 100644 index 0000000000000000000000000000000000000000..49545483c62cc3790af97196c58f3e29ce9c00b5 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite-steps.md @@ -0,0 +1,9 @@ +# 开发步骤 + +- **[Hi3861开发板](quickstart-lite-steps-board3861.md)** + +- **[Hi3516开发板](quickstart-lite-steps-board3516.md)** + +- **[Hi3518开发板](quickstart-lite-steps-board3518.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-lite.md b/zh-cn/device-dev/quick-start/quickstart-lite.md new file mode 100644 index 0000000000000000000000000000000000000000..47a4ec111d5d343ef0f1abe4321730c8a201249a --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-lite.md @@ -0,0 +1,11 @@ +# 轻量和小型系统入门 + +- **[概述](quickstart-lite-overview.md)** + +- **[了解开发板](quickstart-lite-introduction.md)** + +- **[搭建系统环境](quickstart-lite-env-setup.md)** + +- **[开发步骤](quickstart-lite-steps.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-burn.md b/zh-cn/device-dev/quick-start/quickstart-standard-burn.md new file mode 100644 index 0000000000000000000000000000000000000000..be86e001d66decb04ed2382d2b8158351437b267 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-burn.md @@ -0,0 +1,201 @@ +# 镜像烧录 + +- [下一步](#section5600113114323) + +标准系统烧录,在V2.2 Beta1及以上版本支持。 + +Hi3516DV300支持烧录标准系统,其烧录方式包括网口烧录和串口烧录三种方式,其中: + +- **Windows系统:支持网口烧录和串口烧录** +- **Linux系统:支持串口烧录和网口烧录。** + +同一种烧录方式(如网口烧录),在Windows和Linux环境下的烧录操作完全一致,区别仅在于DevEco Device Tool环境搭建不同。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>当前Hi3516DV300开发板支持通过网口、USB、串口三种方式烧录OpenHarmony标准系统。本文以网口方式为例讲解烧录操作,其他两种烧录方式请参照[Hi3516DV300烧录指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)。 + +### 前提条件 + +在DevEco Device Tool中[打开一个工程](https://device.harmonyos.com/cn/docs/ide/user-guides/open_project-0000001071680043),该工程文件夹选择待烧录文件所在文件夹即可。其中开发板类型固定选择Hi3516DV300,Framework选择“Hb”。 + +### 使用网口烧录 + +Hi3516DV300开发板使用网口录方式,支持Windows和Linux系统。 + +1. 请连接好电脑和待烧录开发板,需要同时连接串口、网口和电源,具体可参考[Hi3516DV300开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3516-0000001152041033)。 +2. 打开电脑的设备管理器,查看并记录对应的串口号。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果对应的串口异常,请根据[Hi3516DV300/Hi3518EV300开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 + + ![](figure/zh-cn_image_0000001114129428.png) + +3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 + + ![](figure/2021-01-27_170334-16.png) + +4. 在**Partition Configuration**页签中,按照下表内容填写烧录文件信息,包括: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Name

+

Binary

+

Memory

+

System

+

Address

+

Length

+

Board

+

Type

+

fastboot

+

选择“u-boot-hi3516dv300_emmc.bin”

+

emmc

+

none

+

0x000000

+

0x100000

+

固定选择“hi3516dv300”

+

NA

+

boot

+

选择“uImage”

+

emmc

+

none

+

0x100000

+

0xf00000

+

NA

+

updater

+

选择“updater.img”

+

emmc

+

ext3/4

+

0x1000000

+

0x1400000

+

NA

+

misc

+

空白,不用选择

+

emmc

+

none

+

0x2400000

+

0x100000

+

NA

+

system

+

选择“system.img”

+

emmc

+

ext3/4

+

0x2500000

+

0xceb00000

+

NA

+

vendor

+

选择“vendor.img”

+

emmc

+

ext3/4

+

0xd1000000

+

0x10000000

+

NA

+

userdata

+

选择“userdata.img”

+

emmc

+

ext3/4

+

0xe1000000

+

0x5b800000

+

NA

+
+ + ![](figure/zh-cn_image_0000001130584312.png) + +5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 + + - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li1050616379507)中查询的串口号。 + - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 + - upload\_partitions:选择待烧录的文件,包括fastboot、boot、updater、misc、system、vendor和userdata。 + + ![](figure/zh-cn_image_0000001117621400.png) + +6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516DV300网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 +7. 设置网口烧录的IP地址信息,设置如下选项: + + - upload\_net\_server\_ip:选择步骤6中设置的IP地址信息。例如192.168.1.2 + - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 + - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 + - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 + + ![](figure/zh-cn_image_0000001117463460.png) + +8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 +9. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 + + ![](figure/zh-cn_image_0000001114129432.png) + +10. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 + + ![](figure/zh-cn_image_0000001113969542.png) + + +## 下一步 + +恭喜!您已经完成了OpenHarmony标准系统的快速入门,接下来可[开发一个小示例](../guide/device-clock-guide.md),进一步熟悉OpenHarmony的开发。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md new file mode 100644 index 0000000000000000000000000000000000000000..6f3ed7f03f02d6cb9e59dadbe00d463d7734d319 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-docker-environment.md @@ -0,0 +1,118 @@ +# 搭建Ubuntu环境及编译(Docker方式) + +- [获取标准系统源码](#section8761819202511) + - [前提条件](#section102871547153314) + - [操作步骤](#section429012478331) + +- [获取Docker环境](#section181431248132513) +- [编译](#section92391739152318) + +OpenHarmony标准系统为开发者提供的Docker环境已经将对应的编译工具链进行了封装,开发者可省略对应工具的安装。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>- 在使用Docker前需要先安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/ubuntu/)。 +>- Docker方式和安装包方式二选一即可。选择Docker方式的开发者可跳过[安装包方式](quickstart-standard-package-environment.md)的内容。 + +## 获取标准系统源码 + +### 前提条件 + +1. 注册码云gitee账号。 +2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 +3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 + + ``` + git config --global user.name "yourname" + git config --global user.email "your-email-address" + git config --global credential.helper store + ``` + +4. 安装码云repo工具,可以执行如下命令。 + + ``` + curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 + chmod a+x /usr/local/bin/repo + pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests + ``` + + +### 操作步骤 + +方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 + +``` +repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +方式二:通过repo + https 下载。 + +``` +repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +## 获取Docker环境 + +**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** + +1. 获取Docker镜像。 + + ``` + docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + +2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 + ``` + + +**方式二:通过Dockerfile 构建本地Docker镜像进行构建** + +1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 + + ``` + git clone https://gitee.com/openharmony/docs.git + ``` + +2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 + + ``` + cd docs/docker/standard + ./build.sh + ``` + +3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 + + ``` + docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 + ``` + + +## 编译 + +1. 在源码的根目录执行预处理脚本。 + + ``` + ../scripts/prepare.sh + ``` + +2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + +3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](quickstart-standard-burn.md)。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>退出Docker执行exit命令即可。 + diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-8.md" b/zh-cn/device-dev/quick-start/quickstart-standard-faq.md similarity index 100% rename from "zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-8.md" rename to zh-cn/device-dev/quick-start/quickstart-standard-faq.md diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md new file mode 100644 index 0000000000000000000000000000000000000000..d35cc274995107ccc178c03fd48a41641dcc8ea2 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-package-environment.md @@ -0,0 +1,98 @@ +# 搭建Ubuntu环境及编译(安装包方式) + +- [安装依赖工具](#section18431165519244) +- [获取标准系统源码](#section113751052102517) + - [前提条件](#section102871547153314) + - [操作步骤](#section429012478331) + +- [执行prebuilts](#section0495320152619) +- [编译](#section1664835963517) + +## 安装依赖工具 + +安装命令如下: + +``` +sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 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 +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>以上安装命令适用于Ubuntu18.04,其他版本请根据安装包名称采用对应的安装命令。 + +## 获取标准系统源码 + +### 前提条件 + +1. 注册码云gitee账号。 +2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 +3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 + + ``` + git config --global user.name "yourname" + git config --global user.email "your-email-address" + git config --global credential.helper store + ``` + +4. 安装码云repo工具,可以执行如下命令。 + + ``` + curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 + chmod a+x /usr/local/bin/repo + pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests + ``` + + +### 操作步骤 + +方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 + +``` +repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +方式二:通过repo + https 下载。 + +``` +repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify +repo sync -c +repo forall -c 'git lfs pull' +``` + +## 执行prebuilts + +在源码根目录下执行脚本,安装编译器及二进制工具。 + +``` +bash build/prebuilts_download.sh +``` + +下载的prebuilts二进制默认存放在与OpenHarmony同目录下的OpenHarmony\_2.0\_canary\_prebuilts下。 + +## 编译 + +在Linux环境进行如下操作: + +1. 进入源码根目录,执行如下命令进行版本编译。 + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 + +2. 检查编译结果。编译完成后,log中显示如下: + + ``` + build system image successful. + =====build Hi3516DV300 successful. + ``` + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >其他模块化编译操作,可参见[编译构建指导](../subsystems/subsys-build-standard-large.md)。 + +3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](quickstart-standard-burn.md)。 + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md b/zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md new file mode 100644 index 0000000000000000000000000000000000000000..bf45ab1684dce5b497d0685d1cc05e3f20e43ac3 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard-windows-environment.md @@ -0,0 +1,179 @@ +# Windows开发环境准备 + +- [获取软件](#zh-cn_topic_0000001058091994_section1483143015558) +- [安装Visual Studio Code](#zh-cn_topic_0000001058091994_section71401018163318) +- [安装Python](#zh-cn_topic_0000001058091994_section16266553175320) +- [安装Node.js](#zh-cn_topic_0000001058091994_section5353233124511) +- [安装hpm](#zh-cn_topic_0000001058091994_section173054793610) +- [安装DevEco Device Tool插件](#zh-cn_topic_0000001058091994_section4336315185716) + +系统要求:Windows 10 64位系统。 + +DevEco Device Tool以插件方式提供,基于Visual Studio Code进行扩展,安装分为如下几步: + +1. 安装Visual Studio Code +2. 安装Python +3. 安装Node.js +4. 安装hpm +5. 安装DevEco Device Tool插件 + +## 获取软件 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

工具名称

+

用途说明

+

版本要求

+

获取渠道

+

Visual Studio Code

+

代码编辑工具

+

V1.53及以上 64位版本。

+

https://code.visualstudio.com/Download

+

Python

+

编译构建工具

+

V3.7.4~V3.8.x 64位版本

+

https://www.python.org/downloads/

+

Node.js

+

提供npm环境

+

v12.0.0及以上 64位版本

+

https://nodejs.org/zh-cn/download/

+

hpm

+

包管理工具

+

最新版

+

请参考安装hpm

+

DevEco Device Tool

+

OpenHarmony源码的编译、烧录、调试插件工具

+

v2.2 Beta1

+

https://device.harmonyos.com/cn/ide#download

+

下载前,请使用华为开发者帐号登录,如未注册,请先注册华为开发者帐号

+
+ +## 安装Visual Studio Code + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Visual Studio Code,打开命令行工具,输入**code --version**命令,检查版本号是否为1.53及以上版本;可以正常返回版本号,说明环境变量设置也正确。 + +1. 双击Visual Studio Code软件包进行安装。安装过程中,请勾选“添加到PATH(重启后生效)”。 + + ![](figure/zh-cn_image_0000001057335403.png) + +2. 安装完成后,打开命令行工具,输入**code --version**命令,可以正常显示版本号说明安装成功。 + +## 安装Python + +>![](../public_sys-resources/icon-note.gif) **说明:** +>请注意,Python版本要求为V3.7.4\~V3.8.x 64位版本。 + +1. 双击Python安装包进行安装,勾选“**Add Python 3.8 to PATH**”,然后点击**Install Now**开始安装。 + + ![](figure/zh-cn_image_0000001176317561.png) + +2. 等待安装完成后,点击**Close**。 + + ![](figure/zh-cn_image_0000001142794291.png) + +3. 打开命令行工具,输入python --version,检查安装结果。 + + ![](figure/zh-cn_image_0000001130278040.png) + +4. 在命令行工具中,分别执行如下命令设置pip源,用于后续安装DevEco Device Tool过程中下载依赖的组件包。 + + ``` + pip config set global.trusted-host repo.huaweicloud.com + pip config set global.index-url https://repo.huaweicloud.com/repository/pypi/simple + pip config set global.timeout 120 + ``` + + +## 安装Node.js + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装Node.js,打开命令行工具,输入**node -v**命令,检查版本号是否为12.0.0及以上版本。 + +1. 点击下载后的软件包进行安装,全部按照默认设置点击**Next**,直至**Finish**。安装过程中,Node.js会自动在系统的path环境变量中配置node.exe的目录路径。 +2. 重新打开命令行工具,输入“node -v“命令,能正常查询Node.js的版本号,说明Node.js安装成功。 + +## 安装hpm + +该方式需先确保**Node.js**安装成功。 + +在安装hpm前,请检查网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问。这种情况下,需要先[设置npm代理](https://device.harmonyos.com/cn/docs/ide/user-guides/npm_proxy-0000001054491032),才能安装hpm。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>如果已安装hpm,可以执行**npm update -g @ohos/hpm-cli**命令升级hpm至最新版本。 + +1. 建议将npm源配置为国内镜像,例如设置为华为云镜像源。 + + ``` + npm config set registry https://repo.huaweicloud.com/repository/npm/ + ``` + +2. 打开命令行工具,执行如下命令安装最新版本hpm。 + + ``` + npm install -g @ohos/hpm-cli + ``` + + ![](figure/zh-cn_image_0000001073840162.png) + +3. 安装完成后,执行如下命令(V为大写字母)检查hpm安装结果。 + + ``` + hpm -V + ``` + + +## 安装DevEco Device Tool插件 + +安装DevEco Device Tool插件,**主机的用户名不能包含中文字符**,否则可能导致运行出现错误。 + +DevEco Device Tool正常运行需要依赖于C/C++和CodeLLDB插件,在安装完DevEco Device Tool后,会自动从Visual Studio Code的插件市场安装C/C++和CodeLLDB插件。因此,在安装DevEco Device Tool前,请检查Visual Studio Code的网络连接状态,如果网络不能直接访问Internet,则需要通过代理服务器才可以访问,请先[Visual Studio Code代理设置](https://device.harmonyos.com/cn/docs/ide/user-guides/vscode_proxy-0000001074231144)。 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>安装DevEco Device Tool时,请先关闭Visual Studio Code。 + +1. 解压DevEco Device Tool插件压缩包,双击安装包程序进行安装。 +2. 安装过程中,会自动安装DevEco Device Tool所需的依赖文件(如C/C++和CodeLLDB插件)和执行程序。 + + ![](figure/zh-cn_image_0000001072468991.png) + +3. 安装完成后,会自动关闭命令行工具窗口。 +4. 启动Visual Studio Code,点击左侧的![](figure/zh-cn_image_0000001072757874.png)按钮,检查INSTALLED中,是否已成功安装C/C++、CodeLLDB和DevEco Device Tool。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如果C/C++和CodeLLDB插件安装不成功,则DevEco Device Tool不能正常运行,解决方法,详细请参考:[离线安装C/C++和CodeLLDB插件](https://device.harmonyos.com/cn/docs/ide/user-guides/offline_plugin_install-0000001074376846)。 + + ![](figure/zh-cn_image_0000001142802505.png) + + diff --git a/zh-cn/device-dev/quick-start/quickstart-standard.md b/zh-cn/device-dev/quick-start/quickstart-standard.md new file mode 100644 index 0000000000000000000000000000000000000000..3931c3264362456d7d60add4edbdeefc5eb47f3b --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart-standard.md @@ -0,0 +1,15 @@ +# 标准系统入门 + +- **[常见问题](quickstart-lite-env-setup-faqs.md)** + +- **[Windows开发环境准备](quickstart-standard-windows-environment.md)** + +- **[搭建Ubuntu环境及编译(Docker方式)](quickstart-standard-docker-environment.md)** + +- **[搭建Ubuntu环境及编译(安装包方式)](quickstart-standard-package-environment.md)** + +- **[镜像烧录](quickstart-standard-burn.md)** + +- **[常见问题](quickstart-standard-faq.md)** + + diff --git a/zh-cn/device-dev/quick-start/quickstart.md b/zh-cn/device-dev/quick-start/quickstart.md new file mode 100644 index 0000000000000000000000000000000000000000..5ab9867ff455695acd09b4325c016a46cae44dc8 --- /dev/null +++ b/zh-cn/device-dev/quick-start/quickstart.md @@ -0,0 +1,7 @@ +# 快速入门 + +- **[轻量和小型系统入门](quickstart-lite.md)** + +- **[标准系统入门](quickstart-standard.md)** + + diff --git "a/zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" "b/zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" deleted file mode 100755 index fae4d8bb46425aee84df037e4e126c480c18bd9d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\344\272\206\350\247\243\345\274\200\345\217\221\346\235\277.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 了解开发板 - -- **[Hi3861开发板介绍](Hi3861开发板介绍.md)** - -- **[Hi3516开发板介绍](Hi3516开发板介绍.md)** - -- **[Hi3518开发板介绍](Hi3518开发板介绍.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" "b/zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" deleted file mode 100644 index 3e0807591c3e4ae71f160c45a6da9dc6cbf3dbca..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\205\245\351\227\250\344\273\213\347\273\215.md" +++ /dev/null @@ -1,54 +0,0 @@ -# 入门介绍 - -- [快速入门流程](#section7825218111517) -- [开发板简介](#zh-cn_topic_0000001053666242_section047719215429) -- [开发板规格](#zh-cn_topic_0000001053666242_section15192203316533) - -开发者可通过本文快速掌握OpenHarmony标准系统的环境搭建、编译、烧录、启动等操作。标准系统可以使用Windows环境进行开发、烧录,使用Linux环境进行编译。 - -本文将以当前推荐的Hi3516DV300开发板为例对上述操作进行说明。 - -## 快速入门流程 - -标准系统快速入门流程如下图所示,其中“搭建Ubuntu环境及编译”环节可根据实际情况选择docker方式或工具包方式其中一种即可。 - -**图 1** 标准环境快速入门流程 -![](figures/标准环境快速入门流程.png "标准环境快速入门流程") - -## 开发板简介 - -Hi3516DV300作为新一代行业专用Smart HD IP摄像机SOC,集成新一代ISP\(Image Signal Processor\)、H.265视频压缩编码器,同时集成高性能NNIE引擎,使得Hi3516DV300在低码率、高画质、智能处理和分析、低功耗等方面引领行业水平。 - -**图 2** Hi3516单板正面外观图 - - -![](figures/3516正面-16.png) - -## 开发板规格 - -**表 1** Hi3516开发板规格清单 - - - - - - - - - - - - - -

规格类型

-

规格清单

-

处理器及内部存储

-
  • Hi3516DV300芯片
  • DDR3 1GB
  • eMMC4.5,8GB容量
-

外部器件

-
  • 以太网口
  • 音频视频
    • 1路语音输入
    • 1路单声道(AC_L)输出,接3W功放(LM4871)
    • MicroHDMI(1路HDMI 1.4)
    -
  • 摄像头
    • 传感器IMX335
    • 镜头M12,焦距4mm,光圈1.8
    -
  • 显示屏
    • LCD连接器(2.35寸)
    • LCD连接器(5.5寸)
    -
  • 外部器件及接口
    • SD卡接口
    • JTAG/I2S 接口
    • ADC接口
    • 舵机接口
    • Grove连接器
    • USB2.0(Type C)
    • 功能按键3个,2个用户自定义按键,1个升级按键
    • LED指示灯,绿灯,红灯
    -
-
- diff --git "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" "b/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" deleted file mode 100644 index 3f827074bfd5e4c7c19251d467dece8dedeb4fe2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-2.md" +++ /dev/null @@ -1,122 +0,0 @@ -# 安装开发板环境 - -- [Hi3516工具要求](#section179175261196) - - [硬件要求](#section5840424125014) - - [软件要求](#section965634210501) - -- [安装Linux服务器工具](#section182916865219) - - [将Linux shell改为bash](#section1715027152617) - - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) - - [安装文件打包工具及Java虚拟机环境](#section16199102083717) - - -## Hi3516工具要求 - -### 硬件要求 - -- Hi3516DV300 IoT Camera开发板 -- USB转串口线、网线(Windows工作台通过USB转串口线、网线与Hi3516DV300 开发板连接) - -各硬件连接关系如下图所示。 - -**图 1** 硬件连线图 - - -![](figures/矩形备份-292.png) - -### 软件要求 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section182916865219)章节。 - -Hi3516开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 - -**表 1** Linux服务器开发工具及获取途径 - - - - - - - - - - - - - - - - - - - - - - - - -

开发工具

-

用途

-

获取途径

-

bash

-

命令行处理工具

-

系统配置

-

编译基础软件包(仅ubuntu 20+需要)

-

编译依赖的基础软件包

-

通过互联网获取

-

dosfstools、mtools、mtd-utils

-

文件打包工具

-

通过apt-get install安装

-

Java 虚拟机环境

-

编译、调试和运行Java程序

-

通过apt-get install安装

-
- -## 安装Linux服务器工具 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装LLVM、hc-gen编译工具。 ->- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 - -### 将Linux shell改为bash - -查看shell是否为bash,在终端运行如下命令 - -``` -ls -l /bin/sh -``` - -如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: - -**方法一**:在终端运行如下命令,然后选择 no。 - -``` -sudo dpkg-reconfigure dash -``` - -**方法二**:先删除sh,再创建软链接。 - -``` -sudo rm -rf /bin/sh -sudo ln -s /bin/bash /bin/sh -``` - -### 安装编译依赖基础软件(仅Ubuntu 20+需要) - -执行以下命令进行安装: - -``` -sudo apt-get install build-essential gcc g++ make zlib* libffi-dev -``` - -### 安装文件打包工具及Java虚拟机环境 - -1. 打开Linux编译服务器终端 -2. 运行如下命令,安装dosfstools,mtools,mtd-utils,Java运行时环境(JRE)和Java sdk 开发工具包。 - - ``` - sudo apt-get install dosfstools mtools mtd-utils default-jre default-jdk - ``` - - diff --git "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" "b/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" deleted file mode 100644 index b2bbd778809bfdb9aa3ac3e5104e070cce42eae4..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203-4.md" +++ /dev/null @@ -1,114 +0,0 @@ -# 安装开发板环境 - -- [Hi3518环境搭建](#section1724111409282) - - [硬件要求](#section487353718276) - - [软件要求](#section17315193935817) - -- [安装Linux服务器工具](#section8831868501) - - [将Linux shell改为bash](#section434110241084) - - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section25911132141020) - - [安装文件打包工具](#section390214473129) - - -## Hi3518环境搭建 - -### 硬件要求 - -- Hi3518EV300 IoT Camera开发板 -- USB转串口线、网线(Windows工作台通过USB转串口线、网线与开发板连接) - - 各硬件连接关系如下图所示。 - - -**图 1** 硬件连线图 -![](figures/硬件连线图-3.png "硬件连线图-3") - -### 软件要求 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本节描述安装包方式搭建编译环境的操作步骤。如果是Docker方式安装编译环境,请跳过此章节以及下述[安装Linux服务器工具](#section8831868501)章节。 - -Hi3518开发板对Linux服务器通用环境配置需要的工具及其获取途径如下表所示。 - -**表 1** Linux服务器开发工具及获取途径 - - - - - - - - - - - - - - - - - - - - -

开发工具

-

用途

-

获取途径

-

bash

-

命令行处理工具

-

系统配置

-

编译基础软件包(仅ubuntu 20+需要)

-

编译依赖的基础软件包

-

通过互联网获取

-

dosfstools、mtools、mtd-utils

-

文件打包工具

-

通过apt-get install安装

-
- -## 安装Linux服务器工具 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装hc-gen编译工具。 ->- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装hc-gen编译工具。安装hc-gen编译工具时,请确保编译工具的环境变量路径唯一。 - -### 将Linux shell改为bash - -查看shell是否为bash,在终端运行如下命令 - -``` -ls -l /bin/sh -``` - -如果显示为“/bin/sh -\> bash”则为正常,否则请按以下方式修改: - -**方法一**:在终端运行如下命令,然后选择 no。 - -``` -sudo dpkg-reconfigure dash -``` - -**方法二**:先删除sh,再创建软链接。 - -``` -sudo rm -rf /bin/sh -sudo ln -s /bin/bash /bin/sh -``` - -### 安装编译依赖基础软件(仅Ubuntu 20+需要) - -执行以下命令进行安装: - -``` -sudo apt-get install build-essential gcc g++ make zlib* libffi-dev -``` - -### 安装文件打包工具 - -1. 打开Linux编译服务器终端。 -2. 运行如下命令,安装dosfstools,mtools,mtd-utils。 - - ``` - sudo apt-get install dosfstools mtools mtd-utils - ``` - - diff --git "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" "b/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" deleted file mode 100644 index 2bf84d7aab300883ba5e0b44f2c0acb5ad043917..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\256\211\350\243\205\345\274\200\345\217\221\346\235\277\347\216\257\345\242\203.md" +++ /dev/null @@ -1,367 +0,0 @@ -# 安装开发板环境 - -- [Hi3861工具要求](#section466851916410) - - [硬件要求](#section19202111020215) - - [软件要求](#section727451210318) - -- [安装Linux编译工具](#section497484245614) - - [安装编译依赖基础软件(仅Ubuntu 20+需要)](#section45512412251) - - [安装Scons](#section7438245172514) - - [安装python模块](#section88701892341) - - [安装gcc\_riscv32(WLAN模组类编译工具链)](#section34435451256) - -- [安装USB转串口驱动](#section1027732411513) - -## Hi3861工具要求 - -### 硬件要求 - -- Linux服务器 -- Windows工作台(主机电脑) -- Hi3861 WLAN模组 -- USB Type-C线(Windows工作台通过USB与Hi3861 WLAN模组连接) - -各硬件连接关系如下图所示。 - -**图 1** 硬件连线图 -![](figures/硬件连线图.png "硬件连线图") - -### 软件要求 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->本节描述采用安装包方式安装相关工具的操作步骤。如果是Docker方式安装,无需安装[表1](#table6299192712513)中的Linux服务器相关工具,只需安装Windows工作台工具即可。 - -Hi3861开发板需要的工具如下表所示。 - -**表 1** Hi3861开发板需要的工具 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

平台类型

-

开发工具

-

用途

-

获取途径

-

Linux服务器

-

编译基础软件包(仅ubuntu 20+需要)

-

编译依赖的基础软件包

-

通过互联网获取

-

Linux服务器

-

SCons3.0.4+

-

编译构建工具

-

通过互联网获取

-

Linux服务器

-

python模块:setuptools、kconfiglib、pycryptodome、six、ecdsa

-

编译构建工具

-

通过互联网获取

-

Linux服务器

-

gcc riscv32

-

编译构建工具

-

通过互联网获取

-

Windows工作台

-

CH341SER.EXE

-

USB转串口驱动

-

http://www.wch.cn/search?q=ch340g&t=downloads

-
- -## 安装Linux编译工具 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- 如果通过“HPM组件方式”或“HPM包管理器命令行工具方式”获取源码,不需要安装gcc\_riscv32编译工具。 ->- (推荐)如果通过“镜像站点方式”或“代码仓库方式”获取源码,需要安装gcc\_riscv32编译工具。安装gcc\_riscv32编译工具时,请确保编译工具的环境变量路径唯一。 - -### 安装编译依赖基础软件(仅Ubuntu 20+需要) - -执行以下命令进行安装: - -``` -sudo apt-get install build-essential gcc g++ make zlib* libffi-dev -``` - -### 安装Scons - -1. 打开Linux编译服务器终端。 -2. 运行如下命令,安装SCons安装包。 - - ``` - python3 -m pip install scons - ``` - -3. 运行如下命令,查看是否安装成功。如果安装成功,查询结果下图所示。 - - ``` - scons -v - ``` - - **图 2** SCons安装成功界面,版本要求3.0.4以上 - ![](figures/SCons安装成功界面-版本要求3-0-4以上.png "SCons安装成功界面-版本要求3-0-4以上") - - -### 安装python模块 - -1. 运行如下命令,安装python模块setuptools。 - - ``` - pip3 install setuptools - ``` - -2. 安装GUI menuconfig工具(Kconfiglib),建议安装Kconfiglib 13.2.0+版本,任选如下一种方式。 - - **命令行方式:** - - ``` - sudo pip3 install kconfiglib - ``` - - - - **安装包方式:** - 1. 下载.whl文件(例如:kconfiglib-13.2.0-py2.py3-none-any.whl)。 - - 下载路径:“[https://pypi.org/project/kconfiglib\#files](https://pypi.org/project/kconfiglib#files)” - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install kconfiglib-13.2.0-py2.py3-none-any.whl - ``` - - - -3. 安装pycryptodome,任选如下一种方式。 - - 安装升级文件签名依赖的Python组件包,包括:pycryptodome、six、ecdsa。安装ecdsa依赖six,请先安装six,再安装ecdsa。 - - - **命令行方式:** - - ``` - sudo pip3 install pycryptodome - ``` - - - **安装包方式:** - 1. 下载.whl文件(例如:pycryptodome-3.9.9-cp38-cp38-manylinux1\_x86\_64.whl)。 - - 下载路径:“[https://pypi.org/project/pycryptodome/\#files](https://pypi.org/project/pycryptodome/#files)”。 - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install pycryptodome-3.9.9-cp38-cp38-manylinux1_x86_64.whl - ``` - - - -4. 安装six,任选如下一种方式。 - - **命令行方式:** - - ``` - sudo pip3 install six --upgrade --ignore-installed six - ``` - - - - **安装包方式:** - 1. 下载.whl文件(例如:six-1.12.0-py2.py3-none-any.whl)。 - - 下载路径:“[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files)” - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install six-1.12.0-py2.py3-none-any.whl - ``` - - - -5. 安装ecdsa,任选如下一种方式。 - - **命令行方式:** - - ``` - sudo pip3 install ecdsa - ``` - - - **安装包方式:** - 1. 下载.whl文件(例如:ecdsa-0.14.1-py2.py3-none-any.whl)。 - - 下载路径:“[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files)” - - - 1. 运行如下命令,安装.whl文件。 - - ``` - sudo pip3 install ecdsa-0.14.1-py2.py3-none-any.whl - ``` - - - - -### 安装gcc\_riscv32(WLAN模组类编译工具链) - ->![](public_sys-resources/icon-notice.gif) **须知:** ->- Hi3861平台仅支持使用libgcc运行时库的静态链接,不建议开发者使用libgcc运行时库的动态链接,会导致商业分发时被GPL V3污染。 ->- 通过下述步骤2-15,我们编译好了gcc\_riscv32 镜像,提供给开发者[直接下载](https://repo.huaweicloud.com/harmonyos/compiler/gcc_riscv32/7.3.0/linux/gcc_riscv32-linux-7.3.0.tar.gz)使用。直接下载 gcc\_riscv32 镜像的开发者可省略下述2-15步。 - -1. 打开Linux编译服务器终端。 -2. 环境准备,请安装"gcc, g++, bison, flex, makeinfo"软件,确保工具链能正确编译。 - - ``` - sudo apt-get install gcc && sudo apt-get install g++ && sudo apt-get install flex bison && sudo apt-get install texinfo - ``` - -3. 下载riscv-gnu-toolchain交叉编译工具链。 - - ``` - git clone --recursive https://gitee.com/mirrors/riscv-gnu-toolchain.git - ``` - -4. 打开文件夹riscv-gnu-toolchain,先删除空文件夹,以防止下载newlib,binutils,gcc时冲突。 - - ``` - cd riscv-gnu-toolchain && rm -rf riscv-newlib && rm -rf riscv-binutils && rm -rf riscv-gcc - ``` - -5. 下载riscv-newlib-3.0.0。 - - ``` - git clone -b riscv-newlib-3.0.0 https://github.com/riscv/riscv-newlib.git - ``` - -6. 下载riscv-binutils-2.31.1。 - - ``` - git clone -b riscv-binutils-2.31.1 https://github.com/riscv/riscv-binutils-gdb.git - ``` - -7. 下载riscv-gcc-7.3.0。 - - ``` - git clone -b riscv-gcc-7.3.0 https://github.com/riscv/riscv-gcc - ``` - -8. 添加riscv-gcc-7.3.0补丁。 - - 访问gcc官方补丁链接[89411](https://gcc.gnu.org/git/?p=gcc.git;a=commitdiff;h=026216a753ef0a757a9e368a59fa667ea422cf09;hp=2a23a1c39fb33df0277abd4486a3da64ae5e62c2),[86724](https://gcc.gnu.org/git/?p=gcc.git;a=blobdiff;f=gcc/graphite.h;h=be0a22b38942850d88feb159603bb846a8607539;hp=4e0e58c60ab83f1b8acf576e83330466775fac17;hb=b1761565882ed6a171136c2c89e597bc4dd5b6bf;hpb=fbd5f023a03f9f60c6ae36133703af5a711842a3),按照补丁链接中要求的修改,手动将变更添加到对应的.c和.h文件中,注意由于patch版本与下载的gcc版本有所偏差,行数有可能对应不上,请自行查找patch中的关键字定位到对应行。 - -9. 下载[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 - ``` - -10. 下载[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 - ``` - -11. 下载[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 - ``` - -12. 打开文件夹riscv-gnu-toolchain,新建工具链输出目录。 - - ``` - cd /opt && mkdir gcc_riscv32 - ``` - -13. 编译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 .. - ``` - -14. 编译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 .. - ``` - -15. 编译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 - ``` - -16. 设置环境变量。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果直接采用编译好的riscv32 gcc包,请参照如下步骤设置环境变量: - >1. 将压缩包解压到根目录 - > ``` - > tar -xvf gcc_riscv32-linux-7.3.0.tar.gz -C ~ - > ``` - >2. 设置环境变量。 - > ``` - > vim ~/.bashrc - > ``` - >3. 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - > ``` - > export PATH=~/gcc_riscv32/bin:$PATH - > ``` - - ``` - vim ~/.bashrc - ``` - - 将以下命令拷贝到.bashrc文件的最后一行,保存并退出。 - - ``` - export PATH=~/gcc_riscv32/bin:$PATH - ``` - -17. 生效环境变量。 - - ``` - source ~/.bashrc - ``` - -18. Shell命令行中输入如下命令,如果能正确显示编译器版本号,表明编译器安装成功。 - - ``` - riscv32-unknown-elf-gcc -v - ``` - - -## 安装USB转串口驱动 - -相关步骤在Windows工作台操作。 - -1. 点击链接[下载CH341SER USB转串口](http://www.hihope.org/download/download.aspx?mtt=8)驱动程序。 -2. 点击安装包,安装驱动程序。 -3. 驱动安装完成后,重新插拔USB接口,串口信息显示如下图所示。 - - ![](figures/zh-cn_image_0000001174350633.png) - - diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" "b/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" deleted file mode 100644 index f8e0b7384e225685a08fa51e0cf97264bfe3851e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-1.md" +++ /dev/null @@ -1,292 +0,0 @@ -# 常见问题 - -- [安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH”](#section1221016541119) -- [安装python3过程中,提示“-bash: make: command not found”](#section1913477181213) -- [安装python3过程中,提示“zlib not available”](#section108211415131210) -- [安装python3过程中,提示“No module named '\_ctypes'”](#section2062268124) -- [编译构建过程中,提示“No module named 'Crypto'”](#section982315398121) -- [编译构建过程中,提示“No module named 'ecdsa'”](#section102035451216) -- [编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0”](#section4498158162320) -- [编译构建过程中,提示找不到“-lgcc”](#section11181036112615) -- [编译构建过程中,提示找不到“python”](#section1571810194619) -- [安装 kconfiglib时,遇到lsb\_release错误](#section691681635814) - -## 安装python3过程中,提示“configure: error: no acceptable C compiler found in $PATH” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - configure: error: no acceptable C compiler found in $PATH. See 'config.log' for more details - ``` - -- **可能原因** - - 环境中未安装“gcc”。 - -- **解决办法** - - 1、通过命令“apt-get install gcc”在线安装。 - - 2、完成后,重新安装python3。 - - -## 安装python3过程中,提示“-bash: make: command not found” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - -bash: make: command not found - ``` - -- **可能原因** - - 环境中未安装“make”。 - -- **解决办法** - - 1、通过命令“apt-get install make”在线安装。 - - 2、完成后,重新安装python3。 - - -## 安装python3过程中,提示“zlib not available” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - zipimport.ZipImportError: can't decompress data; zlib not avaliable - ``` - -- **可能原因** - - 环境中未安装“zlib”。 - -- **解决办法** - - 方法1:通过命令“apt-get install zlib”在线安装。 - - 方法2:如果软件源中没有该软件,请从“www.zlib.net”下载版本代码,并离线安装。 - - ![](figures/10.png) - - 完成下载后,通过以下命令安装: - - ``` - # tar xvf zlib-1.2.11.tar.gz - # cd zlib-1.2.11 - # ./configure - # make && make install - ``` - - 完成后,重新安装python3。 - - -## 安装python3过程中,提示“No module named '\_ctypes'” - -- **现象描述** - - 安装python3过程中出现以下错误: - - ``` - ModuleNotFoundError:No module named ‘_ctypes’ - ``` - - -- **可能原因** - - 环境中未安装“libffi”和“libffi-devel”。 - - -- **解决办法** - - 1、通过命令“apt-get install libffi\* -y”,在线安装。 - - 2、完成后,重新安装python3。 - - -## 编译构建过程中,提示“No module named 'Crypto'” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - ModuleNotFoundError: No module named 'Crypto' - ``` - - -- **可能原因** - - 环境中未安装“Crypto”。 - - -- **解决办法** - - 方法1:通过命令“pip3 install Crypto”,在线安装。 - - 方法2:离线安装 - - 通过网页[https://pypi.org/project/pycrypto/\#files](https://pypi.org/project/pycrypto/#files),下载源码。 - - ![](figures/zh-cn_image_0000001128470864.png) - - 将源码放置在Linux服务器中,解压,并安装“python3 setup.py install”。 - - 完成上述安装后,重新构建。 - - -## 编译构建过程中,提示“No module named 'ecdsa'” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - ModuleNotFoundError:No module named 'ecdsa' - ``` - - -- **可能原因** - - 环境中未安装“ecdsa”。 - - -- **解决办法** - - 方法1:通过命令“pip3 install ecdsa”,在线安装。 - - 方法2:离线安装 - - 通过网页[https://pypi.org/project/ecdsa/\#files](https://pypi.org/project/ecdsa/#files),下载安装包。 - - ![](figures/zh-cn_image_0000001128311072.png) - - 将安装包放置Linux服务器中,并安装“pip3 install ecdsa-0.15-py2.py3-none-any.whl”。 - - 完成上述安装后,重新构建。 - - -## 编译构建过程中,提示“Could not find a version that satisfies the requirement six\>=1.9.0” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - Could not find a version that satisfies the requirement six>=1.9.0 - ``` - - -- **可能原因** - - 环境中未安装合适的“six”。 - - -- **解决办法** - - 方法1:通过命令“pip3 install six”,在线安装。 - - 方法2:离线安装 - - 通过网页[https://pypi.org/project/six/\#files](https://pypi.org/project/six/#files),下载安装包。 - - ![](figures/zh-cn_image_0000001174270699.png) - - 将源码放置在Linux服务器中,并安装“pip3 install six-1.14.0-py2.py3-none-any.whl”。 - - 完成上述安装后,重新构建。 - - -## 编译构建过程中,提示找不到“-lgcc” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - riscv32-unknown-elf-ld: cannot find -lgcc - ``` - - -- **可能原因** - - 交叉编译器gcc\_riscv32的PATH添加错误,如下,在"bin"后多添加了一个“/”,应该删除。 - - ``` - ~/gcc_riscv32/bin/:/data/toolchain/ - ``` - - -- **解决办法** - - 重新修改gcc\_riscv32的PATH,将多余的“/”删除。 - - ``` - ~/gcc_riscv32/bin:/data/toolchain/ - ``` - - -## 编译构建过程中,提示找不到“python” - -- **现象描述** - - 编译构建过程中出现以下错误: - - ``` - -bash: /usr/bin/python: No such file or directory - ``` - - -- **可能原因**1 - - 没有装python。 - -- **解决办法** - - 请按照 [安装Python环境](../quick-start/Ubuntu编译环境准备.md) - -- **可能原因2** - - ![](figures/zh-cn_image_0000001128311070.png) - -- **解决办法** - - usr/bin目录下没有python软链接,请运行以下命令添加软链接: - - ``` - # cd /usr/bin/ - # which python3 - # ln -s /usr/local/bin/python3 python - # python --version - ``` - - 例: - - ![](figures/zh-cn_image_0000001174350623.png) - - -## 安装 kconfiglib时,遇到lsb\_release错误 - -- **现象描述** - - 安装kconfiglib过程中遇到如下错误打印: - - ``` - subprocess.CalledProcessError: Command '('lsb_release', '-a')' returned non-zero exit status 1. - ``` - -- **可能原因** - - lsb\_release模块基于的python版本与现有python版本不一致 - -- **解决办法** - - 执行"find / -name lsb\_release",找到lsb\_release位置并删除,如:"sudo rm -rf /usr/bin/lsb\_release" - - diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" "b/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" deleted file mode 100644 index ece72f03517ecd60ca587fcba3c3fab1a5974a47..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-3.md" +++ /dev/null @@ -1,175 +0,0 @@ -# 常见问题 - -- [烧写选择串口后提示失败](#section627268185113) -- [Windows电脑与单板网络连接失败](#section195391036568) -- [烧写失败](#section571164016565) -- [编译构建过程中,提示找不到“python”](#section1039835245619) -- [串口无回显](#section14871149155911) - -## 烧写选择串口后提示失败 - -- **现象描述** - - 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 - - **图 1** 打开串口失败图 - ![](figures/打开串口失败图.png "打开串口失败图") - -- **可能原因** - - 串口已经被占用。 - -- **解决办法** - -1. 按图依次选择下拉框,查找带有serial-xx的终端 - - **图 2** 查找是否存在占用串口的终端 - ![](figures/查找是否存在占用串口的终端.png "查找是否存在占用串口的终端") - -2. 点击标号中的垃圾桶图标,关闭串口。 - - **图 3** 关闭串口终端 - ![](figures/关闭串口终端.png "关闭串口终端") - -3. 重新点击烧写,选择串口并开始烧写程序 - - **图 4** 重新启动烧写任务 - - - ![](figures/changjian1.png) - - -## Windows电脑与单板网络连接失败 - -- **现象描述** - - 点击烧写并选择串口后,无法获取文件。 - - **图 5** 网络不通,单板无法获取文件图 - ![](figures/网络不通-单板无法获取文件图.png "网络不通-单板无法获取文件图") - -- **可能原因** - - 单板网络与Windows电脑不联通。 - - Windows电脑防火墙未允许Visual Studio Code联网。 - -- **解决方法** - -1. 检查网线是否连接。 -2. 点击Windows防火墙。 - - **图 6** 网络防火墙设置图 - ![](figures/网络防火墙设置图.png "网络防火墙设置图") - -3. 点击“允许应用通过防火墙”。 - - **图 7** 防火墙和网络保护界面图 - ![](figures/防火墙和网络保护界面图.png "防火墙和网络保护界面图") - -4. 查找Visual Studio Code应用。 - - **图 8** 查找Visual Studio Code应用图 - ![](figures/查找Visual-Studio-Code应用图.png "查找Visual-Studio-Code应用图") - -5. 勾选Visual Studio Code的专用和公用网络的访问权限。 - - **图 9** 允许Visual Studio Code应用访问网络 - ![](figures/允许Visual-Studio-Code应用访问网络.png "允许Visual-Studio-Code应用访问网络") - - -## 烧写失败 - -- **现象描述** - - 点击烧写并选择串口后,出现无法烧写的情况。 - -- **可能原因** - - 安装IDE插件DevEco后未重启。 - -- **解决方法** - - 重启IDE。 - - -## 编译构建过程中,提示找不到“python” - -- **现象描述** - - ![](figures/zh-cn_image_0000001174270715.png) - - -- **可能原因1** - - 没有装python。 - -- **解决办法** - - 请按照[安装python](../quick-start/Ubuntu编译环境准备.md)。 - -- **可能原因2** - - ![](figures/zh-cn_image_0000001128470880.png) - -- **解决办法** - - usr/bin目录下没有python软链接,请运行以下命令: - - ``` - # cd /usr/bin/ - # which python3 - # ln -s /usr/local/bin/python3 python - # python --version - ``` - - 例: - - ![](figures/zh-cn_image_0000001174270713.png) - - -## 串口无回显 - -- **现象描述** - - 串口显示已连接,重启单板后,回车无任何回显。 - -- **可能原因1** - - 串口连接错误。 - -- **解决办法** - - 修改串口号。 - - 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](../quick-start/运行Hello-OHOS.md)修改串口号。 - - -- **可能原因2** - - 单板U-boot被损坏。 - -- **解决办法** - - 烧写U-boot。 - - 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 - - -1. 获取引导文件U-boot。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >单板的U-boot文件请在开源包中获取: - >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin - >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin - -2. 根据USB烧写步骤烧写U-boot文件。 - - 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 - -3. 烧写完成后,登录串口如下图所示。 - - **图 10** U-boot烧写完成串口显示图 - ![](figures/U-boot烧写完成串口显示图.png "U-boot烧写完成串口显示图") - - diff --git "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" "b/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" deleted file mode 100644 index b2dc3ad51268d608a8767e7eaf9256fbc9adfe11..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\270\270\350\247\201\351\227\256\351\242\230-6.md" +++ /dev/null @@ -1,174 +0,0 @@ -# 常见问题 - -- [烧写选择串口后提示失败](#section1498892119619) -- [Windows电脑与单板网络连接失败](#section8512971816) -- [烧写失败](#section1767804111198) -- [编译构建过程中,提示找不到“python”](#zh-cn_topic_0000001053466255_section1039835245619) -- [串口无回显](#zh-cn_topic_0000001053466255_section14871149155911) - -## 烧写选择串口后提示失败 - -- **现象描述** - - 点击烧写并选择串口后,出现Error: Opening COMxx: Access denied。 - - **图 1** 打开串口失败图 - ![](figures/打开串口失败图-7.png "打开串口失败图-7") - -- **可能原因** - - 串口已经被占用。 - -- **解决办法** - -1. 按图依次选择下拉框,查找带有serial-xx的终端 - - **图 2** 查找是否存在占用串口的终端 - ![](figures/查找是否存在占用串口的终端-8.png "查找是否存在占用串口的终端-8") - -2. 点击标号中的垃圾桶图标,关闭串口。 - - **图 3** 关闭串口终端 - ![](figures/关闭串口终端-9.png "关闭串口终端-9") - -3. 重新点击烧写,选择串口并开始烧写程序 - - **图 4** 重新启动烧写任务 - - - ![](figures/changjian1-10.png) - - -## Windows电脑与单板网络连接失败 - -- **现象描述** - - 点击烧写并选择串口后,无法获取文件。 - - **图 5** 网络不通,单板无法获取文件图 - ![](figures/网络不通-单板无法获取文件图-11.png "网络不通-单板无法获取文件图-11") - -- **可能原因** - - 单板网络与Windows电脑不联通。 - - Windows电脑防火墙未允许Visual Studio Code联网。 - -- **解决方法** - -1. 检查网线是否连接。 -2. 点击Windows防火墙。 - - **图 6** 网络防火墙设置图 - ![](figures/网络防火墙设置图-12.png "网络防火墙设置图-12") - -3. 点击“允许应用通过防火墙”。 - - **图 7** 防火墙和网络保护界面图 - ![](figures/防火墙和网络保护界面图-13.png "防火墙和网络保护界面图-13") - -4. 查找Visual Studio Code应用。 - - **图 8** 查找Visual Studio Code应用图 - ![](figures/查找Visual-Studio-Code应用图-14.png "查找Visual-Studio-Code应用图-14") - -5. 勾选Visual Studio Code的专用和公用网络的访问权限。 - - **图 9** 允许Visual Studio Code应用访问网络 - ![](figures/允许Visual-Studio-Code应用访问网络-15.png "允许Visual-Studio-Code应用访问网络-15") - - -## 烧写失败 - -- **现象描述** - - 点击烧写并选择串口后,出现无法烧写的情况。 - -- **可能原因** - - 安装IDE插件DevEco后未重启。 - -- **解决方法** - - 重启IDE。 - - -## 编译构建过程中,提示找不到“python” - -- **现象描述** - - ![](figures/zh-cn_image_0000001174270743.png) - - -- **可能原因1** - - 没有装python。 - -- **解决办法** - - 请按照[安装python](../quick-start/Ubuntu编译环境准备.md)。 - -- **可能原因2** - - ![](figures/zh-cn_image_0000001174270739.png) - -- **解决办法** - - usr/bin目录下没有python软链接,请运行以下命令: - - ``` - # cd /usr/bin/ - # which python3 - # ln -s /usr/local/bin/python3 python - # python --version - ``` - - 例: - - ![](figures/zh-cn_image_0000001174350661.png) - - -## 串口无回显 - -- **现象描述** - - 串口显示已连接,重启单板后,回车无任何回显。 - -- **可能原因1** - - 串口连接错误。 - -- **解决办法** - - 修改串口号。 - - 请查看设备管理器,确认连接单板的串口与终端中连接串口是否一致,若不一致,请按镜像运行内[步骤1](../quick-start/运行Hello-OHOS.md)修改串口号。 - - -- **可能原因2** - - 单板U-boot被损坏。 - -- **解决办法** - - 烧写U-boot。 - - 若上述步骤依旧无法连接串口,可能由于单板U-boot损坏,按下述步骤烧写U-boot。 - - -1. 获取引导文件U-boot。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >单板的U-boot文件请在开源包中获取: - >Hi3516DV300:device\\hisilicon\\hispark\_taurus\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3516dv300.bin - >Hi3518EV300:device\\hisilicon\\hispark\_aries\\sdk\_liteos\\uboot\\out\\boot\\u-boot-hi3518ev300.bin - -2. 根据USB烧写步骤烧写U-boot文件。 - - 按照[Hi3516系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)/[Hi3518系列USB烧写步骤](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3518_upload-0000001057313128)中描述的USB烧写方法,选择对应单板的U-boot文件进行烧写。 - -3. 烧写完成后,登录串口如下图所示。 - - ![](figures/zh-cn_image_0000001174350659.png) - - diff --git "a/zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" "b/zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" deleted file mode 100644 index 70e795860fbfacc0dc0c4d9c38c453e7a5a99519..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\345\274\200\345\217\221\346\255\245\351\252\244.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 开发步骤 - -- **[Hi3861开发板](Hi3861开发板.md)** - -- **[Hi3516开发板](Hi3516开发板.md)** - -- **[Hi3518开发板](Hi3518开发板.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" "b/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" deleted file mode 100644 index 2f4c97aa4a72f1a42454c7662ccfc17eab7e17d4..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210Docker\346\226\271\345\274\217\357\274\211.md" +++ /dev/null @@ -1,118 +0,0 @@ -# 搭建Ubuntu环境及编译(Docker方式) - -- [获取标准系统源码](#section8761819202511) - - [前提条件](#section102871547153314) - - [操作步骤](#section429012478331) - -- [获取Docker环境](#section181431248132513) -- [编译](#section92391739152318) - -OpenHarmony标准系统为开发者提供的Docker环境已经将对应的编译工具链进行了封装,开发者可省略对应工具的安装。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->- 在使用Docker前需要先安装Docker,Docker安装请参考[官方指导](https://docs.docker.com/engine/install/ubuntu/)。 ->- Docker方式和安装包方式二选一即可。选择Docker方式的开发者可跳过[安装包方式](搭建Ubuntu环境及编译(安装包方式).md)的内容。 - -## 获取标准系统源码 - -### 前提条件 - -1. 注册码云gitee账号。 -2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 - - ``` - git config --global user.name "yourname" - git config --global user.email "your-email-address" - git config --global credential.helper store - ``` - -4. 安装码云repo工具,可以执行如下命令。 - - ``` - curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 - chmod a+x /usr/local/bin/repo - pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests - ``` - - -### 操作步骤 - -方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 - -``` -repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -方式二:通过repo + https 下载。 - -``` -repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -## 获取Docker环境 - -**方式一:从HuaweiCloud SWR上直接获取Docker镜像进行构建:** - -1. 获取Docker镜像。 - - ``` - docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - -2. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker-standard:0.0.1 - ``` - - -**方式二:通过Dockerfile 构建本地Docker镜像进行构建** - -1. 获取Dockerfile脚本文件,用来构建本地Docker镜像。 - - ``` - git clone https://gitee.com/openharmony/docs.git - ``` - -2. 进入Dockerfile代码目录路径执行Docker镜像构建命令。 - - ``` - cd docs/docker/standard - ./build.sh - ``` - -3. 进入OpenHarmony代码根目录执行如下命令,从而进入Docker构建环境。 - - ``` - docker run -it -v $(pwd):/home/openharmony openharmony-docker-standard:0.0.1 - ``` - - -## 编译 - -1. 在源码的根目录执行预处理脚本。 - - ``` - ../scripts/prepare.sh - ``` - -2. 通过如下编译脚本启动标准系统类设备(参考内存≥128MB)的编译。 - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - -3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](镜像烧录.md)。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->退出Docker执行exit命令即可。 - diff --git "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" "b/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" deleted file mode 100644 index 92eb461fe7ace1d62022113eabdd655b4d1f6788..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272Ubuntu\347\216\257\345\242\203\345\217\212\347\274\226\350\257\221\357\274\210\345\256\211\350\243\205\345\214\205\346\226\271\345\274\217\357\274\211.md" +++ /dev/null @@ -1,98 +0,0 @@ -# 搭建Ubuntu环境及编译(安装包方式) - -- [安装依赖工具](#section18431165519244) -- [获取标准系统源码](#section113751052102517) - - [前提条件](#section102871547153314) - - [操作步骤](#section429012478331) - -- [执行prebuilts](#section0495320152619) -- [编译](#section1664835963517) - -## 安装依赖工具 - -安装命令如下: - -``` -sudo apt-get update && sudo apt-get install binutils git git-lfs gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 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 -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->以上安装命令适用于Ubuntu18.04,其他版本请根据安装包名称采用对应的安装命令。 - -## 获取标准系统源码 - -### 前提条件 - -1. 注册码云gitee账号。 -2. 注册码云SSH公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191)。 -3. 安装[git客户端](http://git-scm.com/book/zh/v2/%E8%B5%B7%E6%AD%A5-%E5%AE%89%E8%A3%85-Git)和[git-lfs](https://gitee.com/vcs-all-in-one/git-lfs?_from=gitee_search#downloading))并配置用户信息。 - - ``` - git config --global user.name "yourname" - git config --global user.email "your-email-address" - git config --global credential.helper store - ``` - -4. 安装码云repo工具,可以执行如下命令。 - - ``` - curl -s https://gitee.com/oschina/repo/raw/fork_flow/repo-py3 > /usr/local/bin/repo #如果没有权限,可下载至其他目录,并将其配置到环境变量中 - chmod a+x /usr/local/bin/repo - pip3 install -i https://repo.huaweicloud.com/repository/pypi/simple requests - ``` - - -### 操作步骤 - -方式一(推荐):通过repo + ssh 下载(需注册公钥,请参考[码云帮助中心](https://gitee.com/help/articles/4191))。 - -``` -repo init -u git@gitee.com:openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -方式二:通过repo + https 下载。 - -``` -repo init -u https://gitee.com/openharmony/manifest.git -b master --no-repo-verify -repo sync -c -repo forall -c 'git lfs pull' -``` - -## 执行prebuilts - -在源码根目录下执行脚本,安装编译器及二进制工具。 - -``` -bash build/prebuilts_download.sh -``` - -下载的prebuilts二进制默认存放在与OpenHarmony同目录下的OpenHarmony\_2.0\_canary\_prebuilts下。 - -## 编译 - -在Linux环境进行如下操作: - -1. 进入源码根目录,执行如下命令进行版本编译。 - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台,比如:Hi3516DV300 - -2. 检查编译结果。编译完成后,log中显示如下: - - ``` - build system image successful. - =====build Hi3516DV300 successful. - ``` - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >其他模块化编译操作,可参见[编译构建指导](../subsystems/标准系统编译构建指导.md)。 - -3. 编译源码完成,请进行镜像烧录,具体请参见[镜像烧录](镜像烧录.md)。 - diff --git "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" "b/zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" deleted file mode 100755 index 73a9d50f87e5de08c775137b9864e6f02656872e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\346\220\255\345\273\272\347\263\273\347\273\237\347\216\257\345\242\203.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 搭建系统环境 - -- **[概述](概述-0.md)** - -- **[Windows开发环境准备](Windows开发环境准备.md)** - -- **[Ubuntu编译环境准备](Ubuntu编译环境准备.md)** - -- **[常见问题](常见问题.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" "b/zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" deleted file mode 100755 index 0281a27a47be0f03dcb2595968a0377c5e65f554..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\346\240\207\345\207\206\347\263\273\347\273\237\345\205\245\351\227\250.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 标准系统入门 - -- **[入门介绍](入门介绍.md)** - -- **[Windows开发环境准备](Windows开发环境准备-7.md)** - -- **[搭建Ubuntu环境及编译(Docker方式)](搭建Ubuntu环境及编译(Docker方式).md)** - -- **[搭建Ubuntu环境及编译(安装包方式)](搭建Ubuntu环境及编译(安装包方式).md)** - -- **[镜像烧录](镜像烧录.md)** - -- **[常见问题](常见问题-8.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" "b/zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" deleted file mode 100644 index a5446960eb35cd7ad18fa426da226ea89ac6d2bf..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\345\205\245\351\227\250.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 轻量和小型系统入门 - -- **[概述](概述.md)** - -- **[了解开发板](了解开发板.md)** - -- **[搭建系统环境](搭建系统环境.md)** - -- **[开发步骤](开发步骤.md)** - - diff --git "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" "b/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" deleted file mode 100644 index 51873c97ac3662e15356d6350e6da77ed10fc7c0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS-5.md" +++ /dev/null @@ -1,262 +0,0 @@ -# 运行Hello OHOS - -- [新建应用程序](#section1550972416485) -- [编译](#section234175193114) -- [烧录](#section7609155824819) -- [镜像运行](#section17612105814480) -- [下一步学习](#section9712145420182) - -本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 - -## 新建应用程序 - -1. 新建目录及源码 - - 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 - - ``` - #include - - int main(int argc, char **argv) - { - printf("\n************************************************\n"); - printf("\n\t\tHello OHOS!\n"); - printf("\n************************************************\n\n"); - - return 0; - } - ``` - -2. 新建编译组织文件 - - 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: - - ``` - 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. 添加新组件 - - 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "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. 修改单板配置文件 - - 修改文件**vendor/hisilicon/hispark\_aries/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "subsystem": "applications", - "components": [ - ##start## - { "component": "hello_world_app", "features":[] }, - ##end## - { "component": "camera_sample_app", "features":[] } - - ] - }, - ``` - - -## 编译 - -如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/Docker编译环境.md)的编译操作。如果Linux编译环境通过软件包方式安装,进入源码根目录,执行如下命令进行编译: - -``` -hb set(设置编译路径) -.(选择当前路径) -选择ipcamera_hispark_aries@hisilicon并回车 -hb build -f(执行编译) -``` - -结果文件生成在out/hispark\_aries/ipcamera\_hispark\_aries目录下。 - -**图 1** 设置图例 -![](figures/设置图例-4.png "设置图例-4") - ->![](public_sys-resources/icon-notice.gif) **须知:** ->Hi3518EV300单板的U-boot文件获取路径:device/hisilicon/hispark\_aries/sdk\_liteos/uboot/out/boot/u-boot-hi3518ev300.bin - -## 烧录 - -Hi3518开发板的代码烧录仅支持USB烧录方式。 - -1. 请连接好电脑和待烧录开发板,以Hi3518EV300为例,需要同时连接串口和USB口,具体可参考[Hi3518开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3518-0000001105201138)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001128470900.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/zh-cn_image_0000001174350649.png) - -4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3518系列开发板进行适配,无需单独修改。 -5. 在“hi3518ev300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001057313128_li46411811196)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“hiburn-usb”。 - - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 - - ![](figures/zh-cn_image_0000001128311090.png) - -6. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -7. 打开工程文件,点击![](figures/2021-01-27_170334-5.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3518ev300\_fastboot下的**Erase**按钮,擦除U-Boot。 - - ![](figures/zh-cn_image_0000001174270731.png) - -8. 执行**Erase**擦除操作后,显示如下提示信息时,请重启开发板(下电再上电)。 - - ![](figures/zh-cn_image_0000001128311092.png) - -9. 重新上电后,显示如下信息时,表示擦除U-Boot成功。 - - ![](figures/zh-cn_image_0000001128311094.png) - -10. 擦除完成后,点击hi3518ev300下的**Upload**按钮,启动烧录。 - - ![](figures/zh-cn_image_0000001174350641.png) - -11. 启动烧录后,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001174350643.png) - - -## 镜像运行 - -1. 连接串口。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >若无法连接串口,请参考[常见问题](../quick-start/常见问题-6.md)进行排查。 - - **图 2** 连接串口图 - - - ![](figures/chuankou1-6.png) - - 1. 单击**Monitor**打开串口。 - 2. 连续输入回车直到串口显示"hisilicon"。 - 3. 单板初次启动或修改启动参数,请进入[步骤2](#li9441185382314),否则进入[步骤3](#li6442853122312)。 - -2. (初次烧写必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,可保存执行结果,但U-boot重新烧入,则需要再次执行下述步骤。 - - **表 1** U-boot修改命令 - - - - - - - - - - - - - - - - - - - - - - -

执行命令

-

命令解释

-

setenv bootcmd "sf probe 0;sf read 0x40000000 0x100000 0x600000;go 0x40000000";

-

设置bootcmd内容,选择FLASH器件0,读取FLASH起始地址为0x100000,大小为0x600000字节的内容到0x40000000的内存地址,此处0x600000为6MB,与IDE中填写OHOS_Image.bin的文件大小必须相同

-

setenv bootargs "console=ttyAMA0,115200n8 root=flash fstype=jffs2 rw rootaddr=7M rootsize=8M";

-

表示设置bootargs参数为串口输出,波特率为115200,数据位8,rootfs挂载于FLASH上,文件系统类型为jffs2 rw,以支持可读写JFFS2文件系统。“rootaddr=7M rootsize=8M”处对应填入实际rootfs.img的烧写起始位置与长度,与IDE内所填大小必须相同

-

saveenv

-

表示保存当前配置。

-

reset

-

表示复位单板。

-

pri

-

表示查看显示参数。

-
- - >![](public_sys-resources/icon-notice.gif) **须知:** - >**“go 0x40000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 - -3. 若启动时显示**"hisilicon \#**字样,请输入**“reset”**指令,等待系统自启动进入系统,系统启动后,显示**“OHOS”**字样,输入**”./bin/helloworld”**并回车,显示成功结果如下图所示。 - - **图 3** 启动成功并执行应用程序图 - ![](figures/启动成功并执行应用程序图.png "启动成功并执行应用程序图") - - -## 下一步学习 - -恭喜您,已完成Hi3518的快速上手!建议您下一步进入[无屏摄像头产品开发](../guide/摄像头控制.md)的学习 。 - diff --git "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" "b/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" deleted file mode 100755 index d5f775c64f385feec6cdc67c211ee5978397aca7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-OHOS.md" +++ /dev/null @@ -1,269 +0,0 @@ -# 运行Hello OHOS - -- [新建应用程序](#section204672145202) -- [编译](#section1077671315253) -- [烧录](#section1347011412201) -- [镜像运行](#section24721014162010) -- [执行应用程序](#section5276734182615) - -本节指导开发者在单板上运行第一个应用程序,其中包括新建应用程序、编译、烧写、运行等步骤,最终输出“Hello OHOS!”。 - -## 新建应用程序 - -1. 新建目录及源码 - - 新建**applications/sample/camera/apps/src/helloworld.c**目录及文件,代码如下所示,用户可以自定义修改打印内容(例如:修改OHOS为World)。当前应用程序可支持标准C及C++的代码开发。 - - ``` - #include - - int main(int argc, char **argv) - { - printf("\n************************************************\n"); - printf("\n\t\tHello OHOS!\n"); - printf("\n************************************************\n\n"); - - return 0; - } - ``` - -2. 新建编译组织文件 - - 新建**applications/sample/camera/apps/BUILD.gn**文件,内容如下所示: - - ``` - 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. 添加新组件 - - 修改文件**build/lite/components/applications.json**,添加组件hello\_world\_app的配置,如下所示为applications.json文件片段,"\#\#start\#\#"和"\#\#end\#\#"之间为新增配置("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "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. 修改单板配置文件 - - 修改文件**vendor/hisilicon/hispark\_taurus/config.json**,新增hello\_world\_app组件的条目,如下所示代码片段为applications子系统配置,"\#\#start\#\#"和"\#\#end\#\#"之间为新增条目("\#\#start\#\#"和"\#\#end\#\#"仅用来标识位置,添加完配置后删除这两行): - - ``` - { - "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":[] } - ] - }, - ``` - - -## 编译 - -如果Linux编译环境通过Docker方式安装,具体编译过程请参见[Docker方式获取编译环境](../get-code/Docker编译环境.md)的编译操作。如果Linux编译环境通过软件包方式安装,请进入源码根目录,执行如下命令进行编译: - -``` -hb set(设置编译路径) -.(选择当前路径) -选择ipcamera_hispark_taurus@hisilicon并回车 -hb build -f(执行编译) -``` - -**图 1** 设置图例 -![](figures/设置图例.png "设置图例") - -结果文件生成在out/hispark\_taurus/ipcamera\_hispark\_taurus目录下。 - ->![](public_sys-resources/icon-notice.gif) **须知:** ->Hi3516DV300单板的U-boot文件获取路径:device/hisilicon/hispark\_taurus/sdk\_liteos/uboot/out/boot/u-boot-hi3516dv300.bin - -## 烧录 - -Hi3516开发板的代码烧录支持USB烧录、网口烧录和串口烧录三种方式。此处仅以网口烧录为例进行说明。 - -1. 请连接好电脑和待烧录开发板,以Hi3516DV300为例,需要同时连接串口、网口和电源,具体可参考[Hi3516开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3516-0000001152041033)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3516/Hi3518系列开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001174350647.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/2021-01-27_170334.png) - -4. 在“Partition Configuration”页签,设置待烧录文件信息,默认情况下,DevEco Device Tool已针对Hi3516系列开发板进行适配,无需单独修改。 -5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li142386399535)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 - - upload\_partitions:选择待烧录的文件,默认情况下会同时烧录fastboot、kernel、rootfs和userfs。 - - ![](figures/zh-cn_image_0000001128470904.png) - -6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 -7. 设置网口烧录的IP地址信息,设置如下选项: - - - upload\_net\_server\_ip:选择[6](#zh-cn_topic_0000001056443961_li1558813168234)中设置的IP地址信息。例如192.168.1.2 - - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 - - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 - - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 - - ![](figures/zh-cn_image_0000001174270733.png) - -8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -9. 打开工程文件,点击![](figures/2021-01-27_170334-2.png)图标,打开DevEco Device Tool界面,在“PROJECT TASKS”中,点击hi3516dv300下的**Upload**按钮,启动烧录。 - - ![](figures/zh-cn_image_0000001174270729.png) - -10. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 - - ![](figures/zh-cn_image_0000001128470906.png) - -11. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001128311098.png) - - -## 镜像运行 - -1. 连接串口。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >若无法连接串口,请参考[常见问题](../quick-start/常见问题-3.md)进行排查。 - - **图 2** 连接串口图 - - - ![](figures/chuankou1.png) - - 1. 单击**Monitor**打开串口。 - 2. 连续输入回车直到串口显示"hisilicon"。 - 3. 单板初次启动或修改启动参数,请进入[步骤2](#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](#ld26f18828aa44c36bfa36be150e60e49)。 - -2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 - - **表 1** U-boot修改命令 - - - - - - - - - - - - - - - - - - - -

执行命令

-

命令解释

-

setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

-

读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

-

setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

-

表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

-

“rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

-

saveenv

-

表示保存当前配置。

-

reset

-

表示复位单板。

-
- - >![](public_sys-resources/icon-notice.gif) **须知:** - >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 - -3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 - - **图 3** 系统启动图 - - - ![](figures/qi1.png) - - -## 执行应用程序 - -根目录下,在命令行输入指令“**./bin/helloworld**”执行写入的demo程序,显示成功结果如下图所示。 - -**图 4** 启动并成功执行应用程序图 -![](figures/启动并成功执行应用程序图.png "启动并成功执行应用程序图") - diff --git "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" "b/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" deleted file mode 100755 index f428ec411ee4fc51d1be00be263867d1f8f8dc74..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\350\277\220\350\241\214Hello-World.md" +++ /dev/null @@ -1,158 +0,0 @@ -# 运行Hello World - -- [修改源码](#section79601457101015) -- [调测验证](#section1621064881419) -- [printf打印](#section1246911301217) -- [根据asm文件进行问题定位](#section199621957141014) -- [运行结果](#section18115713118) -- [下一步学习](#section9712145420182) - -本示例将演示如何编写简单业务,输出“Hello World”,初步了解OpenHarmony 如何运行在开发板上。 - -## 修改源码 - -bugfix和新增业务两种情况,涉及源码修改。下面以新增业务(my\_first\_app)为例,向开发者介绍如何进行源码修改。 - -1. 确定目录结构。 - - 开发者编写业务时,务必先在./applications/sample/wifi-iot/app路径下新建一个目录(或一套目录结构),用于存放业务源码文件。 - - 例如:在app下新增业务my\_first\_app,其中hello\_world.c为业务代码,BUILD.gn为编译脚本,具体规划目录结构如下: - - ``` - . - └── applications - └── sample - └── wifi-iot - └── app - │── my_first_app - │ │── hello_world.c - │ └── BUILD.gn - └── BUILD.gn - ``` - -2. 编写业务代码。 - - 新建./applications/sample/wifi-iot/app/my\_first\_app下的hello\_world.c文件,在hello\_world.c中新建业务入口函数HelloWorld,并实现业务逻辑。并在代码最下方,使用OpenHarmony启动恢复模块接口SYS\_RUN\(\)启动业务。(SYS\_RUN定义在ohos\_init.h文件中) - - ``` - #include - #include "ohos_init.h" - #include "ohos_types.h" - - void HelloWorld(void) - { - printf("[DEMO] Hello world.\n"); - } - SYS_RUN(HelloWorld); - ``` - -3. 编写用于将业务构建成静态库的BUILD.gn文件。 - - 新建./applications/sample/wifi-iot/app/my\_first\_app下的BUILD.gn文件,并完成如下配置。 - - 如[步骤1](#li5479332115116)所述,BUILD.gn文件由三部分内容(目标、源文件、头文件路径)构成,需由开发者完成填写。 - - ``` - static_library("myapp") { - sources = [ - "hello_world.c" - ] - include_dirs = [ - "//utils/native/lite/include" - ] - } - ``` - - - static\_library中指定业务模块的编译结果,为静态库文件libmyapp.a,开发者根据实际情况完成填写。 - - sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。 - - include\_dirs中指定source所需要依赖的.h文件路径。 - -4. 编写模块BUILD.gn文件,指定需参与构建的特性模块。 - - 配置./applications/sample/wifi-iot/app/BUILD.gn文件,在features字段中增加索引,使目标模块参与编译。features字段指定业务模块的路径和目标,以my\_first\_app举例,features字段配置如下。 - - ``` - import("//build/lite/config/component/lite_component.gni") - - lite_component("app") { - features = [ - "my_first_app:myapp", - ] - } - ``` - - - my\_first\_app是相对路径,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn。 - - myapp是目标,指向./applications/sample/wifi-iot/app/my\_first\_app/BUILD.gn中的static\_library\("myapp"\)。 - - -## 调测验证 - -目前调试验证的方法有两种,分别为通过printf打印日志、通过asm文件定位panic问题,开发者可以根据具体业务情况选择。 - -由于本示例业务简单,采用printf打印日志的调试方式即可。下面开始介绍这两种调试手段的使用方法。 - -## printf打印 - -代码中增加printf维测,信息会直接打印到串口上。开发者可在业务关键路径或业务异常位置增加日志打印,如下所示。 - -``` -void HelloWorld(void) -{ - printf("[DEMO] Hello world.\n"); -} -``` - -## 根据asm文件进行问题定位 - -系统异常退出时,会在串口上打印异常退出原因调用栈信息,如下文所示。通过解析异常栈信息可以定位异常位置。 - -``` -=======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******************* -``` - -为解析上述调用栈信息,需要使用到Hi3861\_wifiiot\_app.asm文件,该文件记录了代码中函数在Flash上的符号地址以及反汇编信息。asm文件会随版本大包一同构建输出,存放在./out/wifiiot/路径下。 - -1. 将调用栈CallStack信息保存到txt文档中,以便于编辑。(可选) -2. 打开asm文件,并搜索CallStack中的地址,列出对应的函数名 信息。通常只需找出前几个栈信息对应的函数,就可明确异常代码方向。 - - ``` - 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. 根据以上调用栈信息,可以定位WadRecvCB函数中出现了异常。 - - ![](figures/zh-cn_image_0000001174270737.png) - -4. 完成代码排查及修改。 - -## 运行结果 - -示例代码编译、烧录、运行、调测后,在串口界面会显示如下结果: - -``` -ready to OS start -FileSystem mount ok. -wifi init success! -[DEMO] Hello world. -``` - -## 下一步学习 - -恭喜,您已完成Hi3861 WLAN模组快速上手!建议您下一步进入[WLAN产品开发](../guide/概述.md)的学习 。 - diff --git "a/zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" "b/zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" deleted file mode 100644 index 3fca75cfcd0691990f88acac3e1f32ac98528a08..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\351\225\234\345\203\217\347\203\247\345\275\225.md" +++ /dev/null @@ -1,201 +0,0 @@ -# 镜像烧录 - -- [下一步](#section5600113114323) - -标准系统烧录,在V2.2 Beta1及以上版本支持。 - -Hi3516DV300支持烧录标准系统,其烧录方式包括网口烧录和串口烧录三种方式,其中: - -- **Windows系统:支持网口烧录和串口烧录** -- **Linux系统:支持串口烧录和网口烧录。** - -同一种烧录方式(如网口烧录),在Windows和Linux环境下的烧录操作完全一致,区别仅在于DevEco Device Tool环境搭建不同。 - ->![](public_sys-resources/icon-note.gif) **说明:** ->当前Hi3516DV300开发板支持通过网口、USB、串口三种方式烧录OpenHarmony标准系统。本文以网口方式为例讲解烧录操作,其他两种烧录方式请参照[Hi3516DV300烧录指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_upload-0000001052148681)。 - -### 前提条件 - -在DevEco Device Tool中[打开一个工程](https://device.harmonyos.com/cn/docs/ide/user-guides/open_project-0000001071680043),该工程文件夹选择待烧录文件所在文件夹即可。其中开发板类型固定选择Hi3516DV300,Framework选择“Hb”。 - -### 使用网口烧录 - -Hi3516DV300开发板使用网口录方式,支持Windows和Linux系统。 - -1. 请连接好电脑和待烧录开发板,需要同时连接串口、网口和电源,具体可参考[Hi3516DV300开发板介绍](https://device.harmonyos.com/cn/docs/start/introduce/oem_minitinier_des_3516-0000001152041033)。 -2. 打开电脑的设备管理器,查看并记录对应的串口号。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如果对应的串口异常,请根据[Hi3516DV300/Hi3518EV300开发板串口驱动安装指导](https://device.harmonyos.com/cn/docs/ide/user-guides/hi3516_hi3518-drivers-0000001050743695)安装USB转串口的驱动程序。 - - ![](figures/zh-cn_image_0000001114129428.png) - -3. 打开DevEco Device Tool,在Projects中,点击**Settings**打开工程配置界面。 - - ![](figures/2021-01-27_170334-17.png) - -4. 在**Partition Configuration**页签中,按照下表内容填写烧录文件信息,包括: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Name

-

Binary

-

Memory

-

System

-

Address

-

Length

-

Board

-

Type

-

fastboot

-

选择“u-boot-hi3516dv300_emmc.bin”

-

emmc

-

none

-

0x000000

-

0x100000

-

固定选择“hi3516dv300”

-

NA

-

boot

-

选择“uImage”

-

emmc

-

none

-

0x100000

-

0xf00000

-

NA

-

updater

-

选择“updater.img”

-

emmc

-

ext3/4

-

0x1000000

-

0x1400000

-

NA

-

misc

-

空白,不用选择

-

emmc

-

none

-

0x2400000

-

0x100000

-

NA

-

system

-

选择“system.img”

-

emmc

-

ext3/4

-

0x2500000

-

0xceb00000

-

NA

-

vendor

-

选择“vendor.img”

-

emmc

-

ext3/4

-

0xd1000000

-

0x10000000

-

NA

-

userdata

-

选择“userdata.img”

-

emmc

-

ext3/4

-

0xe1000000

-

0x5b800000

-

NA

-
- - ![](figures/zh-cn_image_0000001130584312.png) - -5. 在“hi3516dv300”页签,设置烧录选项,包括upload\_port、upload\_partitions和upload\_protocol。 - - - upload\_port:选择步骤[2](#zh-cn_topic_0000001056443961_li1050616379507)中查询的串口号。 - - upload\_protocol:选择烧录协议,固定选择“hiburn-net”。 - - upload\_partitions:选择待烧录的文件,包括fastboot、boot、updater、misc、system、vendor和userdata。 - - ![](figures/zh-cn_image_0000001117621400.png) - -6. 检查和设置连接开发板后的网络适配器的IP地址信息,设置方法请参考[设置Hi3516DV300网口烧录的IP地址信息](https://device.harmonyos.com/cn/docs/ide/user-guides/set_ipaddress-0000001141825075)。 -7. 设置网口烧录的IP地址信息,设置如下选项: - - - upload\_net\_server\_ip:选择步骤6中设置的IP地址信息。例如192.168.1.2 - - upload\_net\_client\_mask:设置开发板的子网掩码,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如255.255.255.0 - - upload\_net\_client\_gw:设置开发板的网关,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.1 - - upload\_net\_client\_ip:设置开发板的IP地址,工具会自动根据选择的upload\_net\_server\_ip进行设置。例如192.168.1.3 - - ![](figures/zh-cn_image_0000001117463460.png) - -8. 所有的配置都修改完成后,在工程配置页签的顶部,点击**Save**进行保存。 -9. 启动烧录后,显示如下提示信息时,请重启开发板(下电再上电)。 - - ![](figures/zh-cn_image_0000001114129432.png) - -10. 重新上电后,启动烧录,界面提示如下信息时,表示烧录成功。 - - ![](figures/zh-cn_image_0000001113969542.png) - - -## 下一步 - -恭喜!您已经完成了OpenHarmony标准系统的快速入门,接下来可[开发一个小示例](../guide/时钟应用开发示例.md),进一步熟悉OpenHarmony的开发。 - diff --git "a/zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index f9eb065a5d8f0b372e670919a8ed6b89681dbb90..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/quick-start/\351\251\261\345\212\250\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,503 +0,0 @@ -# 驱动开发示例 - -- [驱动程序介绍](#s8efc1952ebfe4d1ea717182e108c29bb) -- [编译和烧写](#section660016185110) -- [镜像运行](#section333215226219) -- [下一步学习](#section9712145420182) - -本节指导开发者在单板上运行第一个驱动程序,其中包括驱动程序介绍、编译、烧写、运行等步骤。 - -## 驱动程序介绍 - -下面基于HDF框架,提供一个简单的UART(Universal Asynchronous Receiver/Transmitter)平台驱动开发样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。驱动程序源码位于vendor/huawei/hdf/sample目录 - -1. 添加配置。 - - 在HDF框架的驱动配置文件(例如device/hisilicon/hi3516dv300/sdk\_liteos/config/uart/uart\_config.hcs)中添加该驱动的配置信息,如下所示: - - ``` - root { - platform { - uart_sample { - num = 5; // UART设备编号 - base = 0x120a0000; // UART 寄存器基地址 - irqNum = 38; - baudrate = 115200; - uartClk = 24000000; - wlen = 0x60; - parity = 0; - stopBit = 0; - match_attr = "sample_uart_5"; - } - } - } - ``` - - 在HDF框架的设备配置文件(例如vendor/hisilicon/ipcamera\_hi3516dv300\_liteos/config/device\_info/device\_info.hcs)中添加该驱动的设备节点信息,如下所示: - - ``` - root { - device_info { - platform :: host { - hostName = "platform_host"; - priority = 50; - device_uart :: device { - device5 :: deviceNode { - policy = 2; - priority = 10; - permission = 0660; - moduleName = "UART_SAMPLE"; - serviceName = "HDF_PLATFORM_UART_5"; - deviceMatchAttr = "sample_uart_5"; - } - } - } - } - } - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >配置文件与UART驱动示例的源码在同一个路径,需要手动添加到Hi3516DV300单板路径下。 - -2. 注册UART驱动入口。 - - 基于HDF框架注册UART驱动的入口HdfDriverEntry,代码如下: - - ``` - // 绑定UART驱动接口到HDF框架 - static int32_t SampleUartDriverBind(struct HdfDeviceObject *device) - { - struct UartHost *uartHost = NULL; - - if (device == NULL) { - return HDF_ERR_INVALID_OBJECT; - } - HDF_LOGI("Enter %s:", __func__); - - uartHost = UartHostCreate(device); - if (uartHost == NULL) { - HDF_LOGE("%s: UartHostCreate failed", __func__); - return HDF_FAILURE; - } - uartHost->service.Dispatch = SampleDispatch; - return HDF_SUCCESS; - } - - // 从UART驱动的HCS中获取配置信息 - static uint32_t GetUartDeviceResource( - struct UartDevice *device, const struct DeviceResourceNode *resourceNode) - { - struct UartResource *resource = &device->resource; - struct DeviceResourceIface *dri = NULL; - dri = DeviceResourceGetIfaceInstance(HDF_CONFIG_SOURCE); - if (dri == NULL || dri->GetUint32 == NULL) { - HDF_LOGE("DeviceResourceIface is invalid"); - return HDF_FAILURE; - } - - if (dri->GetUint32(resourceNode, "num", &resource->num, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read num fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "base", &resource->base, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read base fail"); - return HDF_FAILURE; - } - resource->physBase = (unsigned long)OsalIoRemap(resource->base, 0x48); - if (resource->physBase == 0) { - HDF_LOGE("uart config fail to remap physBase"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "irqNum", &resource->irqNum, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read irqNum fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "baudrate", &resource->baudrate, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read baudrate fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "wlen", &resource->wlen, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read wlen fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "parity", &resource->parity, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read parity fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "stopBit", &resource->stopBit, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read stopBit fail"); - return HDF_FAILURE; - } - if (dri->GetUint32(resourceNode, "uartClk", &resource->uartClk, 0) != HDF_SUCCESS) { - HDF_LOGE("uart config read uartClk fail"); - return HDF_FAILURE; - } - return HDF_SUCCESS; - } - - // 将UART驱动的配置和接口附加到HDF驱动框架 - static int32_t AttachUartDevice(struct UartHost *host, struct HdfDeviceObject *device) - { - int32_t ret; - struct UartDevice *uartDevice = NULL; - if (device->property == NULL) { - HDF_LOGE("%s: property is NULL", __func__); - return HDF_FAILURE; - } - uartDevice = (struct UartDevice *)OsalMemCalloc(sizeof(struct UartDevice)); - if (uartDevice == NULL) { - HDF_LOGE("%s: OsalMemCalloc uartDevice error", __func__); - return HDF_ERR_MALLOC_FAIL; - } - ret = GetUartDeviceResource(uartDevice, device->property); - if (ret != HDF_SUCCESS) { - (void)OsalMemFree(uartDevice); - return HDF_FAILURE; - } - host->num = uartDevice->resource.num; - host->priv = uartDevice; - AddUartDevice(host); - return InitUartDevice(uartDevice); - } - - // 初始化UART驱动 - static int32_t SampleUartDriverInit(struct HdfDeviceObject *device) - { - int32_t ret; - struct UartHost *host = NULL; - - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_OBJECT; - } - HDF_LOGI("Enter %s:", __func__); - host = UartHostFromDevice(device); - if (host == NULL) { - HDF_LOGE("%s: host is NULL", __func__); - return HDF_FAILURE; - } - ret = AttachUartDevice(host, device); - if (ret != HDF_SUCCESS) { - HDF_LOGE("%s: attach error", __func__); - return HDF_FAILURE; - } - host->method = &g_sampleUartHostMethod; - return ret; - } - - static void DeinitUartDevice(struct UartDevice *device) - { - struct UartRegisterMap *regMap = (struct UartRegisterMap *)device->resource.physBase; - /* wait for uart enter idle. */ - while (UartPl011IsBusy(regMap)); - UartPl011ResetRegisters(regMap); - uart_clk_cfg(0, false); - OsalIoUnmap((void *)device->resource.physBase); - device->state = UART_DEVICE_UNINITIALIZED; - } - - // 解绑并释放UART驱动 - static void DetachUartDevice(struct UartHost *host) - { - struct UartDevice *uartDevice = NULL; - - if (host->priv == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return; - } - uartDevice = host->priv; - DeinitUartDevice(uartDevice); - (void)OsalMemFree(uartDevice); - host->priv = NULL; - } - - // 释放UART驱动 - static void SampleUartDriverRelease(struct HdfDeviceObject *device) - { - struct UartHost *host = NULL; - HDF_LOGI("Enter %s:", __func__); - - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return; - } - host = UartHostFromDevice(device); - if (host == NULL) { - HDF_LOGE("%s: host is NULL", __func__); - return; - } - if (host->priv != NULL) { - DetachUartDevice(host); - } - UartHostDestroy(host); - } - - struct HdfDriverEntry g_sampleUartDriverEntry = { - .moduleVersion = 1, - .moduleName = "UART_SAMPLE", - .Bind = SampleUartDriverBind, - .Init = SampleUartDriverInit, - .Release = SampleUartDriverRelease, - }; - - HDF_INIT(g_sampleUartDriverEntry); - ``` - -3. 注册UART驱动接口。 - - HDF框架提供了UART驱动接口的模板方法UartHostMethod,实现UART驱动接口的代码如下: - - ``` - static int32_t SampleUartHostInit(struct UartHost *host) - { - HDF_LOGI("%s: Enter", __func__); - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - return HDF_SUCCESS; - } - - static int32_t SampleUartHostDeinit(struct UartHost *host) - { - HDF_LOGI("%s: Enter", __func__); - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - return HDF_SUCCESS; - } - - // 向UART中写入数据 - static int32_t SampleUartHostWrite(struct UartHost *host, uint8_t *data, uint32_t size) - { - HDF_LOGI("%s: Enter", __func__); - uint32_t idx; - struct UartRegisterMap *regMap = NULL; - struct UartDevice *device = NULL; - - if (host == NULL || data == NULL || size == 0) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - device = (struct UartDevice *)host->priv; - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_PARAM; - } - regMap = (struct UartRegisterMap *)device->resource.physBase; - for (idx = 0; idx < size; idx++) { - UartPl011Write(regMap, data[idx]); - } - return HDF_SUCCESS; - } - - // 设置UART的波特率 - static int32_t SampleUartHostSetBaud(struct UartHost *host, uint32_t baudRate) - { - HDF_LOGI("%s: Enter", __func__); - struct UartDevice *device = NULL; - struct UartRegisterMap *regMap = NULL; - UartPl011Error err; - - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - device = (struct UartDevice *)host->priv; - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_PARAM; - } - regMap = (struct UartRegisterMap *)device->resource.physBase; - if (device->state != UART_DEVICE_INITIALIZED) { - return UART_PL011_ERR_NOT_INIT; - } - if (baudRate == 0) { - return UART_PL011_ERR_INVALID_BAUD; - } - err = UartPl011SetBaudrate(regMap, device->uartClk, baudRate); - if (err == UART_PL011_ERR_NONE) { - device->baudrate = baudRate; - } - return err; - } - - // 获取UART的波特率 - static int32_t SampleUartHostGetBaud(struct UartHost *host, uint32_t *baudRate) - { - HDF_LOGI("%s: Enter", __func__); - struct UartDevice *device = NULL; - - if (host == NULL) { - HDF_LOGE("%s: invalid parameter", __func__); - return HDF_ERR_INVALID_PARAM; - } - device = (struct UartDevice *)host->priv; - if (device == NULL) { - HDF_LOGE("%s: device is NULL", __func__); - return HDF_ERR_INVALID_PARAM; - } - *baudRate = device->baudrate; - return HDF_SUCCESS; - } - - // 在HdfUartSampleInit方法中绑定 - struct UartHostMethod g_sampleUartHostMethod = { - .Init = SampleUartHostInit, - .Deinit = SampleUartHostDeinit, - .Read = NULL, - .Write = SampleUartHostWrite, - .SetBaud = SampleUartHostSetBaud, - .GetBaud = SampleUartHostGetBaud, - .SetAttribute = NULL, - .GetAttribute = NULL, - .SetTransMode = NULL, - }; - ``` - - 在device/hisilicon/drivers/lite.mk编译脚本中增加示例UART驱动模块,代码如下: - - ``` - LITEOS_BASELIB += -lhdf_uart_sample - LIB_SUBDIRS += $(LITEOS_SOURCE_ROOT)/vendor/huawei/hdf/sample/platform/uart - ``` - -4. 用户程序和驱动交互代码。 - - UART驱动成功初始化后,会创建/dev/uartdev-5设备节点,通过设备节点与UART驱动交互的代码如下: - - ``` - #include - #include - #include - #include "hdf_log.h" - - #define HDF_LOG_TAG "hello_uart" - #define INFO_SIZE 16 - - int main(void) - { - int ret; - int fd; - const char info[INFO_SIZE] = {" HELLO UART! "}; - - fd = open("/dev/uartdev-5", O_RDWR); - if (fd < 0) { - HDF_LOGE("hello_uart uartdev-5 open failed %d", fd); - return -1; - } - ret = write(fd, info, INFO_SIZE); - if (ret != 0) { - HDF_LOGE("hello_uart write uartdev-5 ret is %d", ret); - } - ret = close(fd); - if (ret != 0) { - HDF_LOGE("hello_uart uartdev-5 close failed %d", fd); - return -1; - } - return ret; - } - ``` - - 在build/lite/components/drivers.json驱动配置中hdf\_hi3516dv300\_liteos\_a组件下的targets中增加hello\_uart\_sample组件,代码如下: - - ``` - { - "components": [ - { - "component": "hdf_hi3516dv300_liteos_a", - ... - "targets": [ - "//vendor/huawei/hdf/sample/platform/uart:hello_uart_sample" - ] - } - ] - } - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >如上代码均为示例代码,完整代码可以在vendor/huawei/hdf/sample查看。 - >示例代码默认不参与编译,需要手动添加到编译脚本中。 - - -## 编译和烧写 - -参考示例1进行编译和烧写:[编译](../quick-start/驱动开发示例.md)、[烧录](../quick-start/驱动开发示例.md) - -## 镜像运行 - -1. 连接串口。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >若无法连接串口,请参考[常见问题](../quick-start/常见问题-3.md)进行排查。 - - **图 1** 连接串口图 - - - ![](figures/chuankou1.png) - - 1. 单击**Monitor**打开串口。 - 2. 连续输入回车直到串口显示"hisilicon"。 - 3. 单板初次启动或修改启动参数,请进入[步骤2](运行Hello-OHOS.md#l5b42e79a33ea4d35982b78a22913b0b1),否则进入[步骤3](运行Hello-OHOS.md#ld26f18828aa44c36bfa36be150e60e49)。 - -2. (单板初次启动必选)修改U-boot的bootcmd及bootargs内容:该步骤为固化操作,若不修改参数只需执行一次。每次复位单板均会自动进入系统。 - - >![](public_sys-resources/icon-notice.gif) **须知:** - >U-boot引导程序默认会有2秒的等待时间,用户可使用回车打断等待并显示"hisilicon",通过**reset**命令可再次启动系统。 - - **表 1** U-boot修改命令 - - - - - - - - - - - - - - - - - - - -

执行命令

-

命令解释

-

setenv bootcmd "mmc read 0x0 0x80000000 0x800 0x4800; go 0x80000000";

-

读取FLASH起始地址为0x800(单位为512B,即1MB),大小为0x4800(单位为512B,即9MB)的内容到0x80000000的内存地址,该大小(9MB)与IDE中所填写OHOS_Image.bin文件大小必须相同

-

setenv bootargs "console=ttyAMA0,115200n8 root=emmc fstype=vfat rootaddr=10M rootsize=20M rw";

-

表示设置启动参数,输出模式为串口输出,波特率为115200,数据位8,rootfs挂载于emmc器件,文件系统类型为vfat,

-

“rootaddr=10M rootsize=20M rw”处对应填入rootfs.img的烧写起始位置与长度,此处与IDE中新增rootfs.img文件时所填大小必须相同

-

saveenv

-

表示保存当前配置。

-

reset

-

表示复位单板。

-
- - >![](public_sys-resources/icon-notice.gif) **须知:** - >**“go 0x80000000”**为可选指令,默认配置已将该指令固化在启动参数中,单板复位后可自动启动。若想切换为手动启动,可在U-boot启动倒数阶段使用"回车"打断自动启动。 - -3. 输入**“reset”**指令并回车,重启单板,启动成功如下图,输入回车串口显示OHOS字样。 - - **图 2** 系统启动图 - - - ![](figures/qi1.png) - -4. 根目录下,在命令行输入指令“**./bin/hello\_uart**”执行写入的demo程序,显示成功结果如下所示。 - - ``` - OHOS # ./bin/hello_uart - OHOS # HELLO UART! - ``` - - -## 下一步学习 - -恭喜,您已完成Hi3516 快速上手!建议您下一步进入[带屏摄像头产品开发](../guide/屏幕和摄像头控制.md)的学习 。 - diff --git a/zh-cn/device-dev/security/Readme-CN.md b/zh-cn/device-dev/security/Readme-CN.md index 3eb2062d716d8d4d3765ae11edcfd8bb3d8bad27..9a8e221f7fe6561d044900efa29dfec7d0d82af0 100755 --- a/zh-cn/device-dev/security/Readme-CN.md +++ b/zh-cn/device-dev/security/Readme-CN.md @@ -1,5 +1,5 @@ # 隐私与安全 -- [隐私保护](隐私保护.md) -- [安全指南](安全指南.md) +- [隐私保护](safety-protection-privacyguide.md) +- [安全指南](safety-safeguide-security.md) diff --git "a/zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" "b/zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" rename to "zh-cn/device-dev/security/figure/1-\346\225\217\346\204\237\346\235\203\351\231\220\345\274\271\347\252\227.png" diff --git "a/zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" "b/zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" rename to "zh-cn/device-dev/security/figure/2-\345\272\224\347\224\250\345\220\257\345\212\250\351\242\204\346\216\210\346\235\203.png" diff --git "a/zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" "b/zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" rename to "zh-cn/device-dev/security/figure/3-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216.png" diff --git "a/zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" "b/zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" rename to "zh-cn/device-dev/security/figure/4-\351\232\220\347\247\201\345\243\260\346\230\216\345\217\230\346\233\264\351\200\232\347\237\245.png" diff --git "a/zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" "b/zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" rename to "zh-cn/device-dev/security/figure/5-\345\272\224\347\224\250\351\232\220\347\247\201\345\243\260\346\230\216\345\205\245\345\217\243.png" diff --git "a/zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" "b/zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" rename to "zh-cn/device-dev/security/figure/6-1-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" diff --git "a/zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" "b/zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" rename to "zh-cn/device-dev/security/figure/6-2-\351\232\220\347\247\201\345\243\260\346\230\216\346\222\244\351\224\200.png" diff --git "a/zh-cn/device-dev/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/security/figure/DAC\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/DAC\346\265\201\347\250\213\345\233\276.png" rename to "zh-cn/device-dev/security/figure/DAC\346\265\201\347\250\213\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" "b/zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" rename to "zh-cn/device-dev/security/figure/HUKS\345\212\237\350\203\275\347\273\223\346\236\204\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/security/figure/\345\256\211\345\205\250\344\277\235\351\232\234\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" "b/zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/security/figures/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" rename to "zh-cn/device-dev/security/figure/\350\256\276\345\244\207\351\227\264\345\273\272\347\253\213\345\217\257\344\277\241\345\205\263\347\263\273\346\265\201\347\250\213\345\233\276.png" diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/security/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/security/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-note.gif b/zh-cn/device-dev/security/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/security/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/security/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/security/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/security/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/security/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/security/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/security/public_sys-resources/icon-warning.gif and /dev/null differ diff --git a/zh-cn/device-dev/security/safety-protection-privacyguide.md b/zh-cn/device-dev/security/safety-protection-privacyguide.md new file mode 100644 index 0000000000000000000000000000000000000000..95e5eccca8ac113c4ac92f908bb5701109b0e842 --- /dev/null +++ b/zh-cn/device-dev/security/safety-protection-privacyguide.md @@ -0,0 +1,264 @@ +# 隐私保护 + +- [隐私保护概述](#section13200134331414) +- [数据分类分级](#section2371104991511) +- [通用隐私设计规则](#section10354102411162) +- [特殊品类要求](#section118861450201618) + +## 隐私保护概述 + +随着互联网及信息化的发展,个人数据在社会经济和日常生活中发挥着越来越重要的作用。与此同时,个人数据泄露的风险也在增加,消费者产品开发者需要更加有效的保护用户的个人数据,提高用户对产品的信任度。为了提升消费者的隐私体验,产品应默认设置较高级别隐私保护策略,达到保护消费者隐私的目的。 + +**基本概念** + +- **个人数据(Personal Data)** + + 与一个身份已被识别或者身份可被识别的自然人(“数据主体”)相关的任何信息;身份可识别的自然人是指其身份可以通过诸如姓名、身份证号、位置数据等识别码或者通过一个或多个与自然人的身体、生理、精神、经济、文化或者社会身份相关的特定因素来直接或者间接地被识别。个人数据包括:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态等。 + +- **敏感个人数据(Sensitive Personal Data)** + + 敏感个人数据是个人数据的一个重要子集,指的是涉及数据主体的最私密领域的信息或者一旦泄露可能会给数据主体造成重大不利影响的数据。欧盟等国家和地区法律定义的敏感个人数据包括种族、政治观点、宗教和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等。 + + 根据业界最佳实践,敏感个人数据还包括可与自然人身份相关联的银行卡号、身份证号、护照号、口令等。敏感个人数据的处理需要更多更严格的保护措施。 + +- **公开个人数据(Public available Personal Data)** + + 数据主体主动公开的个人数据,或公开网页/应用上可访问的个人数据,包括论坛公开的发帖、评论等。 + +- **用户画像(User Profile)** + + 指对个人数据采取的任何自动化处理的方式,包括评估某个自然人特定方面的情况,尤其是为了分析和预测该自然人的工作表现、经济状况、健康、个人喜好、兴趣、可信度、行为举止、所在位置或行迹。 + +- **数据控制者(Data Controller)** + + 单独或者与他人共同确定个人数据处理的目的和手段的自然人、法人、公共机构、政府部门或其他机构。 + +- **数据处理者(Data Processor)** + + 指代表数据控制者处理个人数据的自然人、法人、公共机构、政府部门或其他机构。数据处理者必须按照数据控制者的要求对个人数据进行充分的保护。 + +- **明示同意(Explicit consent)** + + 如下几种情形GDPR法律提到可以通过数据主体明示同意的方式合法地处理数据: + + - 处理敏感个人数据。 + - 自动化决策,包括进行用户画像。 + - 向不具备充分保护水平的国家转移个人数据,并以同意作为合法性基础。 + + 实现明示同意的方式有: + + - 在收集特定数据时,弹出隐私声明告知个人数据处理相关事项,提供勾选框但不默认勾选,让数据主体勾选“我同意以上述方式处理我的个人数据”,或提供“我同意”的按钮让用户主动点击。 + - 以书面的方式明确表达同意,数据主体在书面陈述上签字。 + - 要求数据主体在系统中上传带有其签名的电子表格。 + - 采取双重验证的方式,要求数据主体邮件形式回复同意后,再次点击用于验证的邮件链接或是输入SMS验证码。 + - 用户主动输入的场景,例如用户主动输入身份证和银行卡号绑卡等场景。 + + +## 数据分类分级 + +基于数据保护目标及风险后果,即数据遭到泄露或者遭到破坏带来的法律风险对个人、组织或公众的影响对数据进行定级,分为极高、高、中、低、公开五个数据级别。 + +**表1** 数据分类分级标准 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

数据级别

+

隐私风险

+

隐私属性

+

典型示例

+

极高级

+

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来灾难性负面影响。

+

敏感个人数据

+

DNA、种族、宗教信仰、性取向;生物识别信息;原始通信内容;银行卡密码、磁道数据。

+

高级别

+

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来严重负面影响。

+

敏感个人数据

+

权威社会标识(身份证、护照等);网页浏览记录;轨迹信息;云空间上传的内容数据(图库/音频/视频等)。

+

中级别

+

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来重大负面影响。

+

一般个人数据

+

设备标识(IMEI, SN, OAID )、用户标识(user ID);个人基本信息(姓名,地址);手机号、邮箱等。

+

低级别

+

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来有限负面影响。

+

一般个人数据

+

操作系统设置信息(操作系统版本,国家/地区等);设备硬件信息(设备型号,屏幕尺寸,屏幕分辨率等);网络信息(网络连接状态,接入网络信息);设备状态(登录设备时间/时长)。

+

公开(无风险)

+

对个人或组织无不利影响的可公开数据

+

非个人数据

+

公开发布的产品介绍,公开的会议信息,外部开源的代码等。

+
+ +备注:隐私保护和数据分类分级的相关定义参照GDPR中的相关内容。 + +## 通用隐私设计规则 + +为了指导厂商完成产品的隐私设计工作,我们整理了以下通用的隐私设计要求,作为OpenHarmony设备厂商产品隐私设计的指南和参考。 + +**数据收集及使用公开透明** + +采集个人数据时,应清晰、明确地告知用户,并确保告知用户的个人信息将被如何使用。 + +- 针对不同等级的个人数据需要制定针对性的隐私处理策略。 + - 敏感个人数据的采集需要获取数据主体明示同意。 + - 一般个人数据的采集需要数据主体同意或基于其他合法授权。 + - 非个人数据与中、高或极高级别个人数据关联采集,需要数据主体同意或其他合法授权,并在隐私声明中呈现。 + +- 应制定并遵从适当的隐私政策。在收集、使用留存和第三方分享用户个人数据时需要符合所有适用法律、政策和规定。如在收集个人数据前,需充分告知用户处理个人数据的种类、目的、处理方式、保留期限等,满足数据主体权利相关要求。 + + 根据以上要求,我们设计了正确示例以供参考。隐私通知/声明的参考示例如下: + + **图 1** 隐私通知/声明示例图 + + + ![](figure/2-应用启动预授权.png) ![](figure/3-应用隐私声明.png) + +- 个人数据应当基于具体、明确、合法的目的收集,不应与此目的不相符的方式作进一步处理。对于收集目的变更和用户撤销同意后再次重新使用的场景都需要用户重新同意。隐私声明变更和撤销的示例如下图: + + **图 2** 隐私通知/声明变更示例图 + + + ![](figure/4-隐私声明变更通知.png) + + **图 3** 撤销同意示例图 + + + ![](figure/6-1-隐私声明撤销.png) ![](figure/6-2-隐私声明撤销.png) + +- 需要提供用户查看隐私声明的入口。例如,可以在应用的“关于”界面提供查看隐私声明的入口,如示例图所示: + + **图 4** 隐私声明查看界面示例图 + + + ![](figure/5-应用隐私声明入口.png) + + +**数据收集及使用最小化** + +个人数据收集应与数据处理目的相关,且是适当、必要的。开发者应尽可能对个人数据进行匿名化或假名化处理,降低对数据主体的风险。仅可收集和处理与特定目的相关且必需的个人数据,不能进行与特定目的不相关的进一步处理。 + +- 敏感权限申请的时候要满足权限最小化的要求,在申请权限时,只申请获取必需的信息或资源所需要的权限。如应用不需要相机权限就能够实现其功能时,则不应该向用户申请相机权限。 +- 数据收集最小化:针对数据的收集要满足最小化要求,不收集与产品提供服务无关联的数据。如提供定位服务的产品,不应收集用户的网页浏览记录。 +- 数据使用的功能要求能够使用户受益,收集的数据不能用于一些与用户正常使用无关的功能。数据收集不能有其他与用户正常使用无关的功能存在。如不得将“生物特征”、“健康数据”等敏感个人数据用于服务改进、投放广告或营销等非业务核心功能。 +- 禁止在日志中打印敏感个人数据,如需要打印一般个人数据时,应对个人数据进行匿名化或假名化处理; + + 优先使用可以重置的标识符,如系统提供了NetworkID和DVID作为分布式场景下的设备标识符,广告业务场景下则建议使用[OAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oaid-0000001050783198),基于应用的分析则建议使用[ODID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/odid-0000001051063255)和[AAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/aaid-0000001051142988),其他需要唯一标识符的场景可以使用UUID接口生成;可重置的标识符不能满足业务需求时,才选择序列号和MAC地址等永久性标识符。 + + +**数据处理选择和控制** + +对个人数据处理必须要征得用户的同意或遵守其他适用的法律法规,用户对其个人数据要有充分的控制权。 + +- 获取用户敏感权限的授权:产品弹窗提醒,向用户呈现需要获取的权限和权限使用目的,用户可通过选择决定是否进行授权及指定授权的方式,让用户对产品权限的授予和个人数据使用做到透明、可知、可控。如下图所示: + + **图 5** 敏感权限提示框示例图 + + + ![](figure/1-敏感权限弹窗.png) + +- 用户可以修改、取消授予的权限:当用户不同意某一权限或者数据收集时,应当允许用户使用与这部分权限和数据收集不相关的功能。如智慧屏产品上通信社交应用,用户可以拒绝授予相机权限,不应该影响与相机无关的功能操作,如语音通话。 +- 用户在产品使用过程中,针对录入个人数据的场景,需要给用户提供对个人数据的增加、删除、修改、查看的操作。 +- 需要给出硬件回收或返厂进行安全删除个人数据的机制或方法。 +- 对用户系统软件、应用软件的下载或升级,涉及修改用户隐私空间,用户对于这类行为需要有知情权和控制权,必须给用户提示,并提供给用户同意和取消的选项。 + +**数据安全** + +从技术上保证数据处理活动的安全性,包括个人数据的加密存储、安全传输等安全机制,系统应默认开启或采取安全保护措施。 + +- 对于个人数据的访问需要有保护机制,主要包括身份认证和访问控制。身份认证(如用户名、密码)限定只有经过认证的用户才能访问数据,可应用于多用户场景;访问控制(如[权限控制](safety-safeguide-security.md#li201725506375))可应用于对应用程序的限制。 +- 分布式设备个人数据安全存储要满足密钥管理和存储服务(HUKS:Huawei Universal Keystore)的要求,包括:密钥安全存储、数据安全存储。 +- 个人数据在分布式设备间传输要满足设备间的信任绑定关系和数据传输通道的安全性要求。详细信息可以参考[设备互联安全](safety-safeguide-security.md#section26153183616)。 +- 认证凭证数据(密码、口令、指纹等)须加密存储。 + +**本地化处理** + +用户数据优先在本设备进行处理,对于本设备无法处理的数据应尽可能在超级终端设备本地进行数据的处理,如果超级终端本地处理无法满足业务目的的,在数据离开超级终端设备本地时应尽可能选择匿名化。 + +**未成年人数据保护要求** + +产品专门给未成年人设计的,或者产品收集用户年龄从而可以识别到是在收集未成年人的个人数据,需结合目标市场国家的法律,专门分析未成年人个人数据保护的问题,收集未成年人数据前需要征得监护人的同意。 + +## 特殊品类要求 + +针对消费者硬件产品来说,除了满足以上的通用隐私要求以外,针对特殊品类的产品还有以下的特殊要求,在产品设计过程中参照执行。 + +**表2** 特殊品类隐私要求 + + + + + + + + + + + + + + + + + + + + + + + + + +

产品品类

+

隐私保护特殊要求

+

智能家居

+

安防类产品涉及的指纹、声纹、面部识别、虹膜等个人生物识别信息以及用户密码信息,属于敏感个人数据,应采用技术措施处理后(例如提取个人生物识别信息的摘要)再进行加密保存在产品本地。

+

智能家居

+

安防类产品涉及的音视频和图片,设备厂家作为数据控制者时,必须提供独立的隐私通知、应用界面必须有设备厂家品牌标识;音视频数据的传输和存储必须加密,非用户本人访问安防产品的音视频数据,必须获得用户授权。

+

智能家居/影音娱乐

+

带有摄像头的产品建议提供物理上可关闭功能,通过隐藏、遮盖、转向让消费者感知摄像头处于关闭状态。

+

智能家居/影音娱乐

+

带有麦克风的产品建议提供显性显示录音的状态,如录音开启时状态灯闪烁,录音关闭时状态灯熄灭。

+

移动办公

+

用户数据跨设备显示、传输等场景需要获得消费者的明示同意,给予消费者对其个人数据有充分的控制权。

+

车机

+

1、隐私通知及权限设置

+

避免在驾驶态让用户阅读隐私政策和权限设置。

+

车机应用需要考虑车辆使用时的安全性,应避免让用户在驾驶过程中进行复杂的权限设置或阅读隐私政策,比如HiCar应用应该在手机端完成应用基本权限设置和隐私政策阅读后再进行使用。

+

隐私声明在确认用户身份后告知。

+

车辆的数据会涉及车主、驾驶员和乘客,应保证隐私声明通知到了数据主体本人。建议做法是在确认使用者的身份后进行隐私声明,如需要用户登录的应用,应在账号登录后弹出隐私声明而不是账号登录之前。

+

2、共享应用个人数据保护

+

共享应用在车机重启后应退出,并对当前用户个人数据进行清除或加密,应用还应提供对历史数据进行彻底删除的功能。

+

3、消息提示

+

考虑车机的开放环境,应用在车机上进行消息提醒时,应避免直接将消息内容显示在车机上,正确的做法是仅提示有新的消息需要查看。

+
+ diff --git a/zh-cn/device-dev/security/safety-safeguide-security.md b/zh-cn/device-dev/security/safety-safeguide-security.md new file mode 100644 index 0000000000000000000000000000000000000000..63804f366b4110c67b0b87ced8b24aea03dbf220 --- /dev/null +++ b/zh-cn/device-dev/security/safety-safeguide-security.md @@ -0,0 +1,275 @@ +# 安全指南 + +- [安全概述](#section1521410017353) +- [硬件安全](#section2558121318351) + - [安全机制](#section1399511541896) + - [推荐做法](#section948519243104) + +- [系统安全](#section87802111361) + - [安全机制](#section149107611118) + - [推荐做法](#section1364122019112) + +- [数据安全](#section2468927364) + - [安全机制](#section1378993720111) + - [推荐做法](#section1531735481112) + +- [设备互联安全](#section26153183616) +- [应用安全](#section852593153614) + - [安全机制](#section55012136125) + - [推荐做法](#section6341102610123) + + +## 安全概述 + +OpenHarmony操作系统是一个开放的系统,开发者可以通过OpenHarmony开发灵活的服务和应用,为开发者和使用者带来便利和价值。为了达到这一目的,OpenHarmony提供了一个可以有效保护应用和用户数据的执行环境。 + +在这个执行环境中,芯片的安全能力、系统的安全能力、以及上层的安全服务一起协作,从硬件安全、系统安全、数据安全、设备互联安全、应用安全、安全更新多个维度提供安全保障。 + +**图 1** 安全保障示意图 +![](figure/安全保障示意图.png "安全保障示意图") + +## 硬件安全 + +### 安全机制 + +- 启动可信根 + + OpenHarmony设备采用PKI(Public Key Infrastructure)体系保护软件完整性,确保设备运行来源合法、软件未被篡改。 + + 在设备启动流程中,逐级进行软件签名校验形成安全启动链,任何一个环节的签名校验不通过即终止设备启动;安全启动链中最初执行签名校验的软硬件实体,需确保自身的合法、未被篡改。该实体即为设备的启动可信根。启动可信根可为固化在ROM中的一段代码,这段代码在芯片制造环节固化到芯片中,芯片制造完成后软件不可更改,在设备上电初始化的过程中,最先执行这段ROM中的代码,并由这段ROM代码执行后续的软件签名校验。 + + ROM中的代码在执行签名校验时,需确保用于校验的PKI公钥的合法性,OpenHarmony设备可采用eFuse/OTP等存储介质来存储公钥(如公钥哈希值),来保护公钥自身的合法性。公钥一般在设备制造环节,烧录到设备的eFuse/OTP中。 + +- 硬件隔离可信环境 + + 硬件隔离的可信环境,遵循了可信计算系统的设计理念。可信环境内外形成了两个世界:可信世界与不可信世界,两者之间存在清晰而明确的隔离边界;OpenHarmony设备在可信环境中实现了核心敏感数据的保护机制,可确保即使不可信世界的操作系统存在漏洞且被利用,也依然能确保可信环境中敏感数据的安全。 + + OpenHarmony设备的可信环境,基于硬件的安全隔离机制构建,在不同的OpenHarmony设备上芯片隔离机制略有差异,较为通用的方法是采用ARM的TrustZone技术。在部分Risc-V芯片平台上,也可能采用独立安全核的形式来构建可信环境。 + + 可信环境中,运行特定的、精简的操作系统iTrustee lite,用于管理可信环境的资源和任务调度,给OpenHarmony设备提供安全服务。密钥管理及数据安全,是可信环境中最为常见的安全服务,设备在eFuse/OTP中存有硬件唯一根密钥,可信环境可基于该密钥结合业务上下文衍生出多种密钥,给应用提供密钥管理和数据加解密相关的服务;设备核心密钥生命周期不离开可信环境。可信环境同样可提供身份认证、系统状态监控、数据安全存储等安全服务,提高设备安全性。 + +- 硬件密钥引擎 + + 密码学是信息安全的基础。数据加解密对计算机设备的核心诉求是:高效、安全。硬件加解密技术利用计算机硬件辅助软件,甚至直接取代软件,来处理数据的加解密。相比由软件实现的加解密计算,硬件实现的加解密计算更高效、更安全。 + + 由硬件来实现加解密处理,意味着部分专用的硬件资源会用于处理加解密计算任务,当加解密引擎工作的时候CPU可以并发地继续执行其他计算任务,因此硬件加解密引擎可以带来极大的性能提升,同时降低CPU负载。此外,硬件密钥引擎可以带来更高的安全性,设计良好的硬件密钥引擎,哪怕软件被攻破也依然可保护密钥不泄露,甚至可对抗电磁、辐射等物理侧信道攻击。 + + OpenHarmony设备支持硬件密钥引擎,支撑OpenHarmony系统进行数据加解密、证书验签、哈希计算等计算任务,可支持AES/RSA等主流的密码学算法。 + + +### 推荐做法 + +- 启动可信根可由一段固化在芯片中的代码和设备根密钥组成,前者一般在芯片制造阶段写入,设备生命周期内不可更改,负责在启动阶段校验设备软件证书;后者则是用于设备证书签名的私钥相对应的公钥,证书签名私钥不出PKI签名服务器,而公钥则需写入设备。为防止攻击者篡改公钥从而达到绕过签名认证的目的,写入OpenHarmony设备的公钥须确保不可篡改,可将公钥信息写入如熔丝等介质;考虑到熔丝空间有限,可仅存储公钥的哈希值,并由启动代码校验公钥的合法性。 +- 可信执行环境较为通用的做法是基于ARM TrustZone技术构建,也可根据设备的实际形态选择其他隔离机制,如TrustZone-M、独立安全核等;可信执行环境中须部署TEE OS,用于管理可信执行环境的资源及任务调度。OpenHarmony系统提供iTrustee作为TEE OS的解决方案,开发者及设备商可基于iTrustee开发并部署安全业务。 + + 并非所有OpenHarmony设备都强制要求支持可信执行环境,部分运行低敏感业务的瘦资源设备可不做强制要求;可根据实际业务场景选择是否支持可信执行环境,以及实现怎样的可信执行环境。 + +- 硬件密钥引擎须提供真随机数、公钥、对称密钥、哈希等密钥算法能力,通过在OpenHarmony系统中部署相应的驱动程序,给应用提供统一的密钥管理及密钥算法服务。 + +## 系统安全 + +### 安全机制 + +对于128KB\~128MB内存的设备,推荐使用OpenHarmony轻内核组件,在该内核下: + +- 进程隔离 + + 进程隔离是为了防止A进程读写B进程内存数据的情况发生,进程的隔离技术,一般都采用虚拟地址空间映射方式,通过MMU配置,进程A的虚拟地址和进程B的虚拟地址映射各自不同的实际的物理地址段,这样A进程通过访问虚拟地址访问的实际内存数据在非共享内存的情况下,只属于A进程,B进程无法直接访问。 + + OpenHarmony由于资源有限,对于内核态和用户态的进程采用不同的方式:所有的内核态进程共享同一块VMM空间,即所有的内核态进程之间无隔离,系统启动时内核态创建两个基本进程KProcess和KIdle,KProcess进程为内核态进程的根进程,KIdle进程为KProcess进程的子进程;但是对于每一个用户态进程均拥有自己独立的VMM空间,相互之间不可见,实现进程间隔离。 + +- 自主访问控制 + + 自主访问控制DAC(Discretionary Access Control)的思想是文件权限由文件拥有者来决定其他角色的访问权限。权限管控粒度分为三类:user\(自身\), group\(组员\),other\(其他人\),即UGO。将任意用户分类为UGO中三者之一,并采取相应的管控策略,即完成了DAC权限校验流程。 + + DAC机制依赖于进程的uid、gid等属性,需要以此作为文件创建以及文件访问过程中的特征id。文件创建时,创建者将自身uid写入文件,文件访问时,又以此作为文件归属的分类依据。 + + 每一个应用,对应一个uid。应用在创建文件时,将自身uid信息加入被创建文件的元数据\(metadata\)中,并设置UGO三个组的权限。在文件访问过程中,将以访问者uid作为访问校验主体、以文件元数据中的uid权限信息作为客体,进行权限校验。 + + 下图描述了DAC在文件访问时的鉴权过程,首先匹配进程uid和文件uid属性,其次匹配进程gid和文件gid属性,最后都匹配失败的情况,判断文件other属性是否支持进程的读、写、执行操作。同时支持忽略DAC检测机制(读、写、执行)作为一组系统特权(Capability),支持高权限(如系统服务)对低权限(三方APP)的文件管理。 + + **图 2** DAC流程图 + ![](figure/DAC流程图.png "DAC流程图") + +- Capability机制 + + Capability机制实际上是对root权限的具体细分。在多用户计算机系统中,一般会有一个特殊的角色拥有系统的所有权限,这个角色一般是系统管理员\(root\)。对于OpenHarmony这种需要支持三方应用生态的内核,需要将系统中的特权访问进行管控。系统需要对用户层访问内核的特权级系统调用进行限制。仅允许部分高权限应用进行特权操作。具体实现方式是内核spawn第一个用户程序INIT,其包含全部的特权能力,此后,INIT拉起其他应用框架服务,拉起过程中,对各应用框架进行相应的降权操作,为各应用保留必须的特权能力。 当应用去调用特权接口时,内核态就会通过进程ID查看当前访问者是否有权限访问目标接口。 + +- 安全启动 + + 安全启动是整个系统安全的基础,通过采用数字签名和完整性校验机制,从芯片内部固化的可信启动根开始,逐级校验每一层软件的完整性和合法性,确保最终启动的操作系统软件是厂家提供的正确合法的软件,防止攻击者对系统软件做恶意的篡改和植入,为整个系统提供初始安全的基础运行环境。 + + 在芯片上电后,由于片上ROM代码本身不可更改,因此无需校验;片上ROM基于eFuse中的非对称算法公钥hash对bootloader进行校验。这些过程都基于硬件信任根来进行,是完全可信的。经过此过程校验通过的bootloader模块可以作为后续的信任基础,此过程就是启动信任链的构造过程。Bootloader通常首先对执行环境进行一定的初始化,主要是初始化DDR以及flash读写,为进一步加载后续模块以及执行更为复杂的逻辑进行准备。Bootloader完成初始化动作后,首先完成x509证书的完整性校验,然后利用x509证书的公钥对需要校验的镜像包(kernel.bin、teeOS.bin、rootfs.bin)进行校验。 + + +### 推荐做法 + +- 自主访问控制和Capability机制是控制资源被谁可以访问的机制,建议所有权限设置都采用最小权限原则。 +- 安全启动必须要开启,信任根必须是基于芯片的不可更改的形式存在,并且在有安全升级的情况下,必须考虑安全升级后对于安全启动的影响,也就是安全升级后必须要更新对应镜像文件的签名信息或者hash值。 + +## 数据安全 + +### 安全机制 + +HUKS(Huawei Universal Keystore Service),提供了密钥管理、证书管理服务,当前在OpenHarmony上主要提供密钥管理服务,用于支撑HiChain\(设备身份认证平台\)的基础设备认证。如下是HUKS的功能结构图: + +**图 3** HUKS功能结构图 +![](figure/HUKS功能结构图.png "HUKS功能结构图") + +支持算法包括: + +- 认证加密:AES-128/192/256-GCM +- 签名验签:ED25519 +- 密钥协商:X25519 +- 消息认证:HMAC-SHA256/512 +- 数据摘要:SHA256/512 + +HUKS在使用中有如下约束: + +- 密钥安全存储:密钥要求存储于安全存储区域,数据不可以修改,恢复出厂设置时出厂预置的密钥不能被删除。 +- 密钥访问安全:OpenHarmony通过将不同应用数据保存在不同的位置,来实现应用间数据的隔离。通过参数结构体中包含UID和进程ID,来实现不同应用间的数据隔离。 +- 不支持并发访问:HUKS本身不考虑多个应用同时调用的情况,因为HUKS只是一个lib库,也不考虑资源的互斥。如果有多个应用都会用到HUKS服务,那么应该由每个应用各自链接一份HUKS库,并由业务传入持久化数据存储的路径,以实现应用间的数据存储分开。数据存储在各应用各自存储目录下。 + +### 推荐做法 + +对于设备认证功能,建议使用HiChain来对接HUKS,HUKS可以向HiChain等应用提供密钥的产生、导入、导出、加密/解密、存储、销毁,证书的导入和查询,秘密信息的存储等能力。 + +## 设备互联安全 + +为了实现用户数据在设备互联场景下在各个设备之间的安全流转,需要保证设备之间相互正确可信,即设备和设备之间建立信任关系,并能够在验证信任关系后,搭建安全的连接通道,实现用户数据的安全传输。设备之间的信任关系在本文档中涉及IoT主控设备和IoT设备之间建立的可信关系。设备间可信关系建立的流程如下图所示: + +**图 4** 设备间建立可信关系流程图 +![](figure/设备间建立可信关系流程图.png "设备间建立可信关系流程图") + +- **IoT设备互联安全** + + 设备互联支持基于OpenHarmony的IoT设备(如AI音箱、智能家居、智能穿戴等设备)与IoT主控设备间建立点对点的信任关系,并在具备信任关系的设备间,搭建安全的连接通道,实现用户数据端到端加密传输。 + + +- **IoT主控设备的IoT业务身份标识** + + IoT主控设备为不同的IoT设备管理业务生成不同的身份标识,形成不同IoT管理业务间的隔离,该标识用于IoT主控设备与IoT设备之间的认证以及通信。IoT业务身份标识为椭圆曲线公私钥对(Ed25519公私钥对)。 + + +- **IoT设备身份标识** + + IoT设备会生成各自的设备身份标识,用来与IoT主控设备通信。该身份标识同样为椭圆曲线公私钥对(Ed25519公私钥对);IoT设备私钥不出IoT设备,设备每次恢复出厂设置,会重置这个公私钥对。 + + 上述身份标识可用于IoT主控设备与IoT设备间的安全通信:当IoT主控设备与IoT设备通过信任绑定流程交换业务身份标识或设备标识后,可以进行密钥协商并建立安全通信通道。 + + +- **设备间点对点的信任绑定** + + IoT主控设备和IoT设备建立点对点信任关系的过程,实际上是相互交换IoT设备的身份标识的过程。 + + 在点对点建立信任关系的过程中,用户需要在IoT主控设备上,输入IoT设备上提供的PIN码:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置;PIN码的展示形式,可以是一个用户可读的数字,也可以是一个二维码。随后,IoT主控设备和IoT设备间使用PAKE协议完成认证和会话密钥协商过程,并在此基础上,通过协商出的会话密钥加密传输通道用于交换双方设备的身份标识公钥。 + + +- **IoT主控设备与IoT设备间的通信安全** + + 当建立过信任关系的IoT主控设备与IoT设备间进行通信时,双方在完成上述信任关系绑定后,基于本地存储的对端身份公钥相互进行认证;在每次通信时基于STS协议完成双向身份认证以及会话密钥协商,之后设备使用此会话密钥加密双方设备间的传输通道。 + + +## 应用安全 + +### 安全机制 + +- 应用签名管控 + + OpenHarmony应用的安装需要首先对包的完整性进行校验,具体策略是在开发阶段完成开发和调试后对安装包进行签名,这个签名需要使用指定的私钥,这个私钥就是跟验签用的公钥是一对的,一般的做法是OEM厂商生成一对公私钥,然后将公钥信息预置到设备中,而私钥就放在一个不联网的本地服务器上,这样可以确保私钥被泄露的风险尽量小,而应用在完成开发后就可以通过外置设备(例如USB)上传安装包到存放私钥的服务器上计算签名并下载签名结果到外置设备上。而安装应用时首先计算包的Hash值,一般采用SHA256算法,然后使用hash值和签名信息以及预置公钥进行验签,只有验签通过的应用才能安装。 + + 除了要证明应用来自云端认证过的,还需要证明来源,即这个应用来自合法开发者开发的,具体做法是,开发者向云端申请开发证书,开发完成后,用开发证书进行自签名,设备端存放这个证书的上一级证书,所以安装过程中,对自签名信息做校验,确保开发者的合法性。 + +- 应用权限控制 + + 由于OpenHarmony系统允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 + + **表 1** **OpenHarmony系统权限列表** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

OpenHarmony系统权限

+

授权方式

+

权限说明

+

ohos.permission.LISTEN_BUNDLE_CHANGE

+

system_grant(静态权限)

+

允许该应用获取应用变化消息。

+

ohos.permission.GET_BUNDLE_INFO

+

system_grant(静态权限)

+

允许该应用获取应用信息。

+

ohos.permission.INSTALL_BUNDLE

+

system_grant(静态权限)

+

允许该应用安装应用。

+

ohos.permission.CAMERA

+

user_grant(动态权限)

+

此应用可随时使用相机拍摄照片和录制视频。

+

ohos.permission.MODIFY_AUDIO_SETTINGS

+

system_grant(静态权限)

+

允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

+

ohos.permission.READ_MEDIA

+

user_grant(动态权限)

+

允许该应用读取您的视频收藏。

+

ohos.permission.MICROPHONE

+

user_grant(动态权限)

+

此应用可随时使用麦克风进行录音。

+

ohos.permission.WRITE_MEDIA

+

user_grant(动态权限)

+

允许该应用写入您的音乐收藏。

+

ohos.permission.DISTRIBUTED_DATASYNC

+

user_grant(动态权限)

+

管控分布式数据传输能力。

+

ohos.permission.DISTRIBUTED_VIRTUALDEVICE

+

user_grant(动态权限)

+

允许应用使用分布式虚拟能力

+
+ + +### 推荐做法 + +开发者在开发过程中需明确后续应用在运行时需要运行哪些权限,并在profile.json中进行注册,然后需要对应用进行签名,确保设备在安装这些应用时能对应用的完整性和来源进行校验。 + diff --git a/zh-cn/device-dev/security/safety.md b/zh-cn/device-dev/security/safety.md new file mode 100644 index 0000000000000000000000000000000000000000..72bbe83ac0cf5052a2b1b53ce27b380ef390b963 --- /dev/null +++ b/zh-cn/device-dev/security/safety.md @@ -0,0 +1,7 @@ +# 隐私与安全 + +- **[隐私保护](safety-protection-privacyguide.md)** + +- **[安全指南](safety-safeguide-security.md)** + + diff --git "a/zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" "b/zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" deleted file mode 100755 index c387b9a68e6fd35a272c442f521842e8410c009a..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/security/\345\256\211\345\205\250\346\214\207\345\215\227.md" +++ /dev/null @@ -1,271 +0,0 @@ -# 安全指南 - -- [安全概述](#section1521410017353) -- [硬件安全](#section2558121318351) -- [安全机制](#section1312953842210) -- [推荐做法](#section37901319112311) -- [系统安全](#section87802111361) -- [安全机制](#section1654963052914) -- [推荐做法](#section45821048173613) -- [数据安全](#section2468927364) -- [安全机制](#section11192175813293) -- [推荐做法](#section174640713306) -- [设备互联安全](#section26153183616) -- [应用安全](#section852593153614) -- [安全机制](#section12125105014377) -- [推荐做法](#section1641420155381) - -## 安全概述 - -OpenHarmony操作系统是一个开放的系统,开发者可以通过OpenHarmony开发灵活的服务和应用,为开发者和使用者带来便利和价值。为了达到这一目的,OpenHarmony提供了一个可以有效保护应用和用户数据的执行环境。 - -在这个执行环境中,芯片的安全能力、系统的安全能力、以及上层的安全服务一起协作,从硬件安全、系统安全、数据安全、设备互联安全、应用安全、安全更新多个维度提供安全保障。 - -**图 1** 安全保障示意图 -![](figures/安全保障示意图.png "安全保障示意图") - -## 硬件安全 - -## 安全机制 - -- 启动可信根 - - OpenHarmony设备采用PKI(Public Key Infrastructure)体系保护软件完整性,确保设备运行来源合法、软件未被篡改。 - - 在设备启动流程中,逐级进行软件签名校验形成安全启动链,任何一个环节的签名校验不通过即终止设备启动;安全启动链中最初执行签名校验的软硬件实体,需确保自身的合法、未被篡改。该实体即为设备的启动可信根。启动可信根可为固化在ROM中的一段代码,这段代码在芯片制造环节固化到芯片中,芯片制造完成后软件不可更改,在设备上电初始化的过程中,最先执行这段ROM中的代码,并由这段ROM代码执行后续的软件签名校验。 - - ROM中的代码在执行签名校验时,需确保用于校验的PKI公钥的合法性,OpenHarmony设备可采用eFuse/OTP等存储介质来存储公钥(如公钥哈希值),来保护公钥自身的合法性。公钥一般在设备制造环节,烧录到设备的eFuse/OTP中。 - -- 硬件隔离可信环境 - - 硬件隔离的可信环境,遵循了可信计算系统的设计理念。可信环境内外形成了两个世界:可信世界与不可信世界,两者之间存在清晰而明确的隔离边界;OpenHarmony设备在可信环境中实现了核心敏感数据的保护机制,可确保即使不可信世界的操作系统存在漏洞且被利用,也依然能确保可信环境中敏感数据的安全。 - - OpenHarmony设备的可信环境,基于硬件的安全隔离机制构建,在不同的OpenHarmony设备上芯片隔离机制略有差异,较为通用的方法是采用ARM的TrustZone技术。在部分Risc-V芯片平台上,也可能采用独立安全核的形式来构建可信环境。 - - 可信环境中,运行特定的、精简的操作系统iTrustee lite,用于管理可信环境的资源和任务调度,给OpenHarmony设备提供安全服务。密钥管理及数据安全,是可信环境中最为常见的安全服务,设备在eFuse/OTP中存有硬件唯一根密钥,可信环境可基于该密钥结合业务上下文衍生出多种密钥,给应用提供密钥管理和数据加解密相关的服务;设备核心密钥生命周期不离开可信环境。可信环境同样可提供身份认证、系统状态监控、数据安全存储等安全服务,提高设备安全性。 - -- 硬件密钥引擎 - - 密码学是信息安全的基础。数据加解密对计算机设备的核心诉求是:高效、安全。硬件加解密技术利用计算机硬件辅助软件,甚至直接取代软件,来处理数据的加解密。相比由软件实现的加解密计算,硬件实现的加解密计算更高效、更安全。 - - 由硬件来实现加解密处理,意味着部分专用的硬件资源会用于处理加解密计算任务,当加解密引擎工作的时候CPU可以并发地继续执行其他计算任务,因此硬件加解密引擎可以带来极大的性能提升,同时降低CPU负载。此外,硬件密钥引擎可以带来更高的安全性,设计良好的硬件密钥引擎,哪怕软件被攻破也依然可保护密钥不泄露,甚至可对抗电磁、辐射等物理侧信道攻击。 - - OpenHarmony设备支持硬件密钥引擎,支撑OpenHarmony系统进行数据加解密、证书验签、哈希计算等计算任务,可支持AES/RSA等主流的密码学算法。 - - -## 推荐做法 - -- 启动可信根可由一段固化在芯片中的代码和设备根密钥组成,前者一般在芯片制造阶段写入,设备生命周期内不可更改,负责在启动阶段校验设备软件证书;后者则是用于设备证书签名的私钥相对应的公钥,证书签名私钥不出PKI签名服务器,而公钥则需写入设备。为防止攻击者篡改公钥从而达到绕过签名认证的目的,写入OpenHarmony设备的公钥须确保不可篡改,可将公钥信息写入如熔丝等介质;考虑到熔丝空间有限,可仅存储公钥的哈希值,并由启动代码校验公钥的合法性。 -- 可信执行环境较为通用的做法是基于ARM TrustZone技术构建,也可根据设备的实际形态选择其他隔离机制,如TrustZone-M、独立安全核等;可信执行环境中须部署TEE OS,用于管理可信执行环境的资源及任务调度。OpenHarmony系统提供iTrustee作为TEE OS的解决方案,开发者及设备商可基于iTrustee开发并部署安全业务。 - - 并非所有OpenHarmony设备都强制要求支持可信执行环境,部分运行低敏感业务的瘦资源设备可不做强制要求;可根据实际业务场景选择是否支持可信执行环境,以及实现怎样的可信执行环境。 - -- 硬件密钥引擎须提供真随机数、公钥、对称密钥、哈希等密钥算法能力,通过在OpenHarmony系统中部署相应的驱动程序,给应用提供统一的密钥管理及密钥算法服务。 - -## 系统安全 - -## 安全机制 - -对于128KB\~128MB内存的设备,推荐使用OpenHarmony轻内核组件,在该内核下: - -- 进程隔离 - - 进程隔离是为了防止A进程读写B进程内存数据的情况发生,进程的隔离技术,一般都采用虚拟地址空间映射方式,通过MMU配置,进程A的虚拟地址和进程B的虚拟地址映射各自不同的实际的物理地址段,这样A进程通过访问虚拟地址访问的实际内存数据在非共享内存的情况下,只属于A进程,B进程无法直接访问。 - - OpenHarmony由于资源有限,对于内核态和用户态的进程采用不同的方式:所有的内核态进程共享同一块VMM空间,即所有的内核态进程之间无隔离,系统启动时内核态创建两个基本进程KProcess和KIdle,KProcess进程为内核态进程的根进程,KIdle进程为KProcess进程的子进程;但是对于每一个用户态进程均拥有自己独立的VMM空间,相互之间不可见,实现进程间隔离。 - -- 自主访问控制 - - 自主访问控制DAC(Discretionary Access Control)的思想是文件权限由文件拥有者来决定其他角色的访问权限。权限管控粒度分为三类:user\(自身\), group\(组员\),other\(其他人\),即UGO。将任意用户分类为UGO中三者之一,并采取相应的管控策略,即完成了DAC权限校验流程。 - - DAC机制依赖于进程的uid、gid等属性,需要以此作为文件创建以及文件访问过程中的特征id。文件创建时,创建者将自身uid写入文件,文件访问时,又以此作为文件归属的分类依据。 - - 每一个应用,对应一个uid。应用在创建文件时,将自身uid信息加入被创建文件的元数据\(metadata\)中,并设置UGO三个组的权限。在文件访问过程中,将以访问者uid作为访问校验主体、以文件元数据中的uid权限信息作为客体,进行权限校验。 - - 下图描述了DAC在文件访问时的鉴权过程,首先匹配进程uid和文件uid属性,其次匹配进程gid和文件gid属性,最后都匹配失败的情况,判断文件other属性是否支持进程的读、写、执行操作。同时支持忽略DAC检测机制(读、写、执行)作为一组系统特权(Capability),支持高权限(如系统服务)对低权限(三方APP)的文件管理。 - - **图 2** DAC流程图 - ![](figures/DAC流程图.png "DAC流程图") - -- Capability机制 - - Capability机制实际上是对root权限的具体细分。在多用户计算机系统中,一般会有一个特殊的角色拥有系统的所有权限,这个角色一般是系统管理员\(root\)。对于OpenHarmony这种需要支持三方应用生态的内核,需要将系统中的特权访问进行管控。系统需要对用户层访问内核的特权级系统调用进行限制。仅允许部分高权限应用进行特权操作。具体实现方式是内核spawn第一个用户程序INIT,其包含全部的特权能力,此后,INIT拉起其他应用框架服务,拉起过程中,对各应用框架进行相应的降权操作,为各应用保留必须的特权能力。 当应用去调用特权接口时,内核态就会通过进程ID查看当前访问者是否有权限访问目标接口。 - -- 安全启动 - - 安全启动是整个系统安全的基础,通过采用数字签名和完整性校验机制,从芯片内部固化的可信启动根开始,逐级校验每一层软件的完整性和合法性,确保最终启动的操作系统软件是厂家提供的正确合法的软件,防止攻击者对系统软件做恶意的篡改和植入,为整个系统提供初始安全的基础运行环境。 - - 在芯片上电后,由于片上ROM代码本身不可更改,因此无需校验;片上ROM基于eFuse中的非对称算法公钥hash对bootloader进行校验。这些过程都基于硬件信任根来进行,是完全可信的。经过此过程校验通过的bootloader模块可以作为后续的信任基础,此过程就是启动信任链的构造过程。Bootloader通常首先对执行环境进行一定的初始化,主要是初始化DDR以及flash读写,为进一步加载后续模块以及执行更为复杂的逻辑进行准备。Bootloader完成初始化动作后,首先完成x509证书的完整性校验,然后利用x509证书的公钥对需要校验的镜像包(kernel.bin、teeOS.bin、rootfs.bin)进行校验。 - - -## 推荐做法 - -- 自主访问控制和Capability机制是控制资源被谁可以访问的机制,建议所有权限设置都采用最小权限原则。 -- 安全启动必须要开启,信任根必须是基于芯片的不可更改的形式存在,并且在有安全升级的情况下,必须考虑安全升级后对于安全启动的影响,也就是安全升级后必须要更新对应镜像文件的签名信息或者hash值。 - -## 数据安全 - -## 安全机制 - -HUKS(Huawei Universal Keystore Service),提供了密钥管理、证书管理服务,当前在OpenHarmony上主要提供密钥管理服务,用于支撑HiChain\(设备身份认证平台\)的基础设备认证。如下是HUKS的功能结构图: - -**图 3** HUKS功能结构图 -![](figures/HUKS功能结构图.png "HUKS功能结构图") - -支持算法包括: - -- 认证加密:AES-128/192/256-GCM -- 签名验签:ED25519 -- 密钥协商:X25519 -- 消息认证:HMAC-SHA256/512 -- 数据摘要:SHA256/512 - -HUKS在使用中有如下约束: - -- 密钥安全存储:密钥要求存储于安全存储区域,数据不可以修改,恢复出厂设置时出厂预置的密钥不能被删除。 -- 密钥访问安全:OpenHarmony通过将不同应用数据保存在不同的位置,来实现应用间数据的隔离。通过参数结构体中包含UID和进程ID,来实现不同应用间的数据隔离。 -- 不支持并发访问:HUKS本身不考虑多个应用同时调用的情况,因为HUKS只是一个lib库,也不考虑资源的互斥。如果有多个应用都会用到HUKS服务,那么应该由每个应用各自链接一份HUKS库,并由业务传入持久化数据存储的路径,以实现应用间的数据存储分开。数据存储在各应用各自存储目录下。 - -## 推荐做法 - -对于设备认证功能,建议使用HiChain来对接HUKS,HUKS可以向HiChain等应用提供密钥的产生、导入、导出、加密/解密、存储、销毁,证书的导入和查询,秘密信息的存储等能力。 - -## 设备互联安全 - -为了实现用户数据在设备互联场景下在各个设备之间的安全流转,需要保证设备之间相互正确可信,即设备和设备之间建立信任关系,并能够在验证信任关系后,搭建安全的连接通道,实现用户数据的安全传输。设备之间的信任关系在本文档中涉及IoT主控设备和IoT设备之间建立的可信关系。设备间可信关系建立的流程如下图所示: - -**图 4** 设备间建立可信关系流程图 -![](figures/设备间建立可信关系流程图.png "设备间建立可信关系流程图") - -- **IoT设备互联安全** - - 设备互联支持基于OpenHarmony的IoT设备(如AI音箱、智能家居、智能穿戴等设备)与IoT主控设备间建立点对点的信任关系,并在具备信任关系的设备间,搭建安全的连接通道,实现用户数据端到端加密传输。 - - -- **IoT主控设备的IoT业务身份标识** - - IoT主控设备为不同的IoT设备管理业务生成不同的身份标识,形成不同IoT管理业务间的隔离,该标识用于IoT主控设备与IoT设备之间的认证以及通信。IoT业务身份标识为椭圆曲线公私钥对(Ed25519公私钥对)。 - - -- **IoT设备身份标识** - - IoT设备会生成各自的设备身份标识,用来与IoT主控设备通信。该身份标识同样为椭圆曲线公私钥对(Ed25519公私钥对);IoT设备私钥不出IoT设备,设备每次恢复出厂设置,会重置这个公私钥对。 - - 上述身份标识可用于IoT主控设备与IoT设备间的安全通信:当IoT主控设备与IoT设备通过信任绑定流程交换业务身份标识或设备标识后,可以进行密钥协商并建立安全通信通道。 - - -- **设备间点对点的信任绑定** - - IoT主控设备和IoT设备建立点对点信任关系的过程,实际上是相互交换IoT设备的身份标识的过程。 - - 在点对点建立信任关系的过程中,用户需要在IoT主控设备上,输入IoT设备上提供的PIN码:对于有屏幕的设备,该PIN码动态生成;对于没有屏幕的设备,该PIN码由设备生产厂家预置;PIN码的展示形式,可以是一个用户可读的数字,也可以是一个二维码。随后,IoT主控设备和IoT设备间使用PAKE协议完成认证和会话密钥协商过程,并在此基础上,通过协商出的会话密钥加密传输通道用于交换双方设备的身份标识公钥。 - - -- **IoT主控设备与IoT设备间的通信安全** - - 当建立过信任关系的IoT主控设备与IoT设备间进行通信时,双方在完成上述信任关系绑定后,基于本地存储的对端身份公钥相互进行认证;在每次通信时基于STS协议完成双向身份认证以及会话密钥协商,之后设备使用此会话密钥加密双方设备间的传输通道。 - - -## 应用安全 - -## 安全机制 - -- 应用签名管控 - - OpenHarmony应用的安装需要首先对包的完整性进行校验,具体策略是在开发阶段完成开发和调试后对安装包进行签名,这个签名需要使用指定的私钥,这个私钥就是跟验签用的公钥是一对的,一般的做法是OEM厂商生成一对公私钥,然后将公钥信息预置到设备中,而私钥就放在一个不联网的本地服务器上,这样可以确保私钥被泄露的风险尽量小,而应用在完成开发后就可以通过外置设备(例如USB)上传安装包到存放私钥的服务器上计算签名并下载签名结果到外置设备上。而安装应用时首先计算包的Hash值,一般采用SHA256算法,然后使用hash值和签名信息以及预置公钥进行验签,只有验签通过的应用才能安装。 - - 除了要证明应用来自云端认证过的,还需要证明来源,即这个应用来自合法开发者开发的,具体做法是,开发者向云端申请开发证书,开发完成后,用开发证书进行自签名,设备端存放这个证书的上一级证书,所以安装过程中,对自签名信息做校验,确保开发者的合法性。 - -- 应用权限控制 - - 由于OpenHarmony系统允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 - - **表 1** **OpenHarmony系统权限列表** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

OpenHarmony系统权限

-

授权方式

-

权限说明

-

ohos.permission.LISTEN_BUNDLE_CHANGE

-

system_grant(静态权限)

-

允许该应用获取应用变化消息。

-

ohos.permission.GET_BUNDLE_INFO

-

system_grant(静态权限)

-

允许该应用获取应用信息。

-

ohos.permission.INSTALL_BUNDLE

-

system_grant(静态权限)

-

允许该应用安装应用。

-

ohos.permission.CAMERA

-

user_grant(动态权限)

-

此应用可随时使用相机拍摄照片和录制视频。

-

ohos.permission.MODIFY_AUDIO_SETTINGS

-

system_grant(静态权限)

-

允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

-

ohos.permission.READ_MEDIA

-

user_grant(动态权限)

-

允许该应用读取您的视频收藏。

-

ohos.permission.MICROPHONE

-

user_grant(动态权限)

-

此应用可随时使用麦克风进行录音。

-

ohos.permission.WRITE_MEDIA

-

user_grant(动态权限)

-

允许该应用写入您的音乐收藏。

-

ohos.permission.DISTRIBUTED_DATASYNC

-

user_grant(动态权限)

-

管控分布式数据传输能力。

-

ohos.permission.DISTRIBUTED_VIRTUALDEVICE

-

user_grant(动态权限)

-

允许应用使用分布式虚拟能力

-
- - -## 推荐做法 - -开发者在开发过程中需明确后续应用在运行时需要运行哪些权限,并在profile.json中进行注册,然后需要对应用进行签名,确保设备在安装这些应用时能对应用的完整性和来源进行校验。 - diff --git "a/zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" "b/zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" deleted file mode 100755 index 3777685f3ff4a8e3cdd3e43aad55008b8d02fa27..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/security/\351\232\220\347\247\201\344\277\235\346\212\244.md" +++ /dev/null @@ -1,264 +0,0 @@ -# 隐私保护 - -- [隐私保护概述](#section13200134331414) -- [数据分类分级](#section2371104991511) -- [通用隐私设计规则](#section10354102411162) -- [特殊品类要求](#section118861450201618) - -## 隐私保护概述 - -随着互联网及信息化的发展,个人数据在社会经济和日常生活中发挥着越来越重要的作用。与此同时,个人数据泄露的风险也在增加,消费者产品开发者需要更加有效的保护用户的个人数据,提高用户对产品的信任度。为了提升消费者的隐私体验,产品应默认设置较高级别隐私保护策略,达到保护消费者隐私的目的。 - -**基本概念** - -- **个人数据(Personal Data)** - - 与一个身份已被识别或者身份可被识别的自然人(“数据主体”)相关的任何信息;身份可识别的自然人是指其身份可以通过诸如姓名、身份证号、位置数据等识别码或者通过一个或多个与自然人的身体、生理、精神、经济、文化或者社会身份相关的特定因素来直接或者间接地被识别。个人数据包括:自然人的email地址、电话号码、生物特征(指纹)、位置数据、IP地址、医疗信息、宗教信仰、社保号、婚姻状态等。 - -- **敏感个人数据(Sensitive Personal Data)** - - 敏感个人数据是个人数据的一个重要子集,指的是涉及数据主体的最私密领域的信息或者一旦泄露可能会给数据主体造成重大不利影响的数据。欧盟等国家和地区法律定义的敏感个人数据包括种族、政治观点、宗教和哲学信仰、工会成员资格、基因数据、生物信息、健康和性生活状况、性取向等。 - - 根据业界最佳实践,敏感个人数据还包括可与自然人身份相关联的银行卡号、身份证号、护照号、口令等。敏感个人数据的处理需要更多更严格的保护措施。 - -- **公开个人数据(Public available Personal Data)** - - 数据主体主动公开的个人数据,或公开网页/应用上可访问的个人数据,包括论坛公开的发帖、评论等。 - -- **用户画像(User Profile)** - - 指对个人数据采取的任何自动化处理的方式,包括评估某个自然人特定方面的情况,尤其是为了分析和预测该自然人的工作表现、经济状况、健康、个人喜好、兴趣、可信度、行为举止、所在位置或行迹。 - -- **数据控制者(Data Controller)** - - 单独或者与他人共同确定个人数据处理的目的和手段的自然人、法人、公共机构、政府部门或其他机构。 - -- **数据处理者(Data Processor)** - - 指代表数据控制者处理个人数据的自然人、法人、公共机构、政府部门或其他机构。数据处理者必须按照数据控制者的要求对个人数据进行充分的保护。 - -- **明示同意(Explicit consent)** - - 如下几种情形GDPR法律提到可以通过数据主体明示同意的方式合法地处理数据: - - - 处理敏感个人数据。 - - 自动化决策,包括进行用户画像。 - - 向不具备充分保护水平的国家转移个人数据,并以同意作为合法性基础。 - - 实现明示同意的方式有: - - - 在收集特定数据时,弹出隐私声明告知个人数据处理相关事项,提供勾选框但不默认勾选,让数据主体勾选“我同意以上述方式处理我的个人数据”,或提供“我同意”的按钮让用户主动点击。 - - 以书面的方式明确表达同意,数据主体在书面陈述上签字。 - - 要求数据主体在系统中上传带有其签名的电子表格。 - - 采取双重验证的方式,要求数据主体邮件形式回复同意后,再次点击用于验证的邮件链接或是输入SMS验证码。 - - 用户主动输入的场景,例如用户主动输入身份证和银行卡号绑卡等场景。 - - -## 数据分类分级 - -基于数据保护目标及风险后果,即数据遭到泄露或者遭到破坏带来的法律风险对个人、组织或公众的影响对数据进行定级,分为极高、高、中、低、公开五个数据级别。 - -**表1** 数据分类分级标准 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

数据级别

-

隐私风险

-

隐私属性

-

典型示例

-

极高级

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来灾难性负面影响。

-

敏感个人数据

-

DNA、种族、宗教信仰、性取向;生物识别信息;原始通信内容;银行卡密码、磁道数据。

-

高级别

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来严重负面影响。

-

敏感个人数据

-

权威社会标识(身份证、护照等);网页浏览记录;轨迹信息;云空间上传的内容数据(图库/音频/视频等)。

-

中级别

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来重大负面影响。

-

一般个人数据

-

设备标识(IMEI, SN, OAID )、用户标识(user ID);个人基本信息(姓名,地址);手机号、邮箱等。

-

低级别

-

数据一旦识别或关联到特定个人或群体,其泄露或不当使用可能会给个人带来有限负面影响。

-

一般个人数据

-

操作系统设置信息(操作系统版本,国家/地区等);设备硬件信息(设备型号,屏幕尺寸,屏幕分辨率等);网络信息(网络连接状态,接入网络信息);设备状态(登录设备时间/时长)。

-

公开(无风险)

-

对个人或组织无不利影响的可公开数据

-

非个人数据

-

公开发布的产品介绍,公开的会议信息,外部开源的代码等。

-
- -备注:隐私保护和数据分类分级的相关定义参照GDPR中的相关内容。 - -## 通用隐私设计规则 - -为了指导厂商完成产品的隐私设计工作,我们整理了以下通用的隐私设计要求,作为OpenHarmony设备厂商产品隐私设计的指南和参考。 - -**数据收集及使用公开透明** - -采集个人数据时,应清晰、明确地告知用户,并确保告知用户的个人信息将被如何使用。 - -- 针对不同等级的个人数据需要制定针对性的隐私处理策略。 - - 敏感个人数据的采集需要获取数据主体明示同意。 - - 一般个人数据的采集需要数据主体同意或基于其他合法授权。 - - 非个人数据与中、高或极高级别个人数据关联采集,需要数据主体同意或其他合法授权,并在隐私声明中呈现。 - -- 应制定并遵从适当的隐私政策。在收集、使用留存和第三方分享用户个人数据时需要符合所有适用法律、政策和规定。如在收集个人数据前,需充分告知用户处理个人数据的种类、目的、处理方式、保留期限等,满足数据主体权利相关要求。 - - 根据以上要求,我们设计了正确示例以供参考。隐私通知/声明的参考示例如下: - - **图 1** 隐私通知/声明示例图 - - - ![](figures/2-应用启动预授权.png) ![](figures/3-应用隐私声明.png) - -- 个人数据应当基于具体、明确、合法的目的收集,不应与此目的不相符的方式作进一步处理。对于收集目的变更和用户撤销同意后再次重新使用的场景都需要用户重新同意。隐私声明变更和撤销的示例如下图: - - **图 2** 隐私通知/声明变更示例图 - - - ![](figures/4-隐私声明变更通知.png) - - **图 3** 撤销同意示例图 - - - ![](figures/6-1-隐私声明撤销.png) ![](figures/6-2-隐私声明撤销.png) - -- 需要提供用户查看隐私声明的入口。例如,可以在应用的“关于”界面提供查看隐私声明的入口,如示例图所示: - - **图 4** 隐私声明查看界面示例图 - - - ![](figures/5-应用隐私声明入口.png) - - -**数据收集及使用最小化** - -个人数据收集应与数据处理目的相关,且是适当、必要的。开发者应尽可能对个人数据进行匿名化或假名化处理,降低对数据主体的风险。仅可收集和处理与特定目的相关且必需的个人数据,不能进行与特定目的不相关的进一步处理。 - -- 敏感权限申请的时候要满足权限最小化的要求,在申请权限时,只申请获取必需的信息或资源所需要的权限。如应用不需要相机权限就能够实现其功能时,则不应该向用户申请相机权限。 -- 数据收集最小化:针对数据的收集要满足最小化要求,不收集与产品提供服务无关联的数据。如提供定位服务的产品,不应收集用户的网页浏览记录。 -- 数据使用的功能要求能够使用户受益,收集的数据不能用于一些与用户正常使用无关的功能。数据收集不能有其他与用户正常使用无关的功能存在。如不得将“生物特征”、“健康数据”等敏感个人数据用于服务改进、投放广告或营销等非业务核心功能。 -- 禁止在日志中打印敏感个人数据,如需要打印一般个人数据时,应对个人数据进行匿名化或假名化处理; - - 优先使用可以重置的标识符,如系统提供了NetworkID和DVID作为分布式场景下的设备标识符,广告业务场景下则建议使用[OAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/oaid-0000001050783198),基于应用的分析则建议使用[ODID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/odid-0000001051063255)和[AAID](https://developer.huawei.com/consumer/cn/doc/development/HMSCore-Guides/aaid-0000001051142988),其他需要唯一标识符的场景可以使用UUID接口生成;可重置的标识符不能满足业务需求时,才选择序列号和MAC地址等永久性标识符。 - - -**数据处理选择和控制** - -对个人数据处理必须要征得用户的同意或遵守其他适用的法律法规,用户对其个人数据要有充分的控制权。 - -- 获取用户敏感权限的授权:产品弹窗提醒,向用户呈现需要获取的权限和权限使用目的,用户可通过选择决定是否进行授权及指定授权的方式,让用户对产品权限的授予和个人数据使用做到透明、可知、可控。如下图所示: - - **图 5** 敏感权限提示框示例图 - - - ![](figures/1-敏感权限弹窗.png) - -- 用户可以修改、取消授予的权限:当用户不同意某一权限或者数据收集时,应当允许用户使用与这部分权限和数据收集不相关的功能。如智慧屏产品上通信社交应用,用户可以拒绝授予相机权限,不应该影响与相机无关的功能操作,如语音通话。 -- 用户在产品使用过程中,针对录入个人数据的场景,需要给用户提供对个人数据的增加、删除、修改、查看的操作。 -- 需要给出硬件回收或返厂进行安全删除个人数据的机制或方法。 -- 对用户系统软件、应用软件的下载或升级,涉及修改用户隐私空间,用户对于这类行为需要有知情权和控制权,必须给用户提示,并提供给用户同意和取消的选项。 - -**数据安全** - -从技术上保证数据处理活动的安全性,包括个人数据的加密存储、安全传输等安全机制,系统应默认开启或采取安全保护措施。 - -- 对于个人数据的访问需要有保护机制,主要包括身份认证和访问控制。身份认证(如用户名、密码)限定只有经过认证的用户才能访问数据,可应用于多用户场景;访问控制(如[权限控制](安全指南.md#li201725506375))可应用于对应用程序的限制。 -- 分布式设备个人数据安全存储要满足密钥管理和存储服务(HUKS:Huawei Universal Keystore)的要求,包括:密钥安全存储、数据安全存储。 -- 个人数据在分布式设备间传输要满足设备间的信任绑定关系和数据传输通道的安全性要求。详细信息可以参考[设备互联安全](安全指南.md#section26153183616)。 -- 认证凭证数据(密码、口令、指纹等)须加密存储。 - -**本地化处理** - -用户数据优先在本设备进行处理,对于本设备无法处理的数据应尽可能在超级终端设备本地进行数据的处理,如果超级终端本地处理无法满足业务目的的,在数据离开超级终端设备本地时应尽可能选择匿名化。 - -**未成年人数据保护要求** - -产品专门给未成年人设计的,或者产品收集用户年龄从而可以识别到是在收集未成年人的个人数据,需结合目标市场国家的法律,专门分析未成年人个人数据保护的问题,收集未成年人数据前需要征得监护人的同意。 - -## 特殊品类要求 - -针对消费者硬件产品来说,除了满足以上的通用隐私要求以外,针对特殊品类的产品还有以下的特殊要求,在产品设计过程中参照执行。 - -**表2** 特殊品类隐私要求 - - - - - - - - - - - - - - - - - - - - - - - - - -

产品品类

-

隐私保护特殊要求

-

智能家居

-

安防类产品涉及的指纹、声纹、面部识别、虹膜等个人生物识别信息以及用户密码信息,属于敏感个人数据,应采用技术措施处理后(例如提取个人生物识别信息的摘要)再进行加密保存在产品本地。

-

智能家居

-

安防类产品涉及的音视频和图片,设备厂家作为数据控制者时,必须提供独立的隐私通知、应用界面必须有设备厂家品牌标识;音视频数据的传输和存储必须加密,非用户本人访问安防产品的音视频数据,必须获得用户授权。

-

智能家居/影音娱乐

-

带有摄像头的产品建议提供物理上可关闭功能,通过隐藏、遮盖、转向让消费者感知摄像头处于关闭状态。

-

智能家居/影音娱乐

-

带有麦克风的产品建议提供显性显示录音的状态,如录音开启时状态灯闪烁,录音关闭时状态灯熄灭。

-

移动办公

-

用户数据跨设备显示、传输等场景需要获得消费者的明示同意,给予消费者对其个人数据有充分的控制权。

-

车机

-

1、隐私通知及权限设置

-

避免在驾驶态让用户阅读隐私政策和权限设置。

-

车机应用需要考虑车辆使用时的安全性,应避免让用户在驾驶过程中进行复杂的权限设置或阅读隐私政策,比如HiCar应用应该在手机端完成应用基本权限设置和隐私政策阅读后再进行使用。

-

隐私声明在确认用户身份后告知。

-

车辆的数据会涉及车主、驾驶员和乘客,应保证隐私声明通知到了数据主体本人。建议做法是在确认使用者的身份后进行隐私声明,如需要用户登录的应用,应在账号登录后弹出隐私声明而不是账号登录之前。

-

2、共享应用个人数据保护

-

共享应用在车机重启后应退出,并对当前用户个人数据进行清除或加密,应用还应提供对历史数据进行彻底删除的功能。

-

3、消息提示

-

考虑车机的开放环境,应用在车机上进行消息提醒时,应避免直接将消息内容显示在车机上,正确的做法是仅提示有新的消息需要查看。

-
- diff --git "a/zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" deleted file mode 100755 index b0e0db564441d0635b30ef90c3369a163823e0f3..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/AI\345\274\225\346\223\216\346\241\206\346\236\266\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ /dev/null @@ -1,9 +0,0 @@ -# AI引擎框架开发指南 - -AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。AI业务子系统提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,完成对AI算法能力的生命周期管理和按需部署。插件管理主要实现插件的生命周期管理及插件的按需部署,快速集成AI能力插件;模块管理主要实现任务的调度及管理客户端的实例;通信管理主要实现客户端和服务端之间的跨进程通信及引擎与插件之间的数据传输。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。AI引擎框架如下[图1](#fig143186187187)所示。 - -**图 1** AI引擎框架 - - -![](figures/zh-cn_image_0000001077727032.png) - diff --git "a/zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" "b/zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" deleted file mode 100755 index c4310aa764280d27ea890292596524653beb731e..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/AI\346\241\206\346\236\266.md" +++ /dev/null @@ -1,13 +0,0 @@ -# AI框架 - -- **[AI引擎框架开发指南](AI引擎框架开发指南.md)** - -- **[搭建环境](搭建环境.md)** - -- **[技术规范](技术规范.md)** - -- **[开发指导](开发指导.md)** - -- **[开发示例](开发示例.md)** - - diff --git a/zh-cn/device-dev/subsystems/DFX.md b/zh-cn/device-dev/subsystems/DFX.md deleted file mode 100755 index e5f00a7203adb883c359ee2b11eb1b56c60d7173..0000000000000000000000000000000000000000 --- a/zh-cn/device-dev/subsystems/DFX.md +++ /dev/null @@ -1,11 +0,0 @@ -# DFX - -- **[DFX概述](DFX概述.md)** - -- **[HiLog开发指导](HiLog开发指导.md)** - -- **[HiLog\_Lite开发指导](HiLog_Lite开发指导.md)** - -- **[HiSysEvent开发指导](HiSysEvent开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" "b/zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" deleted file mode 100755 index 0423c0b61223ca02bac79eeb499b659bc03b1b36..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/OTA\345\215\207\347\272\247.md" +++ /dev/null @@ -1,358 +0,0 @@ -# OTA升级 - -- [约束与限制](#section691733275418) -- [生成公私钥对](#section94411533155010) -- [生成升级包](#section632383718539) -- [上传升级包](#section5772112473213) -- [下载升级包](#section251732474917) -- [厂商应用集成OTA能力](#section298217330534) -- [API应用场景-默认场景](#section7685171192916) - - [开发指导](#section0745926153017) - - [示例代码](#section1337111363306) - -- [API应用场景-定制场景](#section1686395317306) - - [开发指导](#section524515314317) - - [示例代码](#section525974743120) - -- [系统升级](#section151997114334) - -OTA(Over the Air)提供对设备远程升级的能力,可以让您的设备(如IP摄像头等),轻松支持远程升级能力。目前仅支持全量包升级,暂不支持差分包升级。全量包升级是将新系统全部内容做成升级包,进行升级;差分包升级是将新老系统的差异内容做成升级包,进行升级。 - -## 约束与限制 - -- 支持基于Hi3861/Hi3518EV300/Hi3516DV300芯片的开源套件。 -- 对Hi3518EV300/Hi3516DV300开源套件,设备需要支持SD卡(VFAT格式)。 - -## 生成公私钥对 - -1. 准备工作:在Windows PC 上,下载安装OpenSSL工具,并配置环境变量。OpenSSL下载路径: - - [http://slproweb.com/products/Win32OpenSSL.html](http://slproweb.com/products/Win32OpenSSL.html) - -2. 在tools\\update\_tools\\update\_pkg\_tools目录下,下载升级包制作工具,保存到Windows本地路径,例如D:\\ota\_tools。 -3. 如图,运行ota\_tools\\key下的Generate\_public\_private\_key.bat ,生成公钥Metis\_PUBLIC.key、私钥private.key和公钥对应的数组public\_arr.txt文件,请妥善保管私钥private.key。 - - **图 1** 生成公私钥对 - - - ![](figures/zh-cn_image_0000001060200050.png) - -4. 用public\_arr.txt里面的全部内容替换OTA模块base\\update\\ota\_lite\\frameworks\\source\\verify\\hota\_verify.c中的g\_pubKeyBuf 。 - - 示例,public\_arr.txt内容 - - ``` - 0x30,0x82,0x1,0xa,0x2,0x82,0x1,0x1,0x0,0xc7,0x8c,0xf3,0x91,0xa1,0x98,0xbf,0xb1,0x8c, - 0xbe,0x22,0xde,0x32,0xb2,0xfa,0xec,0x2c,0x69,0xf6,0x8f,0x43,0xa7,0xb7,0x6f,0x1e,0x4a,0x97, - 0x4b,0x27,0x5d,0x56,0x33,0x9a,0x73,0x4e,0x7c,0xf8,0xfd,0x1a,0xf0,0xe4,0x50,0xda,0x2b,0x8, - 0x74,0xe6,0x28,0xcc,0xc8,0x22,0x1,0xa8,0x14,0x9,0x46,0x46,0x6a,0x10,0xcd,0x39,0xd,0xf3, - 0x4a,0x7f,0x1,0x63,0x21,0x33,0x74,0xc6,0x4a,0xeb,0x68,0x40,0x55,0x3,0x80,0x1d,0xd9,0xbc, - 0xd4,0xb0,0x4a,0x84,0xb7,0xac,0x43,0x1d,0x76,0x3a,0x61,0x40,0x23,0x3,0x88,0xcc,0x80,0xe, - 0x75,0x10,0xe4,0xad,0xac,0xb6,0x4c,0x90,0x8,0x17,0x26,0x21,0xff,0xbe,0x1,0x82,0x16,0x76, - 0x9a,0x1c,0xee,0x8e,0xd9,0xb0,0xea,0xd5,0x50,0x61,0xcc,0x9c,0x2e,0x78,0x15,0x2d,0x1f,0x8b, - 0x94,0x77,0x30,0x39,0x70,0xcf,0x16,0x22,0x82,0x99,0x7c,0xe2,0x55,0x37,0xd4,0x76,0x9e,0x4b, - 0xfe,0x48,0x26,0xc,0xff,0xd9,0x59,0x6f,0x77,0xc6,0x92,0xdd,0xce,0x23,0x68,0x83,0xbd,0xd4, - 0xeb,0x5,0x1b,0x2a,0x7e,0xda,0x9a,0x59,0x93,0x41,0x7b,0x4d,0xef,0x19,0x89,0x4,0x8d,0x5, - 0x7d,0xbc,0x3,0x1f,0x77,0xe6,0x3d,0xa5,0x32,0xf5,0x4,0xb7,0x9c,0xe9,0xfa,0x6e,0xc,0x9f, - 0x4,0x62,0xfe,0x2a,0x5f,0xbf,0xeb,0x9a,0x73,0xa8,0x2a,0x72,0xe3,0xf0,0x57,0x56,0x5c,0x59, - 0x14,0xdd,0x79,0x11,0x42,0x3a,0x48,0xf7,0xe8,0x80,0xb1,0xaf,0x1c,0x40,0xa2,0xc6,0xec,0xf5, - 0x67,0xc1,0x88,0xf6,0x26,0x5c,0xd3,0x11,0x5,0x11,0xed,0xb1,0x45,0x2,0x3,0x1,0x0,0x1, - ``` - - 示例,OTA模块的公钥 - - ``` - #define PUBKEY_LENGTH 270 - - static uint8 g_pubKeyBuf[PUBKEY_LENGTH] = { - 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, - 0x63, 0x07, 0x84, 0xCF, 0x37, 0xF0, 0x45, 0xE8, 0xB9, 0x6E, 0xEF, 0x04, 0x88, 0xD3, 0x43, 0x06, - ``` - -5. 对Hi3518EV300/Hi3516DV300套件,在上一步的基础上,还需用public\_arr.txt里面的全部内容替换uboot模块device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\verify\\update\_public\_key.c中的g\_pub\_key中的全部内容。 - - 示例,uboot模块的公钥 - - ``` - static unsigned char g_pub_key[PUBKEY_LEN] = { - 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, - 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, - ``` - - -## 生成升级包 - -1. 在ota\_tools\\Components目录下,归放需要升级的文件。 - - **图 2** 原始镜像归放位置 - - - ![](figures/zh-cn_image_0000001061889268.png) - - **表 1** 升级包内的文件 - - - - - - - - - - - - - - - - - - - - - - -

包内文件名

-

说明

-

u-boot.bin

-

将编译生成的u-boot-hi351XevX00.bin文件重命名后得到。

-

kernel.bin

-

将编译生成的liteos.bin/kernel文件重命名后得到。

-

rootfs.img

-

将编译生成的rootfs_xxxxx.img文件重命名后得到。

-

config

-

与开发板类型和内核类型相关,参考开源套件的SD卡烧写说明。

-

OTA.tag

-

共32字节,内容为:“package_type:otaA1S2D3F4G5H6J7K8”;其中后16字节为随机数,需要随版本变化。

-
- -2. 修改ota\_tools\\xml下的packet\_harmony.xml文件,配置compAddr分区名,对应ota\_tools\\Components\\的文件,其它项不需修改,作为扩展项预留。 - - 示例,配置组件信息 - - ``` - - - .\Components\rootfs_jffs2.img - .\Components\liteos.bin - .\Components\userfs_jffs2.img - - ``` - -3. 将生成的公私钥路径配置到ota\_tools\\xml路径下的packet\_harmony.xml中。 - - 示例,配置公私钥路径 - - ``` - - .\key\private.key - .\key\Metis_PUBLIC.key - - ``` - -4. 在ota\_tools\\VersionDefine.bat中设置产品名称、软件版本号(用于防回滚校验)。 - - 示例,配置产品名称和版本号 - - ``` - set FILE_PRODUCT_NAME=Hisi - - @rem 设置软件版本号 不要超过16位 - set SOFTWARE_VER=OpenHarmony 1.1 - ``` - -5. 执行ota\_tools下的Make\_Harmony\_PKG.bat,生成升级包Hisi\_OpenHarmony 1.1.bin。升级包通过SHA256+RSA2048方式签名,保证完整性和合法性。 - - **图 3** 升级包制作工具 - - - ![](figures/zh-cn_image_0000001059334449.png) - - -## 上传升级包 - -将升级包Hisi\_OpenHarmony 1.1.bin上传到厂商的OTA服务器。 - -## 下载升级包 - -1. 厂商应用从OTA服务器下载Hisi\_OpenHarmony 1.1.bin。 -2. 对Hi3518EV300/Hi3516DV300开源套件,需要插入SD卡\(容量\>100MBytes\)。 - -## 厂商应用集成OTA能力 - -- 调用OTA模块的动态库libhota.so,对应头文件位于:base\\update\\ota\_lite\\interfaces\\kits\\hota\_partition.h&hota\_updater.h; -- libhota.so对应的源码路径为base\\update\\ota\_lite\\frameworks\\source。 -- API的使用方法,见本文“API应用场景”和API文档的OTA接口章节。 -- 如果需要适配开发板,请参考HAL层头文件:base\\update\\ota\_lite\\hals\\hal\_hota\_board.h。 - -## API应用场景-默认场景 - -升级包是按照上文“生成公私钥对”和“生成升级包”章节制作的。 - -### **开发指导** - -1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化OTA模块。 -2. 调用HotaWrite接口传入升级包数据流,接口内部实现校验、解析及写入升级数据流。 -3. 写入完成后,调用HotaRestart接口重启系统。 - - 升级过程中,使用HotaCancel接口可以取消升级。 - - -### **示例代码** - -使用OpenHarmony的“升级包格式和校验方法“进行升级。 - -``` -int main(int argc, char **argv) -{ - printf("this is update print!\r\n"); - if (HotaInit(NULL, NULL) < 0) { - printf("ota update init fail!\r\n"); - return -1; - } - int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); - if (fd < 0) { - printf("file open failed, fd = %d\r\n", fd); - (void)HotaCancel(); - return -1; - } - int offset = 0; - int fileLen = lseek(fd, 0, SEEK_END); - int leftLen = fileLen; - while (leftLen > 0) { - if (lseek(fd, offset, SEEK_SET) < 0) { - close(fd); - printf("lseek fail!\r\n"); - (void)HotaCancel(); - return -1; - } - int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; - (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); - if (read(fd, g_readBuf, tmpLen) < 0) { - close(fd); - printf("read fail!\r\n"); - (void)HotaCancel(); - return -1; - } - if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { - printf("ota write fail!\r\n"); - close(fd); - (void)HotaCancel(); - return -1; - } - offset += READ_BUF_LEN; - leftLen -= tmpLen; - } - close(fd); - printf("ota write finish!\r\n"); - printf("device will reboot in 10s...\r\n"); - sleep(10); - (void)HotaRestart(); - return 0; -} -``` - -## API应用场景-定制场景 - -升级包不是按照上文“生成公私钥对”和“生成升级包”章节制作的,是通过其它方式制作的。 - -### **开发指导** - -1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化。 -2. 使用HotaSetPackageType接口设置NOT\_USE\_DEFAULT\_PKG,使用"定制"流程。 -3. 调用HotaWrite接口传入升级包数据流,写入设备。 -4. 写入完成后,调用HotaRead接口读取数据,厂商可以自行校验升级包。 -5. 调用HotaSetBootSettings设置启动标记,在重启后需要进入uboot模式时使用(可选)。 -6. 调用HotaRestart接口,进行重启。 - - 升级过程中,使用HotaCancel接口可以取消升级。 - - -### **示例代码** - -使用非OpenHarmony的“升级包格式和校验方法“进行升级。 - -``` -int main(int argc, char **argv) -{ - printf("this is update print!\r\n"); - if (HotaInit(NULL, NULL) < 0) { - printf("ota update init fail!\r\n"); - (void)HotaCancel(); - return -1; - } - (void)HotaSetPackageType(NOT_USE_DEFAULT_PKG); - int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); - if (fd < 0) { - printf("file open failed, fd = %d\r\n", fd); - (void)HotaCancel(); - return -1; - } - int offset = 0; - int fileLen = lseek(fd, 0, SEEK_END); - int leftLen = fileLen; - while (leftLen > 0) { - if (lseek(fd, offset, SEEK_SET) < 0) { - close(fd); - printf("lseek fail!\r\n"); - (void)HotaCancel(); - return -1; - } - int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; - (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); - if (read(fd, g_readBuf, tmpLen) < 0) { - close(fd); - printf("read fail!\r\n"); - (void)HotaCancel(); - return -1; - } - if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { - printf("ota write fail!\r\n"); - close(fd); - (void)HotaCancel(); - return -1; - } - offset += READ_BUF_LEN; - leftLen -= tmpLen; - } - close(fd); - printf("ota write finish!\r\n"); - leftLen = fileLen; - while (leftLen > 0) { - int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; - (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); - if (HotaRead(offset, READ_BUF_LEN, (unsigned char *)g_readBuf) != 0) {} - printf("ota write fail!\r\n"); - (void)HotaCancel(); - return -1; - } - /* do your verify and parse */ - offset += READ_BUF_LEN; - leftLen -= tmpLen; - } - /* set your boot settings */ - (void)HotaSetBootSettings(); - printf("device will reboot in 10s...\r\n"); - sleep(10); - (void)HotaRestart(); - return 0; -} -``` - -## 系统升级 - -厂商应用调用OTA模块的API,OTA模块执行升级包的签名验证、版本防回滚、烧写落盘功能,升级完成后自动重启系统。 - -对Hi3518EV300/Hi3516DV300开源套件,在需要实现防回滚功能的版本中,需要增加LOCAL\_VERSION的值,如"ohos default 1.0"-\>"ohos default 1.1",LOCAL\_VERSION在device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\ota\_update\\ota\_local\_info.c中。 - -示例,增加版本号 - -``` -const char *get_local_version(void) -{ -#if defined(CONFIG_TARGET_HI3516EV200) || \ - defined(CONFIG_TARGET_HI3516DV300) || \ - defined(CONFIG_TARGET_HI3518EV300) -#define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */ -``` - diff --git a/zh-cn/device-dev/subsystems/Readme-CN.md b/zh-cn/device-dev/subsystems/Readme-CN.md index 3032d57b57d4c11908aae5e450f92382b11bd886..7dc0b03cfae21dca2abce92f1b9b354f960e952f 100755 --- a/zh-cn/device-dev/subsystems/Readme-CN.md +++ b/zh-cn/device-dev/subsystems/Readme-CN.md @@ -1,96 +1,78 @@ -# 子系统 - -- [编译构建](编译构建.md) - - [轻量和小型系统编译构建指导](轻量和小型系统编译构建指导.md) - - [编译构建概述](编译构建概述.md) - - [编译构建使用指导](编译构建使用指导.md) - - [编译构建常见问题](编译构建常见问题.md) - - - [标准系统编译构建指导](标准系统编译构建指导.md) - - [编译构建概述](编译构建概述-0.md) - - [编译构建使用指导](编译构建使用指导-1.md) - -- [分布式远程启动](分布式远程启动.md) -- [图形图像](图形图像.md) - - [图形图像概述](图形图像概述.md) - - [容器类组件开发指导](容器类组件开发指导.md) - - [布局容器类组件开发指导](布局容器类组件开发指导.md) - - [普通组件开发指导](普通组件开发指导.md) - - [动画开发指导](动画开发指导.md) - -- [媒体](媒体.md) - - [相机](相机.md) - - [相机开发概述](相机开发概述.md) - - [拍照开发指导](拍照开发指导.md) - - [录像开发指导](录像开发指导.md) - - [预览开发指导](预览开发指导.md) - - - [音视频](音视频.md) - - [音视频开发概述](音视频开发概述.md) - - [音视频播放开发指导](音视频播放开发指导.md) - - [音视频录制开发指导](音视频录制开发指导.md) - -- [公共基础](公共基础.md) - - [公共基础库概述](公共基础库概述.md) - - [公共基础库开发指导](公共基础库开发指导.md) - - [公共基础库常见问题](公共基础库常见问题.md) - -- [AI框架](AI框架.md) - - [AI引擎框架开发指南](AI引擎框架开发指南.md) - - [搭建环境](搭建环境.md) - - [技术规范](技术规范.md) - - [代码管理规范](代码管理规范.md) - - [命名规范](命名规范.md) - - [接口开发规范](接口开发规范.md) - - - [开发指导](开发指导.md) - - [SDK开发过程](SDK开发过程.md) - - [插件的开发过程](插件的开发过程.md) - - [配置文件的开发过程](配置文件的开发过程.md) - - - [开发示例](开发示例.md) - - [唤醒词识别SDK的开发示例](唤醒词识别SDK的开发示例.md) - - [唤醒词识别插件的开发示例](唤醒词识别插件的开发示例.md) - - [唤醒词识别配置文件的开发示例](唤醒词识别配置文件的开发示例.md) - -- [Sensor服务](Sensor服务.md) - - [Sensor服务子系概述](Sensor服务子系概述.md) - - [Sensor服务子系使用指导](Sensor服务子系使用指导.md) - - [Sensor服务子系使用实例](Sensor服务子系使用实例.md) - -- [用户程序框架](用户程序框架.md) - - [概述](概述.md) - - [搭建环境](搭建环境-2.md) - - [开发指导](开发指导-3.md) - - [开发实例](开发实例.md) - -- [OTA升级](OTA升级.md) - -- [安全](安全.md) - - [概述](概述-7.md) - - [应用验签开发指导](应用验签开发指导.md) - - [应用权限管理开发指导](应用权限管理开发指导.md) - - [IPC通信鉴权开发指导](IPC通信鉴权开发指导.md) - -- [启动恢复](启动恢复.md) - - [启动恢复子系统概述](启动恢复子系统概述.md) - - [init启动引导组件](init启动引导组件.md) - - [appspawn应用孵化组件](appspawn应用孵化组件.md) - - [bootstrap服务启动组件](bootstrap服务启动组件.md) - - [syspara系统属性组件](syspara系统属性组件.md) - - [常见问题](常见问题.md) - - [参考](参考.md) - -- [测试](测试.md) -- [DFX](DFX.md) - - [DFX概述](DFX概述.md) - - [HiLog开发指导](HiLog开发指导.md) - - [HiLog\_Lite开发指导](HiLog_Lite开发指导.md) - - [HiSysEvent开发指导](HiSysEvent开发指导.md) - -- [研发工具链](研发工具链.md) - - [bytrace使用指导](bytrace使用指导.md) - - [hdc\_std 使用指导](hdc_std-使用指导.md) - -- [XTS认证子系统开发指南](XTS认证子系统开发指南.md) +# 子系统开发指南 + +- [编译构建](subsys-build.md) + - [轻量和小型系统编译构建指导](subsys-build-mini-lite.md) + - [标准系统编译构建指导](subsys-build-standard-large.md) +- [分布式远程启动](subsys-remote-start.md) +- [图形图像](subsys-graphics.md) + - [图形图像概述](subsys-graphics-overview.md) + - [容器类组件开发指导](subsys-graphics-bundle-guide1.md) + - [布局容器类组件开发指导](subsys-graphics-bundle-guide2.md) + - [普通组件开发指导](subsys-graphics-bundle-guide3.md) + - [动画开发指导](subsys-graphics-animation-guide.md) +- [媒体](subsys-multimedia.md) + - [相机](subsys-multimedia-camera.md) + - [相机开发概述](subsys-multimedia-camera-overview.md) + - [拍照开发指导](subsys-multimedia-camera-photo-guide.md) + - [录像开发指导](subsys-multimedia-camera-record-guide.md) + - [预览开发指导](subsys-multimedia-camera-preview-guide.md) + + - [音视频](subsys-multimedia-video.md) + - [音视频开发概述](subsys-multimedia-video-overview.md) + - [音视频播放开发指导](subsys-multimedia-video-play-guide.md) + - [音视频录制开发指导](subsys-multimedia-video-record-guide.md) +- [公共基础](subsys-utils.md) + - [公共基础库概述](subsys-utils-overview.md) + - [公共基础库开发指导](subsys-utils-guide.md) + - [公共基础库常见问题](subsys-utils-faqs.md) +- [AI框架](subsys-aiframework.md) + - [AI引擎框架开发指南](subsys-aiframework-guide.md) + - [搭建环境](subsys-aiframework-envbuild.md) + - [技术规范](subsys-aiframework-tech.md) + - [代码管理规范](subsys-aiframework-tech-codemanage.md) + - [命名规范](subsys-aiframework-tech-name.md) + - [接口开发规范](subsys-aiframework-tech-interface.md) + + - [开发指导](subsys-aiframework-devguide.md) + - [SDK开发过程](subsys-aiframework-devguide-sdk.md) + - [插件的开发过程](subsys-aiframework-devguide-plugin.md) + - [配置文件的开发过程](subsys-aiframework-devguide-conf.md) + + - [开发示例](subsys-aiframework-demo.md) + - [唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md) + - [唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md) + - [唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md) +- [Sensor服务](subsys-densor.md) + - [Sensor服务子系概述](subsys-densor-overview.md) + - [Sensor服务子系使用指导](subsys-densor-guide.md) + - [Sensor服务子系使用实例](subsys-densor-demo.md) +- [用户程序框架](subsys-application-framework.md) + - [概述](subsys-application-framework-overview.md) + - [搭建环境](subsys-application-framework-builden.md) + - [开发指导](subsys-application-framework-guide.md) + - [开发实例](subsys-application-framework-demo.md) +- [OTA升级](subsys-ota-guide.md) +- [安全](subsys-security.md) + - [概述](subsys-security-overview.md) + - [应用验签开发指导](subsys-security-sigverify.md) + - [应用权限管理开发指导](subsys-security-rightmanagement.md) + - [IPC通信鉴权开发指导](subsys-security-communicationverify.md) +- [启动恢复](subsys-boot.md) + - [启动恢复子系统概述](subsys-boot-overview.md) + - [init启动引导组件](subsys-boot-init.md) + - [appspawn应用孵化组件](subsys-boot-appspawn.md) + - [bootstrap服务启动组件](subsys-boot-bootstrap.md) + - [syspara系统属性组件](subsys-boot-syspara.md) + - [常见问题](subsys-boot-faqs.md) + - [参考](subsys-boot-ref.md) +- [测试](subsys-testguide-test.md) +- [DFX](subsys-dfx.md) + - [DFX概述](subsys-dfx-overview.md) + - [HiLog开发指导](subsys-dfx-hilog-rich.md) + - [HiLog\_Lite开发指导](subsys-dfx-hilog-lite.md) + - [HiSysEvent开发指导](subsys-dfx-hisysevent.md) +- [研发工具链](subsys-toolchain.md) + - [bytrace使用指导](subsys-toolchain-bytrace-guide.md) + - [hdc\_std 使用指导](subsys-toolchain-hdc-guide.md) +- [XTS认证子系统开发指南](subsys-xts-guide.md) diff --git "a/zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" "b/zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" deleted file mode 100755 index 83d933cdb5df36058c1726de5d289c88a9fb2fbb..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/SDK\345\274\200\345\217\221\350\277\207\347\250\213.md" +++ /dev/null @@ -1,162 +0,0 @@ -# SDK开发过程 - -SDK头文件的功能实现是基于对SDK的调用映射到对client的调用。Client端提供的接口如下[表1](#table203963834718)所示。 - -**表 1** Client端提供的接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

接口说明

-

参数要求

-

int AieClientInit(const ConfigInfo &configInfo, ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, IServiceDeadCb *cb)

-

作用:链接并初始化引擎服务,激活跨进程调用。

-

返回值:0为成功,其他返回值失败。

-

configInfo(NOT NULL):引擎相关初始化配置数据;

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

cb(可为NULL):死亡回调 对象;

-

int AieClientPrepare(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo, IClientCb *cb)

-

作用:加载算法插件。

-

返回值: 0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

inputInfo(可为NULL):加载算法插件时输入所需信息;

-

outputInfo(可为NULL):加载算法插件之后如需返回信息则通过此出参返回;

-

cb:异步算法通过此回调返回运算结果,因此异步算法此结构体不能为空;若为同步算法,传入空值即可;

-

int AieClientAsyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

-

作用:执行异步算法。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

inputInfo(可为NULL):算法运算入参;

-

int AieClientSyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo)

-

作用:执行同步算法。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):调用算法信息;

-

inputInfo(可为NULL):算法运算入参;

-

outputInfo(可为NULL):同步算法运算结果出参;

-

int AieClientRelease(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

-

作用:卸载算法插件。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

algorithmInfo(NOT NULL):卸载算法插件的相关信息;

-

inputInfo(可为NULL):调用卸载接口时的输入信息;

-

int AieClientDestroy(ClientInfo &clientInfo)

-

作用:断开与服务端的链接,释放相关缓存。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):所要销毁的引擎客户端信息;

-

int AieClientSetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)

-

作用:设置配置项,可将一些算法的拓展信息通过此接口传入插件。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

optionType (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;

-

inputInfo(可为NULL):插件可根据需要通过此入参设置算法参数信息;

-

int AieClientGetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo, DataInfo &outputInfo)

-

作用:给定特定的optionType和inputInfo,获取其对应的配置项信息。

-

返回值:0为成功,其他返回值失败。

-

clientInfo(NOT NULL):引擎客户端信息;

-

optionType(NOT NULL):所获取配置项信息的对应算法状态位;

-

inputInfo(可为NULL):所获取配置项信息的对应算法参数信息;

-

outputInfo(可为NULL):所要获取的配置项信息返回结果;

-
- -其中,ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构如下[表2](#table22154317482)所示。 - -**表 2** ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构 - - - - - - - - - - - - - - - - - - - - - - - - -

结构体名称

-

说明

-

属性

-

ConfigInfo

-

算法配置项信息。

-

const char *description:配置项信息主体;

-

ClientInfo

-

客户端信息。

-

long long clientVersion:客户端设备版本号(当前还未启用);

-

int clientId:客户端ID;

-

int sessionId:会话ID;

-

uid_t serverUid:server端UID;

-

uid_t clientUid:client端UID;

-

int extendLen:拓展信息(extendMsg)长度;

-

unsigned char *extendMsg:拓展信息主体;

-

AlgorithmInfo

-

算法信息。

-

long long clientVersion:客户端设备版本号(当前还未启用);

-

bool isAsync:是否为异步执行;

-

int algorithmType:引擎框架根据插件加载顺序分配的算法类型ID;

-

long long algorithmVersion:算法版本号;

-

bool isCloud:是否上云(当前还未启用);

-

int operateId:执行ID(当前还未启用);

-

int requestId:请求ID,标识每次request,以对应执行结果;

-

int extendLen:拓展信息(extendMsg)长度;

-

unsigned char *extendMsg:拓展信息主体;

-

DataInfo

-

算法数据入参(inputInfo)、接口调用结果出参(outputInfo)。

-

unsigned char *data:数据主体;

-

int length:数据(data)长度;

-
- -具体开发过程可参考唤醒词识别SDK开发示例。 - diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" "b/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" deleted file mode 100755 index 35dd6eab91788b22712d1b005b27b182a8333da0..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241.md" +++ /dev/null @@ -1,9 +0,0 @@ -# Sensor服务 - -- **[Sensor服务子系概述](Sensor服务子系概述.md)** - -- **[Sensor服务子系使用指导](Sensor服务子系使用指导.md)** - -- **[Sensor服务子系使用实例](Sensor服务子系使用实例.md)** - - diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 99c79334499f61522bd731bc8f9bf2650480f2fd..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,72 +0,0 @@ -# Sensor服务子系使用指导 - -- [使用步骤](#section18816105182315) - -下面使用步骤以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 - -## 使用步骤 - -1. 导入需要的包 - -``` -#include "sensor_agent.h" -#include "sensor_agent_type.h" -``` - -1. 创建传感器回调函数 - -``` -void SensorDataCallbackImpl(SensorEvent *event) -{ - if(event == NULL){ - return; - } - float *sensorData=(float *)event->data; -} -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->回调函数的格式为RecordSensorCallback类型。 - -1. 获取设备支持sensor列表 - -``` -SensorInfo *sensorInfo = (SensorInfo *)NULL; -int32_t count = 0; -int32_t ret = GetAllSensors(&sensorInfo, &count); -``` - -1. 创建的传感器用户 - -``` -SensorUser sensorUser; -sensorUser.callback = SensorDataCallbackImpl; //成员变量callback指向创建的回调方法 -``` - -1. 使能传感器 - -``` -int32_t ret = ActivateSensor(0, &sensorUser); -``` - -1. 订阅传感器数据 - -``` -int32_t ret = SubscribeSensor(0, &sensorUser); -``` - ->![](public_sys-resources/icon-note.gif) **说明:** ->到这步就可以在实现的回调方法中获取到传感器数据。 - -1. 取消传感器数据订阅 - -``` -int32_t ret = UnsubscribeSensor(0, &sensorUser); -``` - -1. 去使能一个传感器 - -``` -int32_t ret = DeactivateSensor(0, &sensorUser); -``` - diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" deleted file mode 100755 index fa1d50d515bbc5e957204aae010019f5629a7767..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\346\246\202\350\277\260.md" +++ /dev/null @@ -1,99 +0,0 @@ -# Sensor服务子系概述 - -- [简介](#section667413271505) -- [接口说明](#section7255104114110) - -## 简介 - -Sensor服务子系统提供了轻量级传感器服务基础框架,您可以使用该框架接口实现传感器列表查询、传感器控制、传感器订阅去订阅等功能。轻量级传感器服务框架如下图所示: - -**图1** Sensor服务框架图 - -![](figures/zh-cn_image_0000001077724150.png) - -- Sensor API:提供传感器的基础API,主要包含查询传感器的列表、订阅/取消传感器数据、执行控制命令等,简化应用开发。 -- Sensor Framework:主要实现传感器的订阅管理、数据通道的创建、销毁等,实现与传感器服务层的通信。 -- Sensor Service:主要实现HDF层数据接收、解析、分发,对设备传感器的管理,数据上报管理以及传感器权限管控等。 - -## 接口说明 - -**表 1** Sensor服务框架API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

接口说明

-

参数要求

-

int32_t GetAllSensors(SensorInfo **sensorInfo, int32_t *count)

-

作用:获取系统中所有传感器的信息。

-

返回值:0表示成功,其他返回值表示失败。

-

sensorInfo(NOT NULL):输出系统中所有传感器的信息;

-

count(NOT NULL):输出系统中所有传感器的数量。

-

int32_t SubscribeSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:订阅传感器数据,系统会将获取到的传感器数据上报给订阅者。

-

返回值: 0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t UnsubscribeSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:去订阅传感器数据,系统将取消传感器数据上报给订阅者。

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t SetBatch(int32_t sensorTypeId, SensorUser *user, int64_t samplingInterval, int64_t reportInterval)

-

作用:设置传感器的数据采样间隔和数据上报间隔

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

-

samplingInterval:传感器数据采样间隔,单位纳秒;

-

reportInterval:传感器数据上报间隔,单位纳秒。

-

int32_t ActivateSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:使能一个传感器订阅用户。

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t DeactivateSensor(int32_t sensorTypeId, SensorUser *user)

-

作用:去使能一个传感器订阅用户

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

-

int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

-

作用:设置传感器的工作模式

-

返回值:0为成功,其他返回值表示失败。

-

sensorTypeId:唯一标识一个传感器类型;

-

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

-

mode:传感器的数据上报模式。

-
- diff --git "a/zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" "b/zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" deleted file mode 100755 index b5e511362a0ef107beff73f3fb82f98c8a590487..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/XTS\350\256\244\350\257\201\345\255\220\347\263\273\347\273\237\345\274\200\345\217\221\346\214\207\345\215\227.md" +++ /dev/null @@ -1,648 +0,0 @@ -# XTS认证子系统开发指南 - -- [简介](#section465982318513) -- [系统类型](#section125090457443) -- [目录](#section161941989596) -- [约束](#section119744591305) -- [使用说明](#section137768191623) -- [用例开发指导](#section3695134065513) - - [C语言用例开发编译指导(适用于轻量系统产品用例开发)](#section198193336544) - - [C语言用例执行指导(适用于轻量系统产品用例开发)](#section13820233175418) - - [C++语言用例开发编译指导(适用于小型系统、标准系统用例开发)](#section3822123311540) - - [C++语言用例执行指导(适用于小型系统、标准系统用例开发)](#section128222336544) - - [JS语言用例开发指导(适用于标准系统)](#section159801435165220) - - [JS语言用例编译打包指导(适用于标准系统)](#section445519106559) - - -## 简介 - -XTS子系统是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套件,后续会拓展dcts(device compatibility test suite)设备兼容性测试套件等。 - -XTS子系统当前包括acts与tools软件包: - -- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 -- tools,存放acts相关测试用例开发框架。 - -## 系统类型 - -OpenHarmony支持如下几种系统类型: - -- 轻量系统(mini system) - - 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,支持的设备最小内存为128KiB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 - -- 小型系统(small system) - - 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为1MiB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 - -- 标准系统(standard system) - - 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为128MiB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 - - -## 目录 - -``` -/test/xts -├── acts # 测试代码存放目录 -│ └── subsystem # 标准系统子系统测试用例源码存放目录 -│ └── subsystem_lite # 轻量系统、小型系统子系统测试用例源码存放目录 -│ └── BUILD.gn # 标准系统测试用例编译配置 -│ └── build_lite # 轻量系统、小型系统测试用例编译配置存放目录 -│ └── BUILD.gn # 轻量系统、小型系统测试用例编译配置 -└── tools # 测试工具代码存放目录 -``` - -## 约束 - -轻量系统用例开发语言是C,小型系统用例开发语言是C++。 - -## 使用说明 - -**表 1** 用例级别说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

级别名称

-

基本定义

-

测试范围

-

Level0

-

冒烟

-

验证关键功能点基本功能/最基本DFX属性在最常见输入下的表现,通过表示功能基本可运行。

-

Level1

-

基本

-

验证各功能点基本功能/基本DFX属性在常见输入下的表现,通过表示功能基本可测试。

-

Level2

-

重要

-

验证各功能点的基本功能/基本DFX属性在常规输入/常见异常情况下的表现,通过表示功能基本正常可用,可开展Beta。

-

Level3

-

一般

-

验证各功能点的全部功能/全部DFX属性在各种常规/非常规输入组合下,或各种正常/异常预置条件组合下的表现。

-

Level4

-

生僻

-

验证关键功能点在极端异常预置条件下、用户难以触及的异常输入组合下的表现。

-
- -**表 2** 用例粒度说明 - - - - - - - - - - - - - - - - - - - - -

用例规模

-

被测试对象

-

测试环境

-

LargeTest

-

业务功能/全场景特性/整机及场景级DFX

-

尽量使用贴近真实的环境设备

-

MediumTest

-

模块/子系统集成至设备后的功能/DFX

-

使用真实的单设备进行验证,可进行消息模拟,尽量不对函数进行MOCK

-

SmallTest

-

模块/类/函数

-

在开发者个人环境进行测试,尽量不依赖其他模块,存在大量的MOCK

-
- -**表 3** 测试类型说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

测试类型名称

-

测试类型定义

-

Function

-

验证被测对象提供给用户的业务功能实现正确性的测试项,这里的“用户”可以是终端用户或开发者,功能包括业务功能及平台功能

-

Performance

-

验证被测对象在特定预置条件/负载模型下的处理能力的测试项,“处理能力”一般以单位时间内可处理的业务量来衡量,如呼叫/秒,帧率/秒,事件处理量/秒等

-

Power

-

验证被测对象在特定预置条件/负载模型下在一定时间内能源消耗量的测试项

-

Reliability

-

验证被测对象在正常/异常输入情况下,或业务量压力和长时间连续运行压力情况下业务表现的测试项,含稳定性、压力、故障注入、Monkey测试项

-

Security

-

验证系统对恶意威胁的防护能力,威胁包括但不限于未授权访问、使用、泄露、破坏、修改、毁灭,以保障信息的机密性、完整性和可用性; 验证系统对用户隐私的保护能力,保障用户的隐私数据被收集、使用、保有、披露和处置符合法律规范,保障用户的隐私权; 验证对各类安全规范的遵从情况,如安全设计规范、安全红线、工信部安全认证规范等,保障安全相关法律法规的合规。

-

Global

-

验证被测对象在是否具有国际化数据支持和本地化能力的测试项,包括语言显示、输入/输出习惯、时间显示、区域特性如货币时间禁忌等等

-

Compatibility

-

当被测对象为应用时,包括被测对象对于自身数据的后向兼容性、对于系统的前后向兼容性、对于不同用户数据(如播放器之音频文件格式/智能短信之用户短信内容)的兼容性测试项; 当被测对象为系统时,包括被测系统对于系统自身数据的后向兼容性、以及对于生态中常用应用的兼容性测试项;当被测对象为软件时,包括被测系统对于相关的硬件的兼容性;

-

User

-

验证被测对象在真实用户场景下的用户体验感受的测试项,注意此种情况下没有客观的“正确”与“失败”,所有的结论及评价都应该来自于用户

-

Standard

-

验证被测对象对于行业及公司内标准/协议/规范的遵从情况的测试项,注意此处的“标准”不包含任何安全标准,针对安全标准的测试项划归为“安全测试”类型

-

Safety

-

验证被测对象的Safety属性,避免产品可能对人身安全、健康以及产品本身带来的危害。

-

Resilience

-

验证被测对象的韧性属性,确保系统受攻击时承受并保持在有定义的运行状态(包括降级)、恢复并适应攻击以保障Mission达成。

-
- -## 用例开发指导 - -根据测试系统选择测试框架和对应测试用例语言。 - -**表 4** 系统和测试框架、开发语言对应关系 - - - - - - - - - - - - - - - - - - - - -

系统

-

测试框架

-

语言

-

轻量系统

-

hctest

-

c

-

小型系统

-

hcpptest

-

c++

-

标准系统

-

HJSUnit、hcpptest

-

js、c++

-
- -### C语言用例开发编译指导(适用于轻量系统产品用例开发) - -**示例:轻量系统测试用例开发** - -当前使用的测试框架是hctest,hctest测试框架支持使用C语言编写测试用例,是在开源测试框架unity的基础上进行增强和适配。 - -1. 用例目录规范:测试用例存储到test/xts/acts仓中 - - ``` - ├── acts - │ └──subsystem_lite - │ │ └── module_hal - │ │ │ └── BUILD.gn - │ │ │ └── src - │ └──build_lite - │ │ └── BUILD.gn - ``` - -2. src目录下用例编写样例。 - - 1.引用测试框架 - - ``` - #include "hctest.h" - ``` - - 2. 使用宏定义LITE\_TEST\_SUIT定义子系统、模块、测试套件名称 - - ``` - /** - * @brief register a test suit named "IntTestSuite" - * @param test subsystem name - * @param example module name - * @param IntTestSuite test suit name - */ - LITE_TEST_SUIT(test, example, IntTestSuite); - ``` - - 3. 定义Setup与TearDown - - 命名方式:测试套件名称+Setup,测试套件名称+TearDown。 - - Setup与TearDown必须存在,可以为空函数。 - - 4. 使用宏定义LITE\_TEST\_CASE写测试用例 - - 包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 - - ``` - LITE_TEST_CASE(IntTestSuite, TestCase001, Function | MediumTest | Level1) - { - //do something - }; - ``` - - 5. 使用宏定义 RUN\_TEST\_SUITE注册测试套件 - - ``` - RUN_TEST_SUITE(IntTestSuite); - ``` - -3. 测试模块的配置文件(BUILD.gn)样例: - - 在每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后静态库的名称、依赖的头文件、依赖的库等;具体写法如下: - - ``` - import("//test/xts/tools/lite/build/suite_lite.gni") - hctest_suite("ActsDemoTest") { - suite_name = "acts" - sources = [ - "src/test_demo.c", - ] - include_dirs = [ ] - cflags = [ "-Wno-error" ] - } - ``` - -4. acts下BUILD.gn增加编译选项。 - - 需要将测试模块加入到acts目录下的编译脚本中,编译脚本路径:test/xts/acts/build\_lite/BUILD.gn。 - - ``` - lite_component("acts") { - ... - if(board_name == "liteos_m") { - features += [ - ... - "//xts/acts/subsystem_lite/module_hal:ActsDemoTest" - ] - } - } - ``` - -5. 测试套件编译命令。 - - 随版本编译,debug版本编译时会同步编译acts测试套件 - - >![](public_sys-resources/icon-note.gif) **说明:** - >acts测试套件编译中间件为静态库,最终链接到版本镜像中 。 - - -### C语言用例执行指导(适用于轻量系统产品用例开发) - -**示例:轻量系统测试用例执行** - -将版本镜像烧录进开发板。 - -**测试步骤** - -1. 使用串口工具登录开发板,并保存串口打印信息。 -2. 重启设备,查看串口日志。 - -**测试结果分析指导** - -基于串口打印日志进行分析; - -每个测试套件执行以Start to run test suite开始,以xx Tests xx Failures xx Ignored结束。 - -### C++语言用例开发编译指导(适用于小型系统、标准系统用例开发) - -**示例:小型系统测试用例开发**(标准参考具体样例目录:global/i18n\_standard) - -当前使用的测试框架是hcpptest,hcpptest测试框架是在开源的googletest测试框架的基础上进行的增强和适配。 - -1. 规范用例目录:测试用例存储到test/xts/acts仓中。 - - ``` - ├── acts - │ └──subsystem_lite - │ │ └── module_posix - │ │ │ └── BUILD.gn - │ │ │ └── src - │ └──build_lite - │ │ └── BUILD.gn - ``` - -2. 测试模块src下用例编写样例: - - 1. 引用测试框架: - - 需要引用gtest.h 如:\#include "gtest/gtest.h" - - ``` - #include "gtest/gtest.h" - ``` - - 2. 定义Setup与TearDown - - ``` - using namespace std; - using namespace testing::ext; - class TestSuite: public testing::Test { - protected: - // Preset action of the test suite, which is executed before the first test case - static void SetUpTestCase(void){ - } - // Test suite cleanup action, which is executed after the last test case - static void TearDownTestCase(void){ - } - // Preset action of the test case - virtual void SetUp() - { - } - // Cleanup action of the test case - virtual void TearDown() - { - } - }; - ``` - - 3. 使用宏定义HWTEST或HWTEST\_F写测试用例 - - 普通测试用例的定义:HWTEST(测试套名称, 测试用例名称, 用例标注)。 - - 包含SetUp和TearDown的测试用例的定义 :HWTEST\_F(测试套名称, 测试用例名称,用例标注)。 - - 宏定义包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 - - ``` - HWTEST_F(TestSuite, TestCase_0001, Function | MediumTest | Level1) { - // do something - } - ``` - -3. 测试模块下用例配置文件(BUILD.gn)样例: - - 每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后可执行文件的名称、依赖的头文件、依赖的库等;具体写法如下。每个测试模块将独立编译成.bin可执行文件, 该文件可直接push到单板上进行测试。 - - 举例: - - ``` - import("//test/xts/tools/lite/build/suite_lite.gni") - hcpptest_suite("ActsDemoTest") { - suite_name = "acts" - sources = [ - "src/TestDemo.cpp" - ] - - include_dirs = [ - "src", - ... - ] - deps = [ - ... - ] - cflags = [ "-Wno-error" ] - } - - ``` - -4. acts目录下增加编译选项(BUILD.gn)样例: - - 将测试模块加入到acts目录下的编译脚本中,编译脚本为:test/xts/acts/build\_lite/BUILD.gn。 - - ``` - lite_component("acts") { - ... - else if(board_name == "liteos_a") { - features += [ - ... - "//xts/acts/subsystem_lite/module_posix:ActsDemoTest" - ] - } - } - ``` - -5. 测试套件编译命令。 - - 随版本编译,debug版本编译时会同步编译acts测试套件 - - >![](public_sys-resources/icon-note.gif) **说明:** - >小型系统acts独立编译成可执行文件(bin格式), 在编译产物的suites\\acts目录下归档。 - - -### C++语言用例执行指导(适用于小型系统、标准系统用例开发) - -**示例:小型系统测试用例执行** - -目前的用例执行采用nfs共享的方式,mount到单板去执行。 - -**环境搭建** - -1. 使用有限网线或无线将开发板与PC进行连接。 -2. 开发板配置IP、子网掩码、网关,确保开发板与PC处于同一个网段。 -3. PC安装nfs服务器并完成注册,启动nfs服务。 -4. 开发板配置mount命令,确保开发板可以访问PC端的nfs共享文件。 - - 格式:mount \[nfs服务器IP\]:\[/nfs共享目录\] \[/开发板目录\] nfs - - 举例: - - ``` - mount 192.168.1.10:/nfs /nfs nfs - ``` - - -**用例执行** - -测试套件执行 ActsDemoTest.bin 触发用例执行,基于串口打印日志进行分析。 - -### JS语言用例开发指导(适用于标准系统) - -当前使用的测试框架是HJSUnit,用于支撑OpenHarmony application测试(特指基于JS应用框架使用 Javascript 语言开发的 APP)进行自动化测试。 - -**用例编写基础语法** - -测试用例为 js 语言,必须满足 JavaScript 语言编程规范: - -**表 5** - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

用例语法

-

描述

-

要求

-

beforeAll

-

测试套级别的预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数

-

可选

-

afterAll

-

测试套级别的清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数

-

可选

-

beforeEach

-

测试用例级别的预置条件,在每条测试用例开始前执行,执行次数与 it 定义的测试用例数一致,支持一个参数:预置动作函数

-

可选

-

afterEach

-

测试用例级别的清理条件,在每条测试用例结束后执行,执行次数与 it 定义的测试用例数一致,支持一个参数:清理动作函数

-

可选

-

describe

-

定义一个测试套,支持两个参数:测试套名称和测试套函数; describe 支持嵌套,每个 describe 内均可以定义 beforeAll 、beforeEach 、afterEach 和 afterAll

-

必选

-

it

-

定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数

-

备注:

-

过滤参数:过滤参数为一个 32 位的 Int 类型参数,0 位 置1表示不筛选、默认执行;0-10 位 置1表示测试用例类型;16-18 位 置1表示测试用例规模;24-28 位 置1表示测试层级

-

测试用例类型。置位0-10分别表示:FUNCTION 方法类测试、PERFORMANCE 性能类测试、POWER 功耗类测试、RELIABILITY 可靠性测试、SECURITY 安全合规测试、GLOBAL 整体性测试、COMPATIBILITY 兼容性测试、USER 用户测试、STANDARD 标准测试、SAFETY 安全特性测试,RESILIENCE 压力测试。

-

测试用例规模。置位16-18分别表示:SMALL 小型测试、MEDIUM 中型测试、LARGE 大型测试。

-

测试层级。置位24-28分别表示:LEVEL0-0 级测试、LEVEL1-1 级测试、LEVEL2-2 级测试、LEVEL3-3 级测试、LEVEL4-4 级测试。

-

必选

-
- -用例编写语法采用 jasmine 的标准语法,格式支持ES6格式。 - -1. 规范用例目录:测试用例存储到entry/src/main/js/test目录。 - - ``` - ├── BUILD.gn - │ └──entry - │ │ └──src - │ │ │ └──main - │ │ │ │ └──js - │ │ │ │ │ └──default - │ │ │ │ │ │ └──pages - │ │ │ │ │ │ │ └──index - │ │ │ │ │ │ │ │ └──index.js # 入口文件 - │ │ │ │ │ └──test # 测试代码存放目录 - │ │ │ └── resources # hap资源存放目录 - │ │ │ └── config.json # hap配置文件 - ``` - -2. index.js示例 - - ``` - // 拉起js测试框架,加载测试用例 - import {Core, ExpectExtend} from 'deccjsunit/index' - - export default { - data: { - title: "" - }, - onInit() { - this.title = this.$t('strings.world'); - }, - onShow() { - console.info('onShow finish') - const core = Core.getInstance() - const expectExtend = new ExpectExtend({ - 'id': 'extend' - }) - core.addService('expect', expectExtend) - core.init() - const configService = core.getDefaultService('config') - configService.setConfig(this) - require('../../../test/List.test') - core.execute() - }, - onReady() { - }, - } - ``` - -3. 单元测试用例示例 - - ``` - // Example1: 使用HJSUnit进行单元测试 - describe('appInfoTest', function () { - it('app_info_test_001', 0, function () { - var info = app.getInfo() - expect(info.versionName).assertEqual('1.0') - expect(info.versionCode).assertEqual('3') - }) - }) - ``` - - -### JS语言用例编译打包指导(适用于标准系统) - -hap包编译请参考[标准系统js应用开发指导](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)。 - diff --git "a/zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100644 index 3933aebf5e5206f7b3c2aaa1f1a8e3d587e43d33..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/bytrace\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,119 +0,0 @@ -# bytrace使用指导 - -- [简介](#section11388623181619) -- [命令行开发指导](#section1595564317164) - - [bytrace命令](#section2344125731617) - - [bytrace命令使用举例](#section5402591174) - - -## 简介 - -bytrace是开发人员用于追踪进程轨迹、分析性能的一种工具,主要对内核ftrace进行了封装和扩展,来支持用户态的打点。通过该工具可以打开想要查看的用户态和内核label(通过下面命令行bytrace -l,查看支持的所有label),然后通过命令行进行抓取trace信息到指定文件中。 - -## 命令行开发指导 - -### bytrace命令 - -bytrace当前支持以下命令: - -**表 1** 命令行列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Option

-

Description

-

-h,--help

-

查看option帮助

-

-b n,--buffer_size n

-

指定n(KB)内存大小用于存取trace日志,默认2048KB

-

-t n,--time n

-

用来指定trace运行的时间(单位:s),取决于需要分析过程的时间

-

--trace_clock clock

-

trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot

-

--trace_begin

-

启动抓trace

-

--trace_dump

-

将数据输出到指定位置(默认控制台)

-

--trace_finish

-

停止抓trace,并将数据输出到指定位置(默认控制台)

-

-l,--list_categories

-

输出手机能支持的trace模块

-

--overwrite

-

当缓冲区满的时候,将丢弃最新的信息。(默认丢弃最老的日志)

-

-o filename,--output filename

-

指定输出的目标文件名称

-

-z

-

抓取trace后进行压缩

-
- -### bytrace命令使用举例 - -以下是常用bytrace命令示例,供开发者参考: - -- 查询支持的label。 - -``` -bytrace -l -``` - -或者 - -``` -bytrace --list_categories -``` - -- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 - -``` -bytrace -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace -``` - -- 设置trace的输出时钟为mono。 - -``` -bytrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace -``` - -- 抓取trace后进行压缩。 - -``` -bytrace -z -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace -``` - diff --git a/zh-cn/device-dev/subsystems/figures/20200721-223604(eSpace).gif b/zh-cn/device-dev/subsystems/figure/20200721-223604(eSpace).gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/20200721-223604(eSpace).gif rename to zh-cn/device-dev/subsystems/figure/20200721-223604(eSpace).gif diff --git "a/zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/Ability\344\270\216AbilitySlice\347\232\204\345\205\263\347\263\273\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/Ability\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" "b/zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" rename to "zh-cn/device-dev/subsystems/figure/Ability\347\256\241\347\220\206\346\234\215\345\212\241\345\222\214\345\214\205\347\256\241\347\220\206\346\234\215\345\212\241\345\220\257\345\212\250.png" diff --git "a/zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" "b/zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" rename to "zh-cn/device-dev/subsystems/figure/LiteOS-A\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" diff --git "a/zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" "b/zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" rename to "zh-cn/device-dev/subsystems/figure/LiteOS-M\345\271\263\345\217\260dump\347\263\273\347\273\237\345\261\236\346\200\247\350\276\223\345\207\272.png" diff --git "a/zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" "b/zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" rename to "zh-cn/device-dev/subsystems/figure/UIButton\347\202\271\345\207\273\346\225\210\346\236\234.gif" diff --git "a/zh-cn/device-dev/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/ViewGroup\346\267\273\345\212\240view\345\256\236\344\276\213\346\225\210\346\236\234\345\233\276.png" diff --git a/zh-cn/device-dev/subsystems/figures/unnaming.png b/zh-cn/device-dev/subsystems/figure/unnaming.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/unnaming.png rename to zh-cn/device-dev/subsystems/figure/unnaming.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001051782526.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001051782526.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001051782526.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001051782526.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052582522.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052582522.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052582522.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052582522.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052662559.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052662559.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052662559.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052662559.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052782555.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052782555.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052782555.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052782555.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052942531.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052942531.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001052942531.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001052942531.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053207924.gif b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053207924.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053207924.gif rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053207924.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053247975.gif b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053247975.gif old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001053247975.gif rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001053247975.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054101094.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054101094.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054101094.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054101094.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054421113.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054421113.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001054421113.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001054421113.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001059334449.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001059334449.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001059334449.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001059334449.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001060200050.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001060200050.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001060200050.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001060200050.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001061889268.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001061889268.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001061889268.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001061889268.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062334618.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062334618.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062334618.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062334618.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062476933.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062476933.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062476933.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062476933.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062942690.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062942690.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001062942690.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001062942690.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001063839940.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001063839940.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001063839940.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001063839940.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077724150.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077724150.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077724150.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077724150.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077727032.png b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077727032.png old mode 100755 new mode 100644 similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001077727032.png rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001077727032.png diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001119924146.gif b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001119924146.gif similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001119924146.gif rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001119924146.gif diff --git a/zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg b/zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001166643927.jpg similarity index 100% rename from zh-cn/device-dev/subsystems/figures/zh-cn_image_0000001166643927.jpg rename to zh-cn/device-dev/subsystems/figure/zh-cn_image_0000001166643927.jpg diff --git "a/zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" "b/zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" rename to "zh-cn/device-dev/subsystems/figure/\345\212\250\347\224\273\345\256\236\347\216\260\346\225\210\346\236\234\345\233\276.gif" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\345\214\205\347\256\241\347\220\206\345\255\220\347\263\273\347\273\237\346\241\206\346\236\266\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" "b/zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\233\276\347\211\2071.png" rename to "zh-cn/device-dev/subsystems/figure/\345\233\276\347\211\2071.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" "b/zh-cn/device-dev/subsystems/figure/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" rename to "zh-cn/device-dev/subsystems/figure/\345\256\211\345\205\250\345\255\220\347\263\273\347\273\237.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\345\271\263\351\223\272\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" "b/zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" rename to "zh-cn/device-dev/subsystems/figure/\345\272\224\347\224\250\345\220\257\345\212\250\346\265\201\347\250\213.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" "b/zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" rename to "zh-cn/device-dev/subsystems/figure/\346\217\222\344\273\266\344\276\235\350\265\226-(2).jpg" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" "b/zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\347\273\223\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" "b/zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figure/\346\231\256\351\200\232\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" "b/zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" rename to "zh-cn/device-dev/subsystems/figure/\346\260\264\345\271\263-\345\236\202\347\233\264\346\226\271\345\220\221\345\217\257\346\273\221\345\212\250\346\225\210\346\236\234\345\233\276.gif" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" "b/zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" rename to "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\346\236\266\346\236\204.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" "b/zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" rename to "zh-cn/device-dev/subsystems/figure/\346\265\213\350\257\225\345\271\263\345\217\260\350\277\220\350\241\214\346\227\266\345\272\217.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\347\273\204\344\273\266\346\240\221\347\273\223\346\236\204\347\244\272\346\204\217\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" "b/zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" rename to "zh-cn/device-dev/subsystems/figure/\347\274\226\350\257\221\346\236\204\345\273\272\346\265\201\347\250\213.jpg" diff --git "a/zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" "b/zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" rename to "zh-cn/device-dev/subsystems/figure/\350\207\252\351\200\202\345\272\224\346\250\241\345\274\217\345\233\276\347\211\207\346\225\210\346\236\234\345\233\276.png" diff --git "a/zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" "b/zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/figures/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" rename to "zh-cn/device-dev/subsystems/figure/\350\256\276\347\275\2562-2\347\275\221\346\240\274\345\271\266\346\267\273\345\212\2404\344\270\252button\347\273\204\344\273\266\350\277\233\350\241\214\345\270\203\345\261\200.png" diff --git a/zh-cn/device-dev/subsystems/figures/RIL-Adapter.png b/zh-cn/device-dev/subsystems/figures/RIL-Adapter.png deleted file mode 100644 index eb3a5f511cb246a0c250a0dc76150b8816f4394b..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/figures/RIL-Adapter.png and /dev/null differ diff --git "a/zh-cn/device-dev/subsystems/figures/\345\216\273\347\224\265.png" "b/zh-cn/device-dev/subsystems/figures/\345\216\273\347\224\265.png" deleted file mode 100755 index 6d8841ed7cd427e5f3d091f8d3261bc38c297bbf..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/subsystems/figures/\345\216\273\347\224\265.png" and /dev/null differ diff --git "a/zh-cn/device-dev/subsystems/figures/\346\235\245\347\224\265.png" "b/zh-cn/device-dev/subsystems/figures/\346\235\245\347\224\265.png" deleted file mode 100644 index f666f21d1575a00e928c99afb29a7aca8c26e641..0000000000000000000000000000000000000000 Binary files "a/zh-cn/device-dev/subsystems/figures/\346\235\245\347\224\265.png" and /dev/null differ diff --git "a/zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100644 index d4993fb7b51791ca8bbd5af2aff43cf011ade64a..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/hdc_std-\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,658 +0,0 @@ -# hdc\_std 使用指导 - -- [环境准备](#section05992022154916) -- [注意事项](#section19543134915210) -- [全局option](#section618522925119) -- [查询设备列表](#section174891132104218) -- [服务进程相关命令](#section680531510497) -- [网络相关的命令](#section71176123212) -- [文件相关的命令](#section173133523013) -- [应用相关的命令](#section2072647133819) -- [调试相关的命令](#section112861250195015) - -hdc\_std(OpenHarmony Device Connector)是OpenHarmony为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux等系统上与开发机或者模拟器进行交互。 - -下文将介绍hdc\_std的环境准备和常用命令及使用举例。 - -## 环境准备 - -**hdc\_std 工具获取方式:** - -从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 - -**使用举例:** - -下面以windows侧使用方式举例: - -从prebuilt/windows侧获取可执行文件hdc\_std.exe,放到磁盘某个位置即可使用。 - -## 注意事项 - -1、使用hdc\_std,如果出现异常,可以尝试通过hdc\_std kill命令杀掉hdc\_std服务,或者通过hdc\_std start -r命令重启服务进程进行解决。 - -2、如果出现hdc\_std list targets获取不到设备信息,通过任务管理器查看是否有hdc.exe进程存在,如果进程存在,可以通过杀掉该进程进行解决。 - -## 全局option - -全局option涉及以下命令: - -- **-h/help -v/version** - -用于显示hdc相关的帮助、版本信息。 - -**表 1** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-h/help -v/version

-

-

返回值

-

返回值说明

-

返回对应信息

-

帮助或者版本信息

-
- -使用方法: - -hdc\_std -h / hdc\_std help - -hdc\_std -v / hdc\_std version - -- **-t key** - -用于连接指定设备标识为key的设备。 - -**表 2** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

key

-

为tcp:port格式,或者USB序列号

-

返回值

-

返回值说明

-

①error: device '***' not found

-

②Nothing to do...

-

①设备不存在

-

②附加的命令不存在

-
- -使用方法: - -该option需要与具体的操作命令搭配使用,下面以shell命令举例: - -hdc\_std list targets (获取设备信息) - -hdc\_std -t _key_ shell (-t后面添加的_key_ 需要替换为上面查询的设备信息) - ->![](public_sys-resources/icon-note.gif) **说明:** ->一台开发机可支持多个设备连接,每个设备有其唯一的设备标识,如果通过网络与设备连接,其标识为tcp:port格式,如果通过usb连接则标识为设备sn号。该命令需要跟随具体操作命令。 - -## 查询设备列表 - -查询设备列表涉及以下命令: - -**list targets\[-v\]** - -显示所有已经连接的目标设备列表 - -**表 3** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-v

-

添加-v选项,则会打印设备详细信息

-

返回值

-

返回值说明

-

①返回设备信息

-

②[Empty]

-

①已经连接的设备列表信息

-

②没有查询到设备信息

-
- -使用方法: - -hdc\_std list targets - -hdc\_std list targets -v - -## 服务进程相关命令 - -服务进程涉及以下命令: - -- **target mount** - -以读写模式挂载/system等分区。 - -**表 4** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-

-

返回值

-

返回值说明

-

①Mount finish

-

②返回具体信息

-

①成功情况下返回的信息

-

②失败情况下的具体信息

-
- -使用方法: - -hdc\_std target mount - -- **smode \[off\]** - -授予后台服务进程root权限, 使用off参数取消授权。 - -使用方法: - -hdc\_std smode - -hdc\_std smode off - -- **kill \[-r\]** - -终止服务进程。 - -**表 5** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-r

-

触发服务重启

-

返回值

-

返回值说明

-

①Kill server finish

-

②返回具体信息

-

①成功情况下返回的信息

-

②失败情况下的具体信息

-
- -使用方法: - -hdc\_std kill - -- **start \[-r\]** - -启动服务进程。 - -**表 6** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-r

-

如果服务进程已经启动,-r选项会触发服务进程重新启动

-

返回值

-

返回值说明

-

-

-
- -使用方法: - -hdc\_std start - -## 网络相关的命令 - -网络部分涉及以下命令: - -- **tconn _host_\[:_port_\]\[-remove\]** - -通过【ip地址:端口号】来指定连接的设备 - -**表 7** 命令说明 - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

host[:port]

-

为tcp:port格式

-

-remove

-

表示断开与指定设备的连接

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std tconn 192.168.0.100:8710 - -- **tmode usb** - -执行后设备端对应daemon进程重启,并首先选用usb连接方式。 - -**表 8** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法: - -hdc\_std tmode usb - -- **tmode port _port-number_** - -执行后设备端对应daemon进程重启,并优先使用网络方式连接设备,如果连接设备再选择usb连接。 - -**表 9** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

port-number

-

listen连接的网络端口

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法: - -hdc\_std tmode port 8710 - ->![](public_sys-resources/icon-note.gif) **说明:** ->执行完毕后,远端daemon将会退出并重启,默认启用TCP连接,如果不加上listen端口则listen随机端口。 - -## 文件相关的命令 - -文件部分涉及以下命令: - -- **file send _local remote_** - -发送文件至远端设备。 - -**表 10** 命令说明 - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

local

-

本地待发送文件路径

-

remote

-

远程待接收文件路径

-

返回值

-

返回值说明

-

①返回具体信息

-

②返回传输结果

-

①失败情况下的具体信息

-

②成功传输的结果信息

-
- -使用方法(举例): - -hdc\_std file send E:\\a.txt /data/local/tmp/a.txt - -- **file recv \[-a\] _remote local_** - -从远端设备接收文件至本地。 - -**表 11** 命令说明 - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-a

-

文件保留时间戳模式

-

local

-

本地待接收文件路径

-

remote

-

远程待发送文件路径

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std file recv /data/local/tmp/a.txt ./a.txt - -## 应用相关的命令 - -应用部分涉及以下命令: - -- **install \[-r/-d/-g\] _package_** - -安装OpenHarmony package。 - -**表 12** 命令说明 - - - - - - - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

package

-

OpenHarmony应用安装包

-

-r

-

替换已存在应用

-

-d

-

允许降级安装

-

-g

-

动态授权

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std install _hwadmin.hap_ - -- **uninstall \[-k\] _package_** - -卸载OpenHarmony应用。 - -**表 13** 命令说明 - - - - - - - - - - - - - - - - - - -

参数

-

参数说明

-

package

-

OpenHarmony应用安装包

-

-k

-

保留/data/cache

-

返回值

-

返回值说明

-

①返回具体信息

-

②无

-

①失败情况下的具体信息

-

②成功情况下无返回值

-
- -使用方法(举例): - -hdc\_std uninstall _package_ - -## 调试相关的命令 - -调试涉及以下命令: - -- **hilog** - -支持抓取log信息。 - -**表 14** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

-

-

返回值

-

返回值说明

-

返回具体信息

-

抓取的日志信息

-
- -使用方法: - -hdc\_std hilog - -- **shell \[_command_\]** - -远程执行命令或进入交互命令环境。 - -**表 15** 命令说明 - - - - - - - - - - - - - - - -

参数

-

参数说明

-

command

-

需要执行的单次命令

-

返回值

-

返回值说明

-

返回具体信息

-

shell后面执行命令的结果信息

-
- -使用方法: - -hdc\_std shell - diff --git "a/zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100644 index 3f83fba3e9943bb252fec4fc273a197c3fcd9ec7..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/hdc_std\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,39 +0,0 @@ -# hdc\_std常见问题 - -- [hdc\_std连接不到设备](#section1221016541119) -- [hdc\_std运行不了](#section219185710311) - -## hdc\_std连接不到设备 - -- **现象描述** - - 执行 "hdc\_std list targets"命令后结果为:\[Empty\] - -- **可能原因和解决方法** - 1. 设备没有被识别: - - 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 - - 2. hdc\_std工作异常: - - 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 - - 如果一直获取不到设备信息,请在任务管理器中查询是否有adb进程,该进程可能会对hdc产生干扰,可以将其杀掉后重复执行上面的步骤。 - - 3. hdc\_std与设备不匹配: - - 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 - - - -## hdc\_std运行不了 - -- **现象描述** - - 点击hdc\_std.exe文件无法运行。 - -- **可能原因和解决方法** - - hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 - - diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-caution.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-caution.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/public_sys-resources/icon-caution.gif and /dev/null differ diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-danger.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-danger.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/public_sys-resources/icon-danger.gif and /dev/null differ diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-note.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-note.gif deleted file mode 100755 index 6314297e45c1de184204098efd4814d6dc8b1cda..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/public_sys-resources/icon-note.gif and /dev/null differ diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-notice.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-notice.gif deleted file mode 100755 index 86024f61b691400bea99e5b1f506d9d9aef36e27..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/public_sys-resources/icon-notice.gif and /dev/null differ diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-tip.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-tip.gif deleted file mode 100755 index 93aa72053b510e456b149f36a0972703ea9999b7..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/public_sys-resources/icon-tip.gif and /dev/null differ diff --git a/zh-cn/device-dev/subsystems/public_sys-resources/icon-warning.gif b/zh-cn/device-dev/subsystems/public_sys-resources/icon-warning.gif deleted file mode 100755 index 6e90d7cfc2193e39e10bb58c38d01a23f045d571..0000000000000000000000000000000000000000 Binary files a/zh-cn/device-dev/subsystems/public_sys-resources/icon-warning.gif and /dev/null differ diff --git "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-demo-conf.md diff --git "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-demo-plugin.md diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md new file mode 100644 index 0000000000000000000000000000000000000000..795599d87226dbe1e7150574143f4b739c042c0f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo-sdk.md @@ -0,0 +1,81 @@ +# 唤醒词识别SDK的开发示例 + +1. 在//foundation/ai/engine /interfaces/kits目录中添加唤醒词识别SDK的API接口定义,该接口可用三方应用的调用。如下代码片段即为唤醒词识别定义的API接口示例,其相关代码参考路径为://foundation/ai/engine /interfaces/kits/asr/keyword\_spotting。 + + ``` + class KWSSdk { + public: + KWSSdk(); + virtual ~KWSSdk(); + + // 定义了创建唤醒词检测工具包的方法 + int32_t Create(); + + // 定义了同步执行唤醒词检测任务的方法 + int32_t SyncExecute(const Array &audioInput); + + // 定义了设置唤醒词检测回调器的方法 + int32_t SetCallback(const std::shared_ptr &callback); + + // 定义了销毁唤醒词工具包的方法,释放与插件的会话信息。 + int32_t Destroy(); + }; + ``` + +2. 在//foundation/ai/engine/services/client/algorithm\_sdk的目录中增加SDK中API接口的具体实现,调用client端提供的接口,实现算法插件能力的使用。如下代码片段即为唤醒词识别的API接口中create方法的具体实现示例,更多详细代码可参考://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting。 + + ``` + int32_t KWSSdk::KWSSdkImpl::Create() + { + if (kwsHandle_ != INVALID_KWS_HANDLE) { + HILOGE("[KWSSdkImpl]The SDK has been created"); + return KWS_RETCODE_FAILURE; + } + if (InitComponents() != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]Fail to init sdk components"); + return KWS_RETCODE_FAILURE; + } + // 调用client端提供的接口AieClientInit,实现初始化引擎服务,激活跨进程调用 + int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode); + return KWS_RETCODE_FAILURE; + } + if (clientInfo_.clientId == INVALID_CLIENT_ID) { + HILOGE("[KWSSdkImpl]Fail to allocate client id"); + return KWS_RETCODE_FAILURE; + } + DataInfo inputInfo = { + .data = nullptr, + .length = 0, + }; + DataInfo outputInfo = { + .data = nullptr, + .length = 0, + }; + // 调用client端提供的接口AieClientPrepare,实现加载算法插件 + retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode); + return KWS_RETCODE_FAILURE; + } + if (outputInfo.data == nullptr || outputInfo.length <= 0) { + HILOGE("[KWSSdkImpl]The data or length of output info is invalid"); + return KWS_RETCODE_FAILURE; + } + MallocPointerGuard pointerGuard(outputInfo.data); + retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_); + if (retCode != RETCODE_SUCCESS) { + HILOGE("[KWSSdkImpl]Get handle from inputInfo failed"); + return KWS_RETCODE_FAILURE; + } + return KWS_RETCODE_SUCCESS; + } + ``` + + 上述代码为API接口的具体实现,从上述示例的代码中,SDK中create接口的具体实现即为下述示例代码中create方法,该方法调用了AI引擎框架client端开放接口AieClientInit,AieClientPrepare,从而实现与server端建立连接及加载算法模型的能力。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >SDK调用AI引擎client端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码。 + + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md b/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md new file mode 100644 index 0000000000000000000000000000000000000000..054336dafd8be39390dfed958dc9d1576a3d297a --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-demo.md @@ -0,0 +1,13 @@ +# 开发示例 + +以开发唤醒词识别为例,开发者可在Hi3516DV300开发板上,基于AI引擎框架开发唤醒词识别的sdk以及唤醒词识别的plugin,通过编译命令编出新的版本镜像并将其烧入版本。同时,开发者开发唤醒词识别的应用,该应用能够接收外部音频,将listen到的音频传入SDK中的接口,若音频中带有关键词,唤醒词识别的应用会识别出相应的词语,并打印在命令行中。 + +本示例中唤醒词识别的场景中唤醒词是固定的,当开发者传入的音频包含”Hi,小问“,启动的应用就会打印"\[Hi, xiaowen\]",当不包含时,会打印'\[UNKNOWN\]"。 + +- **[唤醒词识别SDK的开发示例](subsys-aiframework-demo-sdk.md)** + +- **[唤醒词识别插件的开发示例](subsys-aiframework-demo-plugin.md)** + +- **[唤醒词识别配置文件的开发示例](subsys-aiframework-demo-conf.md)** + + diff --git "a/zh-cn/device-dev/subsystems/\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\205\215\347\275\256\346\226\207\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-devguide-conf.md diff --git "a/zh-cn/device-dev/subsystems/\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\346\217\222\344\273\266\347\232\204\345\274\200\345\217\221\350\277\207\347\250\213.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-devguide-plugin.md diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md new file mode 100644 index 0000000000000000000000000000000000000000..ed8f624d68c07f4791327fc7b161a793a07e54a8 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide-sdk.md @@ -0,0 +1,162 @@ +# SDK开发过程 + +SDK头文件的功能实现是基于对SDK的调用映射到对client的调用。Client端提供的接口如下[表1](#table203963834718)所示。 + +**表 1** Client端提供的接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

接口说明

+

参数要求

+

int AieClientInit(const ConfigInfo &configInfo, ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, IServiceDeadCb *cb)

+

作用:链接并初始化引擎服务,激活跨进程调用。

+

返回值:0为成功,其他返回值失败。

+

configInfo(NOT NULL):引擎相关初始化配置数据;

+

clientInfo(NOT NULL):引擎客户端信息;

+

algorithmInfo(NOT NULL):调用算法信息;

+

cb(可为NULL):死亡回调 对象;

+

int AieClientPrepare(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo, IClientCb *cb)

+

作用:加载算法插件。

+

返回值: 0为成功,其他返回值失败。

+

clientInfo(NOT NULL):引擎客户端信息;

+

algorithmInfo(NOT NULL):调用算法信息;

+

inputInfo(可为NULL):加载算法插件时输入所需信息;

+

outputInfo(可为NULL):加载算法插件之后如需返回信息则通过此出参返回;

+

cb:异步算法通过此回调返回运算结果,因此异步算法此结构体不能为空;若为同步算法,传入空值即可;

+

int AieClientAsyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

+

作用:执行异步算法。

+

返回值:0为成功,其他返回值失败。

+

clientInfo(NOT NULL):引擎客户端信息;

+

algorithmInfo(NOT NULL):调用算法信息;

+

inputInfo(可为NULL):算法运算入参;

+

int AieClientSyncProcess(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo, DataInfo &outputInfo)

+

作用:执行同步算法。

+

返回值:0为成功,其他返回值失败。

+

clientInfo(NOT NULL):引擎客户端信息;

+

algorithmInfo(NOT NULL):调用算法信息;

+

inputInfo(可为NULL):算法运算入参;

+

outputInfo(可为NULL):同步算法运算结果出参;

+

int AieClientRelease(const ClientInfo &clientInfo, const AlgorithmInfo &algorithmInfo, const DataInfo &inputInfo)

+

作用:卸载算法插件。

+

返回值:0为成功,其他返回值失败。

+

clientInfo(NOT NULL):引擎客户端信息;

+

algorithmInfo(NOT NULL):卸载算法插件的相关信息;

+

inputInfo(可为NULL):调用卸载接口时的输入信息;

+

int AieClientDestroy(ClientInfo &clientInfo)

+

作用:断开与服务端的链接,释放相关缓存。

+

返回值:0为成功,其他返回值失败。

+

clientInfo(NOT NULL):所要销毁的引擎客户端信息;

+

int AieClientSetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo)

+

作用:设置配置项,可将一些算法的拓展信息通过此接口传入插件。

+

返回值:0为成功,其他返回值失败。

+

clientInfo(NOT NULL):引擎客户端信息;

+

optionType (NOT NULL):算法配置项,算法插件可根据需要利用此状态位;

+

inputInfo(可为NULL):插件可根据需要通过此入参设置算法参数信息;

+

int AieClientGetOption(const ClientInfo &clientInfo, int optionType, const DataInfo &inputInfo, DataInfo &outputInfo)

+

作用:给定特定的optionType和inputInfo,获取其对应的配置项信息。

+

返回值:0为成功,其他返回值失败。

+

clientInfo(NOT NULL):引擎客户端信息;

+

optionType(NOT NULL):所获取配置项信息的对应算法状态位;

+

inputInfo(可为NULL):所获取配置项信息的对应算法参数信息;

+

outputInfo(可为NULL):所要获取的配置项信息返回结果;

+
+ +其中,ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构如下[表2](#table22154317482)所示。 + +**表 2** ConfigInfo,ClientInfo,AlgorithmInfo,DataInfo的数据结构 + + + + + + + + + + + + + + + + + + + + + + + + +

结构体名称

+

说明

+

属性

+

ConfigInfo

+

算法配置项信息。

+

const char *description:配置项信息主体;

+

ClientInfo

+

客户端信息。

+

long long clientVersion:客户端设备版本号(当前还未启用);

+

int clientId:客户端ID;

+

int sessionId:会话ID;

+

uid_t serverUid:server端UID;

+

uid_t clientUid:client端UID;

+

int extendLen:拓展信息(extendMsg)长度;

+

unsigned char *extendMsg:拓展信息主体;

+

AlgorithmInfo

+

算法信息。

+

long long clientVersion:客户端设备版本号(当前还未启用);

+

bool isAsync:是否为异步执行;

+

int algorithmType:引擎框架根据插件加载顺序分配的算法类型ID;

+

long long algorithmVersion:算法版本号;

+

bool isCloud:是否上云(当前还未启用);

+

int operateId:执行ID(当前还未启用);

+

int requestId:请求ID,标识每次request,以对应执行结果;

+

int extendLen:拓展信息(extendMsg)长度;

+

unsigned char *extendMsg:拓展信息主体;

+

DataInfo

+

算法数据入参(inputInfo)、接口调用结果出参(outputInfo)。

+

unsigned char *data:数据主体;

+

int length:数据(data)长度;

+
+ +具体开发过程可参考唤醒词识别SDK开发示例。 + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md new file mode 100644 index 0000000000000000000000000000000000000000..5de9fe721cbe94bd784c2b09bd70f3258a6af68e --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-devguide.md @@ -0,0 +1,11 @@ +# 开发指导 + +为实现AI 引擎框架的接入,开发者需开发上述[图1](subsys-aiframework-guide.md#fig143186187187)中的SDK模块和Plugin模块,通过调用sdk提供的接口,基于AI引擎框架实现调用plugin中算法的能力,从而实现AI能力的生命周期管理和按需部署功能。 + +- **[SDK开发过程](subsys-aiframework-devguide-sdk.md)** + +- **[插件的开发过程](subsys-aiframework-devguide-plugin.md)** + +- **[配置文件的开发过程](subsys-aiframework-devguide-conf.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md b/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md new file mode 100644 index 0000000000000000000000000000000000000000..50cd9a3f9c3e5bf420863c30218379a631400f26 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-envbuild.md @@ -0,0 +1,5 @@ +# 搭建环境 + +1. 准备开发板:Hi3516DV300,Hi3518EV300 +2. [下载源码](../get-code/sourcecode-acquire.md) + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md b/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..c725c6de1d82b1efa4670cedb9654b8f044d25f3 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-guide.md @@ -0,0 +1,9 @@ +# AI引擎框架开发指南 + +AI业务子系统是OpenHarmony提供原生的分布式AI能力的子系统。AI业务子系统提供了统一的AI引擎框架,实现算法能力快速插件化集成。框架中主要包含插件管理、模块管理和通信管理等模块,完成对AI算法能力的生命周期管理和按需部署。插件管理主要实现插件的生命周期管理及插件的按需部署,快速集成AI能力插件;模块管理主要实现任务的调度及管理客户端的实例;通信管理主要实现客户端和服务端之间的跨进程通信及引擎与插件之间的数据传输。后续,会逐步定义统一的AI能力接口,便于AI能力的分布式调用。同时,提供适配不同推理框架层级的统一推理接口。AI引擎框架如下[图1](#fig143186187187)所示。 + +**图 1** AI引擎框架 + + +![](figure/zh-cn_image_0000001077727032.png) + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md new file mode 100644 index 0000000000000000000000000000000000000000..f93fcf62bb5cb58aa6873e0191ac86627acd5532 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-codemanage.md @@ -0,0 +1,40 @@ +# 代码管理规范 + +- [建议:插件与北向SDK在AI引擎指定的路径下进行代码开发](#section17176374131) +- [规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录](#section2551029111312) +- [规则:插件编译输出路径必须是在/usr/lib](#section97021558121310) + +AI引擎框架包含client、server和common三个主要模块,其中client提供server端连接管理功能,北向SDK在算法对外接口中需封装调用client提供的公共接口;server提供插件加载以及任务管理等功能,各Plugin实现由server提供的插件接口,完成插件接入;common提供与平台相关的操作方法、引擎协议以及相关工具类,供其他各模块调用。 + +AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示: + +**图 1** ****AI引擎代码依赖关系 + + +![](figure/插件依赖-(2).jpg) + +## 建议:插件与北向SDK在AI引擎指定的路径下进行代码开发 + +在AI引擎框架的整体规划中,北向SDK属于client端的一部分,插件由server端调用,属于server端的一部分,因此AI引擎框架为接入的插件与北向SDK规划的路径: + +- SDK代码路径://foundation/ai/engine/services/client/algorithm\_sdk + + e.g. //foundation/ai/engine/services/client/algorithm\_sdk/cv + + e.g. //foundation/ai/engine/services/client/algorithm\_sdk/nlu + +- 插件代码路径://foundation/ai/engine/services/server/plugin + + e.g. //foundation/ai/engine/services/server/plugin/cv + + e.g. //foundation/ai/engine/services/server/plugin/nlu + + +## 规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录 + +北向SDK对外接口是AI业务子系统提供能力的对外暴露方式,按照OpenHarmony的接口管理要求,需统一存放在各子系统的interfaces/kits目录中。当前AI业务子系统插件对外接口路径为//foundation/ai/engine/interfaces/kits,不同插件可在该路径下添加目录,比如增加cv插件,则在路径//foundation/ai/engine/interfaces/kits/cv下面存放接口文件。 + +## 规则:插件编译输出路径必须是在/usr/lib + +server端加载插件是采用dlopen方式,只支持在/usr/lib路径进行,因此插件在编译so时,需要在编译配置文件中指定输出路径为/usr/lib。 + diff --git "a/zh-cn/device-dev/subsystems/\346\216\245\345\217\243\345\274\200\345\217\221\350\247\204\350\214\203.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\346\216\245\345\217\243\345\274\200\345\217\221\350\247\204\350\214\203.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-tech-interface.md diff --git "a/zh-cn/device-dev/subsystems/\345\221\275\345\220\215\350\247\204\350\214\203.md" b/zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\221\275\345\220\215\350\247\204\350\214\203.md" rename to zh-cn/device-dev/subsystems/subsys-aiframework-tech-name.md diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md b/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md new file mode 100644 index 0000000000000000000000000000000000000000..486878e0b4123418899c58c037ed24b3227e4ad6 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework-tech.md @@ -0,0 +1,15 @@ +# 技术规范 + +**用词约定:** + +**规则:**必须准守的约定 + +**建议:**需要加以考虑的约定 + +- **[代码管理规范](subsys-aiframework-tech-codemanage.md)** + +- **[命名规范](subsys-aiframework-tech-name.md)** + +- **[接口开发规范](subsys-aiframework-tech-interface.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-aiframework.md b/zh-cn/device-dev/subsystems/subsys-aiframework.md new file mode 100644 index 0000000000000000000000000000000000000000..77fa018ec4592e10ced77cbec30a0a7a9f003481 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-aiframework.md @@ -0,0 +1,13 @@ +# AI框架 + +- **[AI引擎框架开发指南](subsys-aiframework-guide.md)** + +- **[搭建环境](subsys-aiframework-envbuild.md)** + +- **[技术规范](subsys-aiframework-tech.md)** + +- **[开发指导](subsys-aiframework-devguide.md)** + +- **[开发示例](subsys-aiframework-demo.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-builden.md b/zh-cn/device-dev/subsystems/subsys-application-framework-builden.md new file mode 100644 index 0000000000000000000000000000000000000000..182aea265b994e46add0b4ab22ad8bab8bbf8153 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-builden.md @@ -0,0 +1,7 @@ +# 搭建环境 + +- 开发板:Hi3516DV300 + +- [下载源码](../get-code/sourcecode-acquire.md) +- [编译用户程序框架](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E7%94%A8%E6%88%B7%E7%A8%8B%E5%BA%8F%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md) + diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-application-framework-demo.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-application-framework-demo.md diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md b/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..b132c23b9381bc71ac04a83359bad84395061fc8 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-guide.md @@ -0,0 +1,711 @@ +# 开发指导 + +- [场景介绍](#section93012287133) +- [接口说明](#section11821047161319) +- [开发步骤](#section10514141679) + - [创建Service类型的Ability](#section19921154214315) + - [包管理接口使用指导](#section1724016743217) + - [Hap包打包](#section171771212328) + + +## 场景介绍 + +- 带界面的Ability的应用,比如:新闻类的应用、视频类的应用、导航类的应用、支付类的应用等等,目前我们看到的大部分应用都是带有界面的用于人机交互的应用。 + +- 不带界面的Ability应用,比如:音乐播放器能在后台播放音乐、后台提供计算服务、导航服务的各类应用等。 + +- 不管是带界面的Ability应用还是不带界面的Ability应用,都要打包成Hap包,最终发布到应用市场,用户通过应用市场下载安装相应的应用。 + +## 接口说明 + +**表 1** Ability子系统的对外接口 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名称

+

接口描述

+

Want *WantParseUri(const char *uri)

+

反序列化接口,由字符串生成Want对象。

+

const char *WantToUri(Want want)

+

序列化,把Want对象生成字符串。

+

void SetWantElement(Want *want, ElementName element);

+

设置ElementName对象。

+

void SetWantData(Want *want, const void *data, uint16_t dataLength)

+

设置数据。

+

bool SetWantSvcIdentity(Want *want, SvcIdentity sid)

+

设置SvcIdentity。

+

void ClearWant(Want *want)

+

清除Want的内部内存数据。

+

void SetMainRoute(const std::string &entry)

+

设置AbilitySlice主路由。

+

void SetUIContent(RootView *rootView)

+

设置布局资源。

+

void OnStart(const Want& intent)

+

Ability生命周期状态回调,Ability启动时被回调。

+

void OnStop()

+

Ability生命周期状态回调,Ability销毁时被回调。

+

void OnActive(const Want& intent)

+

Ability生命周期状态回调,Ability显示时被回调。

+

void OnInactive()

+

Ability生命周期状态回调,Ability隐藏时被回调。

+

void OnBackground()

+

Ability生命周期状态回调,Ability退到后台时被回调。

+

const SvcIdentity *OnConnect(const Want &want)

+

Service类型Ability第一次连接时被回调。

+

void OnDisconnect(const Want &want);

+

Service类型Ability断开连接被回调。

+

void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply);

+

Service类型Ability接收消息处理。

+

void Dump(const std::string &extra)

+

dump Ability信息。

+

void Present(AbilitySlice *abilitySlice, const Want &want)

+

发起AbilitySlice跳转。

+

void Terminate()

+

退出当前AbilitySlice。

+

void SetUIContent(RootView *rootView)

+

设置当前AbilitySlice所在Ability的布局资源。

+

void OnStart(const Want& want)

+

AbilitySlice生命周期状态回调,AbilitySlice启动时被回调。

+

void OnStop()

+

AbilitySlice生命周期状态回调,AbilitySlice销毁时被回调。

+

void OnActive(const Want& want)

+

AbilitySlice生命周期状态回调,AbilitySlice显示时被回调。

+

void OnInactive()

+

AbilitySlice生命周期状态回调,AbilitySlice隐藏时被回调。

+

void OnBackground()

+

AbilitySlice生命周期状态回调,AbilitySlice退到后台时被回调。

+

int StartAbility(const Want &want)

+

启动Ability。

+

int StopAbility(const Want &want)

+

停止Service类型的Ability。

+

int TerminateAbility()

+

销毁当前的Ability。

+

int ConnectAbility(const Want &want, const IAbilityConnection &conn, void *data);

+

绑定Service类型的Ability。

+

int DisconnectAbility(const IAbilityConnection &conn)

+

解绑Service类型的Ability。

+

const char *GetBundleName()

+

获取当前ability的对应应用的包名。

+

const char *GetSrcPath()

+

获取当前ability的对应应用的安装路径。

+

const char *GetDataPath()

+

获取当前ability的对应应用的数据路径。

+

int StartAbility(const Want *want)

+

启动Ability,该接口可以不需要在基于Ability开发的应用中使用。

+

int ConnectAbility(const Want *want, const IAbilityConnection *conn, void *data);

+

绑定Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

+

int DisconnectAbility(const IAbilityConnection *conn);

+

解绑Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

+

int StopAbility(const Want *want)

+

停止Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

+

void (*OnAbilityConnectDone)(ElementName *elementName, SvcIdentity *serviceSid, int resultCode, void *data)

+

绑定Service Ability的回调。

+

void (*OnAbilityDisconnectDone)(ElementName *elementName, int resultCode, void *data)

+

解绑Service Ability的回调。

+

void PostTask(const Task& task)

+

投递任务到异步线程进行处理。

+

void PostQuit()

+

退出当前线程的消息循环。

+

static AbilityEventHandler* GetCurrentHandler()

+

获取当前线程的事件处理器。

+

void Run()

+

执行当前线程的消息循环。

+

#define REGISTER_AA(className)

+

注册开发者的Ability到框架中。

+

#define REGISTER_AS(className)

+

注册开发者的AbilitySlice到框架中。

+
+ +## 开发步骤 + +### 创建Service类型的Ability + +1. 在my\_service\_ability.h中创建Ability的子类MyServiceAbility。 + + ``` + class MyServiceAbility: public Ability { + protected: + void OnStart(const Want& want); + const SvcIdentity *OnConnect(const Want &want) override; + void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) override; + }; + ``` + +2. 调用REGISTER\_AA宏将ServiceAbility注册到应用框架中,以便应用框架实例化开发者的MyServiceAbility。 + + ``` + #include "my_service_ability.h" + + REGISTER_AA(ServiceAbility) + + void MyServiceAbility::OnStart(const Want& want) + { + printf("ServiceAbility::OnStart\n"); + Ability::OnStart(want); + } + + const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) + { + printf("ServiceAbility::OnConnect\n"); + return Ability::OnConnect(want); + } + + void MyServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) + { + printf("ServiceAbility::MsgHandle, funcId is %u\n", funcId); + int result = 0; + if (funcId == 0) { + result = IpcIoPopInt32(request) + IpcIoPopInt32(request); + } + // push data + IpcIoPushInt32(reply, result); + } + ``` + +3. 实现Service相关的生命周期方法。Service也是一种Ability,Ability为服务提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。用户在重写的方法里,需要调用父类对应的方法。 + - OnStart\(\) + + 该方法在创建Service的时候调用,用于做一些Service初始化且耗时较短的工作,在Service的整个生命周期只会调用一次。 + + ``` + void MyServiceAbility::OnStart(const Want& want) + { + printf("ServiceAbility::OnStart\n"); + Ability::OnStart(want); + } + ``` + + - OnConnect​\(\) + + 在组件和服务连接时调用,该方法返回SvcIdentity,组件可以通过它,与服务交互。 + + ``` + const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) + { + printf("ServiceAbility::OnConnect\n"); + return Ability::OnConnect(want); + } + ``` + + - OnDisconnect​\(\) + + 在组件与绑定的Service断开连接时调用。 + + - OnStop\(\) + + 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 + + +4. 重写消息处理方法。 + + MsgHandle是Service用来处理客户端消息的方法。其中funcId是客户端传过来的消息类型,request是客户端传过来的序列化请求参数。如果用户在处理完成之后想要把结果传回去,需要把结果序列化后写入reply中。 + + ``` + void ServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) + { + printf("ServiceAbility::MsgHandle, funcId is %d\n", funcId); + int result = 0; + if (funcId == PLUS) { + result = IpcIoPopInt32(request) + IpcIoPopInt32(request); + } + // push data + IpcIoPushInt32(reply, result); + } + ``` + +5. 注册Service。 + + Service也需要在应用清单文件config.json中进行注册,注册类型type需要设置为service。 + + ``` + "abilities": [{ + "name": "ServiceAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "service", + "visible": true + } + ] + ``` + +6. 启动Service。 + - Ability为用户提供了StartAbility\(\)方法来启动另外一个Ability,因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。 + + 开发者可以通过Want的SetWantElement \(\)来设置目标服务信息。ElementName结构体的两个主要参数:第一个参数为包名称;第二个参数为目标Ability。 + + ``` + { + Want want = { nullptr }; + ElementName element = { nullptr }; + SetElementBundleName(&element, "com.company.appname"); + SetElementAbilityName(&element, "ServiceAbility"); + SetWantElement(&want, element); + StartAbility(want); + ClearElement(&element); + ClearWant(&want); + } + ``` + + StartAbility\(\) 方法会立即执行,如果Service尚未运行,则系统首先会调用OnStart\(\)。 + + - 停止Service。 + + Service一旦创建就会一直保持在后台运行,开发者可以通过调用StopAbility\(\)来停止Service。 + + +7. 连接Service。 + - 如果Service需要与Page Ability或其他应用组件中的Service进行交互,则应创建用于连接的Service。Service支持其他Ability通过ConnectAbility\(\)与其进行连接,ConnectAbility\(\)需要传入目标Service的Want,以及IAbilityConnection的实例来处理回调。IAbilityConnection提供了两个方法供用户实现,OnAbilityConnectDone\(\)用来处理连接的回调,OnAbilityDisconnectDone\(\)用来处理断开连接的回调。 + + ``` + { + // ability创建IAbilityConnection对象和定义IAbilityConnection的两个方法实现 + IAbilityConnection abilityConnection = new IAbilityConnection(); + abilityConnection->OnAbilityConnectDone = OnAbilityConnectDone; + abilityConnection->OnAbilityDisconnectDone = OnAbilityDisconnectDone; + + void OnAbilityConnectDone(ElementName *elementName, SvcIdentity *serviceSid, + int resultCode, void *data) + { + if (resultCode != 0) { + return; + } + // push data + IpcIo request; + char dataBuffer[IPC_IO_DATA_MAX]; + IpcIoInit(&request, dataBuffer, IPC_IO_DATA_MAX, 0); + IpcIoPushInt32(&request, 10); + IpcIoPushInt32(&request, 6); + + // send and getReply + IpcIo reply; + uintptr_t ptr = 0; + if (Transact(nullptr, *serviceSid, 0, &request, &reply, + LITEIPC_FLAG_DEFAULT, &ptr) != LITEIPC_OK) { + printf("transact error\n"); + return; + } + int result = IpcIoPopInt32(&reply); + printf("execute add method, result is %d\n", result); + if (ptr != 0) { + FreeBuffer(nullptr, reinterpret_cast(ptr)); + } + } + + void OnAbilityDisconnectDone(ElementName *elementName, + int resultCode, void *data) + { + printf("elementName is %s, %s\n", + elementName->bundleName, elementName->abilityName); + } + } + ``` + + - 发起connect和disconnect。 + + ``` + { + // ability发起connect + Want want = { nullptr }; + ElementName element = { nullptr }; + SetElementBundleName(&element, "com.company.appname"); + SetElementAbilityName(&element, "ServiceAbility"); + SetWantElement(&want, element); + ConnectAbility(want, *abilityConnection, this); + + // ability发起disconnect + DisconnectAbility(*abilityConnection); + } + ``` + + + +### 包管理接口使用指导 + +**安装应用** + +安装接口只能给内置的系统应用使用。根据应用的安装路径,可以在安装应用时进行选择: + +- 将应用安装到系统默认的文件目录/storage/app/。 +- 将应用安装到系统外挂的存储介质中,例如micro sdcard。 + +这两种选择可以在创建InstallParam实例的时候指定,当InstallParam的成员变量installLocation为 INSTALL\_LOCATION\_INTERNAL\_ONLY时,意味着应用将会被安装到/storage/app/目录下;当InstallParam的成员变量installLocation为INSTALL\_LOCATION\_PREFER\_EXTERNAL时,意味着应用将被安装到存储介质,其安装目录是/sdcard/app/。由于安装应用的过程是异步的,所以需要使用类似信号量的机制来确保安装的回调可以被执行。 + +安装应用的步骤如下(示例代码以安装到系统目录为例): + +1. 将经过安全签名的应用放置于指定的目录下。 +2. 创建InstallParam实例和信号量。 + + ``` + InstallParam installParam = { + .installLocation = INSTALL_LOCATION_INTERNAL_ONLY, // 安装到系统目录 + .keepData = false + }; + static sem_t g_sem; + ``` + +3. 定义回调函数。 + + ``` + static void InstallCallback(const uint8_t resultCode, const void *resultMessage) + { + std::string strMessage = reinterpret_cast(resultMessage); + if (!strMessage.empty()) { + printf("install resultMessage is %s, %d\n", strMessage.c_str(),resultCode); + } + sem_post(&g_sem); + } + ``` + +4. 调用Install接口。 + + ``` + const uint32_t WAIT_TIMEOUT = 30; + sem_init(&g_sem, 0, 0); + std::string installPath = “/storage/bundle/demo.hap”; // hap包的存储路径 + bool result = Install(installPath.c_str(), &installParam, InstallCallback); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += WAIT_TIMEOUT; // 超时即释放信号量 + sem_timedwait(&g_sem, &ts); + ``` + + +**卸载应用** + +卸载应用的时候可以选择是否保留应用的数据,开发者可以通过创建的InstallParam实例的成员变量keepData来确定。当keepData为true, 卸载应用之后将保留应用的数据,当keepData为false时,卸载应用之后将不会保留应用的数据。 + +1. 创建InstallParam实例和信号量。 + + ``` + static sem_t g_sem; + InstallParam installParam = { + .installLocation = 1, + .keepData = false // 不保留应用数据 + }; + ``` + +2. 定义回调函数。 + + ``` + static void UninstallCallback(const uint8_t resultCode, const void *resultMessage) + { + std::string strMessage = reinterpret_cast(resultMessage); + if (!strMessage.empty()) { + printf("uninstall resultMessage is %s\n", strMessage.c_str()); + g_resultMessage = strMessage; + } + g_resultCode = resultCode; + sem_post(&g_sem); + } + ``` + +3. 调用Uninstall接口。 + + ``` + sem_init(&g_sem, 0, 0); + const uint32_t WAIT_TIMEOUT = 30; + std::string BUNDLE_NAME = “com.huawei.demo”; // 卸载应用的包名 + Uninstall(BUNDLE_NAME.c_str(), &installParam, UninstallCallback); + struct timespec ts = {}; + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += WAIT_TIMEOUT; + sem_timedwait(&g_sem, &ts); + ``` + + +**查询已安装应用的包信息** + +开发者可以利用BundleManager提供的接口GetBundleInfo来查询系统内已安装应用的包信息。 + +1. 创建以及初始化BundleInfo。 + + ``` + BundleInfo bundleInfo; + (void) memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)); + ``` + +2. 调用GetBundleInfo接口,指定查询应用的包名,同时指定flag来确定获取的BundleInfo中是否含有元能力信息(实例代码以含有元能力信息为例)。 + + ``` + std::string BUNDLE_NAME = "com.huawei.demo"; + uint8_t ret = GetBundleInfo(BUNDLE_NAME.c_str(), 1, &bundleInfo); // flags = 1,获取包信息中含有元能力信息 + ``` + +3. 使用完获取的BundleInfo之后,要及时清理掉其内部所占用的内存空间避免内存泄漏。 + + ``` + ClearBundleInfo(&bundleInfo); + ``` + + +### Hap包打包 + +打包工具一般集成到开发工具或者ide中,开发者一般不涉及直接使用该工具,下面的介绍开发者可以作为了解。打包工具的jar包在开源代码中的位置:developtools/packing\_tool/jar。 + +- 打包命令行参数 + + **表 2** 打包所需要的资源文件描述 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

命令参数

+

对应的资源文件

+

说明

+

是否可缺省

+

--mode

+

-

+

为“hap”字段,打包生成hap

+

+

--json-path

+

清单文件config.json

+

-

+

+

--resources-path

+

资源文件resources

+

-

+

+

--assets-path

+

资源文件assets

+

-

+

+

--lib-path

+

依赖库文件

+

-

+

+

--shared-libs-path

+

共享库文件

+

针对系统应用的共享库,特殊情况下使用

+

+

--ability-so-path

+

主功能so文件

+

-

+

+

--index-path

+

资源索引

+

资源索引文件由资源生成工具生成,由资源流水线会集成该工具

+

+

--out-path

+

-

+

生成的hap包输出路径,默认为当前目录

+

+

--force

+

-

+

是否覆盖原有同名文件,默认为false

+

+
+ +- 打包示例 + - 开发视图 + + ![](figure/zh-cn_image_0000001062942690.png) + + - 编译视图 + + ![](figure/zh-cn_image_0000001062334618.png) + + - 使用打包工具执行以下命令打包: + + ![](figure/zh-cn_image_0000001062476933.png) + + ``` + $ java -jar hmos_app_packing_tool.jar --mode hap --json-path ./config.json --assets-path ./assets/ --ability-so-path ./libentry.so --index-path ./resources.index --out-path out/entry.hap --force true + ``` + + + diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md b/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..a0ab8c2d1bbeb2118c32fee4eda946747445c5eb --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework-overview.md @@ -0,0 +1,141 @@ +# 概述 + +- [基本概念](#section72601941194812) +- [Ability子系统](#section14633111813374) +- [包管理子系统](#section1341146154412) +- [运作机制](#section94302021112717) +- [约束与限制](#section89534912527) + +用户程序框架是OpenHarmony为开发者提供开发OpenHarmony应用的开发框架,包含两个模块:Ability子系统和包管理子系统。 + +## 基本概念 + +开发者在开发前需要先了解以下基本概念,方便开发者更好的理解OpenHarmony用户程序框架。 + +## Ability子系统 + +Ability子系统是管理OpenHarmony应用运行状态的开发框架。 + +**图 1** Ability子系统框架图 +![](figure/Ability子系统框架图.png "Ability子系统框架图") + +- **Ability**:系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability。 + - **Page类型的Ability**:带有界面,为用户提供人机交互的能力。 + + - **Service类型的Ability**:不带界面,为用户提供后台任务机制。 + + + +- **AbilitySlice**:单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。 + + **图 2** Ability与AbilitySlice的关系图 + ![](figure/Ability与AbilitySlice的关系图.png "Ability与AbilitySlice的关系图") + +- **生命周期**:Ability被调度到启动、激活、隐藏和退出等各个状态的统称。 + + **图 3** Ability生命周期流转 + + + ![](figure/图片1.png) + + - **OnStart\(\)** + + 系统首次创建Page实例时触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。 + + - **OnActive\(\)** + + Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。 + + 当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用OnInactive\(\)回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用OnActive\(\)回调。因此,开发者通常需要成对实现OnActive\(\)和OnInactive\(\),并在OnActive\(\)中获取在OnInactive\(\)中被释放的资源。 + + - **OnInactive\(\)** + + 当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。 + + - **OnBackground\(\)** + + 如果Page不再对用户可见,系统将可能根据资源状况调用此回调,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。 + + - **OnForeground\(\)** + + 处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用OnForeground\(\)回调使Page回到INACTIVE状态,然后调用OnActive\(\)回调使Page回到ACTIVE状态。开发者应当在此回调中重新申请在OnBackground\(\)中释放的资源。轻量化设备目前不支持该接口。 + + - **OnStop\(\)** + + 此回调表示系统正在销毁Page。销毁Page的可能原因包括: + + - 用户通过系统管理能力显式关闭Page,例如使用任务管理器关闭Page。 + - 用户行为触发Page的TerminateAbility\(\)方法调用,例如使用应用的退出功能。 + - 配置变更导致系统暂时销毁Page并重建。 + - 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。 + + +- **AbilityKit**:Ability框架提供给开发者的开发包,开发者基于该开发包可以开发出基于Ability组件的应用。基于Ability组件开发的应用有两种类型:基于Javascript语言开发的Ability(JS Ability)和基于C/C++语言开发的Ability(Native Ability)。JS应用开发框架是开发者开发JS Ability所用到框架,是在AbilityKit基础封装的包含js UI组件的一套方便开发者能够迅速开发Ability应用的框架。 +- **AbilityLoader**:负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。 + +- **AbilityManager:**负责AbilityKit和Ability管理服务进行IPC的通信。 + +- **EventHandler**:AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。 + +- **AbilityManagerService**:元能力运行管理服务。该服务用于协调各Ability运行关系、及生命周期进行调度的系统服务。其中,服务启动模块负责Ability管理服务的启动、注册等。服务接口管理模块负责Ability管理服务对外能力的管理。进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。连接管理模块是Ability管理服务对Service类型Ability连接管理的模块 + +- **AppSpawn**:负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。 + + +## 包管理子系统 + +包管理子系统是OpenHarmony为开发者提供的安装包管理框架。 + +**图 4** 包管理子系统框架图 +![](figure/包管理子系统框架图.png "包管理子系统框架图") + +- **BundleKit**:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化listen接口。 +- **包扫描器**:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。 +- **包安装子模块**:安装,卸载,升级一个包;包安装服务是一个单独进程和包管理服务通过IPC进行通信,该服务用于创建、删除安装目录和数据目录等,具有较高的权限。 + +- **包管理子模块**:管理安装包相关的信息,存储持久化包信息。 + +- **包安全管理子模块**:签名检查、权限授予、权限管理。 + + +## 运作机制 + +Ability子系统的核心模块是Ability管理服务、包管理子系统的核心模块是包管理服务,这两个服务是系统级服务,借助系统服务框架Samgr实现服务的注册与发现,并对其他进程提供Ability管理服务和包管理服务。Ability管理服务和包管理服务通过AbilityKit和BundleKit以接口的形式向外提供服务。 + +**图 5** Ability管理服务和包管理服务启动 +![](figure/Ability管理服务和包管理服务启动.png "Ability管理服务和包管理服务启动") + +Ability管理服务和包管理服务启动后,就可以安装OpenHarmony应用和启动运行OpenHarmony应用。 + +**图 6** 应用启动流程 +![](figure/应用启动流程.png "应用启动流程") + +桌面为Ability管理服务启动的第一个OpenHarmony应用。桌面启动后,用户可以在桌面上点击安装的OpenHarmony应用并启动该应用。上图6为从桌面启动一个已安装应用的交互流程。 + +从图中可知,Ability管理服务负责协调Ability之间的显示隐藏,包管理服务负责Ability信息的存储查询。 + +## 约束与限制 + +- 语言版本 + + - C++11版本或以上 + + +- 框架针对不同的芯片平台和底层OS能力,规格有所区别 + + - Cortex-M RAM/ROM: + + - RAM:建议大于20K + + - ROM: \> 300K (包含JS应用开发框架,UIKit及引擎等强相关子系统) + + + - Cortex-A RAM/ROM: + + - RAM:建议大于2M + + - ROM:\> 2M (包含JS应用开发框架,UIKit及引擎等强相关子系统) + + + + diff --git a/zh-cn/device-dev/subsystems/subsys-application-framework.md b/zh-cn/device-dev/subsystems/subsys-application-framework.md new file mode 100644 index 0000000000000000000000000000000000000000..99997047ffcf4648b1b4e7fe5eb8ce2db5c6d66c --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-application-framework.md @@ -0,0 +1,11 @@ +# 用户程序框架 + +- **[概述](subsys-application-framework-overview.md)** + +- **[搭建环境](subsys-application-framework-builden.md)** + +- **[开发指导](subsys-application-framework-guide.md)** + +- **[开发实例](subsys-application-framework-demo.md)** + + diff --git "a/zh-cn/device-dev/subsystems/appspawn\345\272\224\347\224\250\345\255\265\345\214\226\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-appspawn.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/appspawn\345\272\224\347\224\250\345\255\265\345\214\226\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-appspawn.md diff --git "a/zh-cn/device-dev/subsystems/bootstrap\346\234\215\345\212\241\345\220\257\345\212\250\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/bootstrap\346\234\215\345\212\241\345\220\257\345\212\250\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-bootstrap.md diff --git a/zh-cn/device-dev/subsystems/subsys-boot-faqs.md b/zh-cn/device-dev/subsystems/subsys-boot-faqs.md new file mode 100644 index 0000000000000000000000000000000000000000..196a586630627ef713e6acedf249952fbe63ae5d --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-boot-faqs.md @@ -0,0 +1,56 @@ +# 常见问题 + +- [系统启动过程中打印“parse failed!”错误后停止启动](#section2041345718513) +- [系统启动过程未结束就自动重启,如此反复持续](#section57381816168) +- [参数正确的情况下调用SetParameter/GetParameter返回失败](#section129991227141512) + +## 系统启动过程中打印“parse failed!”错误后停止启动 + +**现象描述** + +系统启动过程中,打印“\[Init\] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示: + +![](figure/zh-cn_image_0000001063839940.png) + +**可能原因** + +修改init.cfg文件时,漏掉或多加了逗号或括号等,导致init.cfg文件的json格式被破坏。 + +**解决办法** + +仔细检查init.cfg文件,确保其格式符合json格式要求。 + +## 系统启动过程未结束就自动重启,如此反复持续 + +**现象描述** + +镜像烧写完成后系统启动,启动过程未完成即自动重新启动,如此反复持续。 + +**可能原因** + +被init启动的服务都有一个叫做“importance”的属性(详见[第2章表3](subsys-boot-init.md#table14737791471)描述)。 + +- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。 +- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。 + +因此出现上述现象的可能原因:有“importance”属性为1的服务在每次启动的过程中都会退出(可能是进程崩溃或出错自动退出),导致init进程自动重启单板。 + +**解决办法** + +1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。 +2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。 + +## 参数正确的情况下调用SetParameter/GetParameter返回失败 + +**现象描述** + +在各参数正确的情况下调用SetParameter/GetParameter返回失败。 + +**可能原因** + +程序对SetParameter/GetParameter这两个接口做了权限校验,在各参数正确的情况下调用SetParameter/GetParameter返回操作失败,很有可能是调用者的uid大于1000,没有调用权限。 + +**解决办法** + +无需处理 + diff --git "a/zh-cn/device-dev/subsystems/init\345\220\257\345\212\250\345\274\225\345\257\274\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-init.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/init\345\220\257\345\212\250\345\274\225\345\257\274\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-init.md diff --git a/zh-cn/device-dev/subsystems/subsys-boot-overview.md b/zh-cn/device-dev/subsystems/subsys-boot-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..ee24488c41a99af1472600ecfabe775a0e18e4c3 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-boot-overview.md @@ -0,0 +1,66 @@ +# 启动恢复子系统概述 + +- [约束与限制](#section2029921310472) + +启动恢复子系统负责从内核启动之后到应用启动之前的系统关键服务进程的启动过程以及设备恢复出厂设置的功能。涉及以下组件: + +- init启动引导组件 + + init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见[第2章表2](subsys-boot-init.md#table122681439144112)描述)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。 + +- appspawn应用孵化组件 + + 负责接收**用户程序框架**的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。 + +- bootstrap服务启动组件 + + 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。 + +- syspara系统属性组件 + + 系统属性组件,根据OpenHarmony产品兼容性规范提供获取设备信息的接口,如:产品名、品牌名、厂家名等,同时提供设置/读取系统属性的接口。 + + +## 约束与限制 + +启动恢复子系统源代码目录和适配平台: + +**表 1** 启动恢复子系统源代码目录和适配平台 + + + + + + + + + + + + + + + + + + + +

名称

+

适配平台

+

base/startup/appspawn_lite

+

小型系统设备(参考内存≥1MB),如Hi3516DV300 、Hi3518EV300

+

base/startup/bootstrap_lite

+

轻量系统设备(参考内存≥128KB),如Hi3861V100

+

base/startup/init_lite

+

小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300

+

base/startup/syspara_lite

+
  • 轻量系统设备(参考内存≥128KB),如Hi3861V100
  • 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300
+
+ +- init启动引导组件: + - 配置文件init.cfg烧写到单板之后变成只读模式,修改时必须重新打包和烧写rootfs镜像。 + - 配置文件init.cfg仅支持json格式。 + +- bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。 +- syspara系统属性组件:SetParameter/GetParameter仅支持uid大于1000的应用调用。 + diff --git "a/zh-cn/device-dev/subsystems/\345\217\202\350\200\203.md" b/zh-cn/device-dev/subsystems/subsys-boot-ref.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\217\202\350\200\203.md" rename to zh-cn/device-dev/subsystems/subsys-boot-ref.md diff --git "a/zh-cn/device-dev/subsystems/syspara\347\263\273\347\273\237\345\261\236\346\200\247\347\273\204\344\273\266.md" b/zh-cn/device-dev/subsystems/subsys-boot-syspara.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/syspara\347\263\273\347\273\237\345\261\236\346\200\247\347\273\204\344\273\266.md" rename to zh-cn/device-dev/subsystems/subsys-boot-syspara.md diff --git a/zh-cn/device-dev/subsystems/subsys-boot.md b/zh-cn/device-dev/subsystems/subsys-boot.md new file mode 100644 index 0000000000000000000000000000000000000000..a71c6ab86284f1d1dca602c5e7fffd2aae961f7f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-boot.md @@ -0,0 +1,17 @@ +# 启动恢复 + +- **[启动恢复子系统概述](subsys-boot-overview.md)** + +- **[init启动引导组件](subsys-boot-init.md)** + +- **[appspawn应用孵化组件](subsys-boot-appspawn.md)** + +- **[bootstrap服务启动组件](subsys-boot-bootstrap.md)** + +- **[syspara系统属性组件](subsys-boot-syspara.md)** + +- **[常见问题](subsys-boot-faqs.md)** + +- **[参考](subsys-boot-ref.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md new file mode 100644 index 0000000000000000000000000000000000000000..dc07da91d5c8c7967965ba91ae1ed276279eb8f7 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-mini-lite.md @@ -0,0 +1,996 @@ +# 轻量和小型系统编译构建指导 + +- [概述](#section10958256161119) + - [基本概念](#section1732301411128) + - [目录结构](#section1588744014121) + - [构建流程](#section15761735134) + +- [配置规则](#section2345183962710) + - [组件](#section142532518308) + - [芯片解决方案](#section121501451143710) + - [产品解决方案](#section134549283435) + +- [使用指导](#section13754457192211) + - [前提条件](#section31651120233) + - [hb工具使用说明](#section1133304172313) + - [新增组件](#section167110415315) + - [新增芯片解决方案](#section1474718565412) + - [新增产品解决方案](#section1097623294220) + +- [常见问题](#section19909721104319) + - [ninja版本问题导致编译失败](#section138233464318) + - [ncurses库缺失导致编译失败](#section151033911442) + - [未安装mcopy导致编译失败](#section19811838104418) + - [权限问题导致编译失败](#section03111118451) + - [未安装Crypto导致编译失败](#section69981127125013) + - [编译环境为shell导致编译失败](#section967617530505) + + +## 概述 + +一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: + +- 支持按组件拼装产品并编译。 + +- 独立构建芯片解决方案厂商源码。 +- 独立构建单个组件。 + +### 基本概念 + +在使用编译构建子系统前,应了解如下基本概念: + +- 子系统 + + 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 + + +- 组件 + + 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 + +- gn + + Generate ninja的缩写,用于产生ninja文件。 + +- ninja + + ninja是一个专注于速度的小型构建系统。 + +- hb + + OpenHarmony的命令行工具,用来执行编译命令。 + + +### 目录结构 + +``` +build/lite +├── components # 组件描述文件 +├── figures # readme中的图片 +├── hb # hb pip安装包源码 +├── make_rootfs # 文件系统镜像制作脚本 +├── config # 编译配置项 +│ ├── component # 组件相关的模板定义 +│ ├── kernel # 内核相关的编译配置 +│ └── subsystem # 子系统编译配置 +├── platform # ld脚本 +├── testfwk # 测试编译框架 +└── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 +``` + +### 构建流程 + +编译构建流程如[图1 ](#fig9744112715161)所示,主要分设置和编译两步: + +**图 1** 编译构建流程 +![](figure/编译构建流程.jpg "编译构建流程") + +1. hb set: 设置OpenHarmony源码目录和要编译的产品。 +2. hb build: 编译产品、开发板或者组件。编译主要过程如下: + - 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 + - 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 + - 调用ninja:调用ninja -C out/board/product启动编译。 + - 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 + + +## 配置规则 + +为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: + +### **组件** + +组件源码路径命名规则为:**\{领域\}/\{子系统\}/\{组件\}**,组件目录树规则如下: + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 + +``` +component +├── interfaces +│ ├── innerkits # 系统内接口,组件间使用 +│ └── kits # 应用接口,应用开发者使用 +├── frameworks # framework实现 +├── services # service实现 +└── BUILD.gn # 组件编译脚本 +``` + +以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: + +``` +{ + "components": [ + { + "component": "sensor_lite", # 组件名称 + "description": "Sensor services", # 组件一句话功能描述 + "optional": "true", # 组件是否为最小系统必选 + "dirs": [ # 组件源码路径 + "base/sensors/sensor_lite" + ], + "targets": [ # 组件编译入口 + "//base/sensors/sensor_lite/services:sensor_service" + ], + "rom": "92KB", # 组件ROM值 + "ram": "~200KB", # 组件RAM估值 + "output": [ "libsensor_frameworks.so" ], # 组件编译输出 + "adapted_kernel": [ "liteos_a" ], # 组件已适配的内核 + "features": [], # 组件可配置的特性 + "deps": { + "components": [ # 组件依赖的其他组件 + "samgr_lite", + "ipc_lite" + + ], + "third_party": [ # 组件依赖的三方开源软件 + "bounds_checking_function" + ] + } + } + ] +} +``` + +组件BUILD.gn的编写建议如下: + +- 编译目标名称与组件一致。 +- 组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos\_\{subsystem\}\_\{component\}\_\{feature\}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 +- 宏定义规则:OHOS\_\{SUBSYSTEM\}\_\{COMPONENT\}\_\{FEATURE\} + + >![](../public_sys-resources/icon-note.gif) **说明:** + >组件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。 + + +以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: + +``` + # 声明组件可配置的特性 + declare_args() { + enable_ohos_graphic_ui_animator = false # 动效特性开关 + ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap + } + + # 组件基础功能 + shared_library("base") { + sources = [ + ...... + ] + include_dirs = [ + ...... + ] + } + + # 仅在animator开启时编译 + if(enable_ohos_graphic_ui_animator ) { + shared_library("animator") { + sources = [ + ...... + ] + include_dirs = [ + ...... + ] + deps = [ :base ] + } + } + ...... + # target名称建议与组件名称一致, 组件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等 + executable("ui") { + deps = [ + ":base" + ] + + # animator特性由产品配置 + if(enable_ohos_graphic_ui_animator ) { + deps += [ + "animator" + ] + } + } +``` + +### **芯片解决方案** + +- 芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。 +- 芯片解决方案是一个特殊的组件,源码路径规则为:**device/\{芯片解决方案厂商\}/\{开发板\}**。 +- 芯片解决方案组件会随产品选择的开发板默认编译。 + +芯片解决方案目录树规则如下: + +``` +device +└── company # 芯片解决方案厂商 + └── board # 开发板名称 + ├── BUILD.gn # 编译脚本 + ├── hals # OS南向接口适配 + ├── linux # 可选,linux内核版本 + │ └── config.gni # linux版本编译配置 + └── liteos_a # 可选,liteos内核版本 + └── config.gni # liteos_a版本编译配置 +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>config.gni为开发板编译相关的配置,编译时会采用该配置文件中的参数编译所有OS组件,编译阶段系统全局可见。 + +config.gni的关键字段介绍如下: + +``` +kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 +kernel_version: 开发使用的内核版本,例如:“4.19”。 +board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 +board_arch: 开发芯片arch, 例如: “armv7-a”, “rv32imac”。 +board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 +board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 +board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 +board_cflags: 开发板配置的c文件编译选项。 +board_cxx_flags: 开发板配置的cpp文件编译选项。 +board_ld_flags: 开发板配置的链接选项。 +``` + +### **产品解决方案** + +产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。产品解决方案的源码路径规则为:**vendor/\{产品解决方案厂商\}/\{产品名称\}**_。_产品解决方案也是一个特殊的组件。 + +产品解决方案的目录树规则如下: + +``` +vendor +└── company # 产品解决方案厂商 + ├── product # 产品名称 + │ ├── init_configs + │ │ ├── etc # init进程启动配置(可选,仅linux内核需要) + │ │ └── init.cfg # 系统服务启动配置 + │ ├── hals # 产品解决方案OS适配 + │ ├── BUILD.gn # 产品编译脚本 + │ └── config.json # 产品配置文件 + │ └── fs.yml # 文件系统打包配置 + └── ...... +``` + +>![](../public_sys-resources/icon-caution.gif) **注意:** +>**新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。** + +关键的目录和文件详细介绍如下: + +1. **vendor/company/product/init\_configs/etc** + + 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本。init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS-\>fstab-\>S00-xxx“。Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 + +2. **vendor/company/product/init\_configs/init.cfg** + + init进程启动服务的配置文件,当前支持解析的命令有: + + - start: 启动某个服务 + - mkdir: 创建文件夹 + - chmod: 修改指定路径/文件的权限 + - chown: 修改指定路径/文件的属组 + - mount: 挂载命令 + + 该文件中的各个字段的解释如下: + + ``` + { + "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 + "name" : "pre-init", + "cmds" : [ + "mkdir /storage/data", # 创建目录 + "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 + "mkdir /storage/data/log", + "chmod 0755 /storage/data/log", + "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid + ...... + "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] + # 其中flags仅支持:nodev、noexec、nosuid和rdonly + ] + }, { + "name" : "init", + "cmds" : [ # 按cmds数组顺序启动启动服务 + "start shell", # 注意:start与服务名称之间有且只有一个空格 + ...... + "start service1" + ] + }, { + "name" : "post-init", # 最后执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) + "cmds" : [] + } + ], + "services" : [{ # service数组,一个service对应一个进程 + "name" : "shell", # 服务名称 + "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 + "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 + "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 + "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 + "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 + "caps" : [4294967295] + }, + ...... + ] + } + ``` + +3. **vendor/company/product/init\_configs/hals** + + 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 + +4. **vendor/company/product/config.json** + + config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。 + + 以基于hispark\_taurus开发板的ipcamera产品为例,配置文件如下: + + ``` + { + "product_name": "ipcamera", # 产品名称 + "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 + "device_company": "hisilicon", # 芯片厂商 + "board": "hispark_taurus", # 开发板名称 + "kernel_type": "liteos_a", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "aafwk", # 选择的子系统 + "components": [ + { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 + ] + }, + { + ...... + } + ...... + 更多子系统和组件 + } + } + ``` + +5. **vendor/company/product/fs.yml** + + 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: + + ``` + fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs + fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 + source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 + target_dir: 必填,文件系统下对应文件目录 + ignore_files:选填,声明拷贝忽略文件 + dir_mode: 选填,文件目录权限,默认755 + file_mode: 选填,该文件目录下所有文件的权限,默认555 + fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 + file_dir: 必填,文件系统下具体文件路径 + file_mode: 必填,文件权限声明 + fs_symlink: 选填,配置文件系统软连接 + fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 + fs_attr: 选填,根据配置项动态调整文件系统 + ``` + + 其中fs\_symlink、fs\_make\_cmd字段支持以下变量: + + - $\{root\_path\} + + 代码根目录,对应gn的$\{ohos\_root\_path\} + + - $\{out\_path\} + + 产品out目录,对应gn的$\{root\_out\_dir\} + + - $\{fs\_dir\} + + 文件系统目录,由以下变量拼接而成 + + - $\{root\_path\} + - $\{fs\_dir\_name\} + + + >![](../public_sys-resources/icon-note.gif) **说明:** + >fs.yml是可选的,对于没有文件系统的设备可不配置。 + +6. **vendor/company/product/BUILD.gn** + + 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: + + ``` + group("product") { # target名称需与product名称即三级目录名称一致 + deps = [] + # 拷贝init配置 + deps += [ "init_configs" ] + # 其他 + ...... + } + ``` + + +## 使用指导 + +### 前提条件 + +开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建系统基础环境](../quick-start/quickstart-lite-env-setup.md)。 + +### hb工具使用说明 + +hb是OpenHarmony的命令行工具,用来执行编译命令。以下对hb的常用命令进行说明。 + +**hb set** + +``` +hb set -h +usage: hb set [-h] [-root [ROOT_PATH]] [-p] + +optional arguments: + -h, --help show this help message and exit + -root [ROOT_PATH], --root_path [ROOT_PATH] + Set OHOS root path + -p, --product Set OHOS board and kernel +``` + +- hb set 后无参数,进入默认设置流程 +- hb set -root dir可直接设置代码根目录 +- hb set -p设置要编译的产品 + +**hb env** + +查看当前设置信息 + +``` +hb env +[OHOS INFO] root path: xxx +[OHOS INFO] board: hispark_taurus +[OHOS INFO] kernel: liteos +[OHOS INFO] product: ipcamera +[OHOS INFO] product path: xxx/vendor/hisilicon/ipcamera +[OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19 +``` + +**hb build** + +``` +hb build -h +usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] + [--dmverity] [--tee] [-p PRODUCT] [-f] [-n] + [-T [TARGET [TARGET ...]]] [-v] [-shs] [--patch] + [component [component ...]] + +positional arguments: + component name of the component + +optional arguments: + -h, --help show this help message and exit + -b BUILD_TYPE, --build_type BUILD_TYPE + release or debug version + -c COMPILER, --compiler COMPILER + specify compiler + -t [TEST [TEST ...]], --test [TEST [TEST ...]] + compile test suit + --dmverity Enable dmverity + --tee Enable tee + -p PRODUCT, --product PRODUCT + build a specified product with + {product_name}@{company}, eg: camera@huawei + -f, --full full code compilation + -n, --ndk compile ndk + -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] + Compile single target + -v, --verbose show all command lines while building + -shs, --sign_haps_by_server + sign haps by server + --patch apply product patch before compiling + + --dmverity Enable dmverity + -p PRODUCT, --product PRODUCT + build a specified product with + {product_name}@{company}, eg: ipcamera@hisilcon + -f, --full full code compilation + -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] + Compile single target +``` + +- hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. +- hb build \{component\_name\}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv\_store\)。 +- hb build -p ipcamera@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 +- 在device/device\_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 + +**hb clean** + +清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。 + +``` +hb clean +usage: hb clean [-h] [out_path] + +positional arguments: + out_path clean a specified path. + +optional arguments: + -h, --help show this help message and exit +``` + +### 新增组件 + +本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增: + +1. 源码开发完成后,添加组件编译脚本。 + + 以编译组件hello\_world可执行文件为例,applications/sample/hello\_world/BUILD.gn可以写为: + + ``` + executable("hello_world") { + include_dirs = [ + "include", + ] + sources = [ + "src/hello_world.c" + ] + } + ``` + + 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello\_world的可执行文件。 + + 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: + + ``` + hb build -f -T //applications/sample/hello_world + ``` + + 组件在开发板上功能验证完成后,可按[步骤2\~4](#li11471037297)将组件配置到产品中。 + +2. 添加组件描述。 + + 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: + + - component:组件名称。 + - description:组件的一句话功能描述。 + - optional:组件是否为系统可选。 + - dirs:组件源码路径。 + - targets:组件编译入口。 + + 以将hello\_world组件加入应用子系统为例,在applications.json中添加hello\_world对象: + + ``` + { + "components": [ + { + "component": "hello_world", + "description": "Hello world.", + "optional": "true", + "dirs": [ + "applications/sample/hello_world" + ], + "targets": [ + "//applications/sample/hello_world" + ] + }, + ... + ] + } + ``` + +3. 将组件配置到产品。 + + 产品的配置文件config.json位于位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello\_world组件加入产品配置文件my\_product.json中为例,加入hello\_wolrd对象: + + ``` + { + "product_name": "hello_world_test", + "ohos_version": "OpenHarmony 1.0", + "device_company": "hisilicon", + "board": "hispark_taurus", + "kernel_type": "liteos_a", + "kernel_version": "1.0.0", + "subsystems": [ + { + "subsystem": "applications", + "components": [ + { "component": "hello_world", "features":[] } + ] + }, + ... + ] + } + ``` + +4. 编译产品。 + + 1. 代码根目录输入hb set选择对应产品。 + + 2. 执行hb build。 + + +### 新增芯片解决方案 + +编译构建支持添加新的芯片解决方案厂商,具体步骤如下: + +1. 创建芯片解决方案目录。 + + 按照[芯片解决方案配置规则](#section1625463413327)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: + + ``` + mkdir -p device/realtek/rtl8720 + ``` + +2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 + + 以realtek的“rtl8720“开发板的liteos\_m适配为例,device/realtek/rtl8720/liteos\_a/config.gni的内容如下: + + ``` + # Kernel type, e.g. "linux", "liteos_a", "liteos_m". + kernel_type = "liteos_a" + + # Kernel version. + kernel_version = "3.0.0" + + # Board CPU type, e.g. "cortex-a7", "riscv32". + board_cpu = "real-m300" + + # Board arch, e.g. "armv7-a", "rv32imac". + board_arch = "" + + # Toolchain name used for system compiling. + # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. + # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. + board_toolchain = "gcc-arm-none-eabi" + + # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. + board_toolchain_path = + rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", + root_build_dir) + + # Compiler prefix. + board_toolchain_prefix = "gcc-arm-none-eabi-" + + # Compiler type, "gcc" or "clang". + board_toolchain_type = "gcc" + + # Board related common compile flags. + board_cflags = [] + board_cxx_flags = [] + board_ld_flags = [] + ``` + +3. 编写编译脚本。 + + 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: + + ``` + group("rtl8720") { # target类型也可以shared_library, static_library, executable + # 具体内容 + ...... + } + ``` + +4. 编译芯片解决方案。 + + 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 + + +### 新增产品解决方案 + +编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: + +1. 创建产品目录 + + 按照[产品解决方案配置规则](#section1625463413327)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: + + ``` + mkdir -p vendor/my_company/wifiiot + ``` + +2. 拼装产品 + + 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my\_company/wifiiot/config.json可以是: + + ``` + { + "product_name": "wifiiot", # 产品名称 + "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 + "device_company": "realtek", # 芯片解决方案厂商名称 + "board": "rtl8720", # 开发板名称 + "kernel_type": "liteos_m", # 选择的内核类型 + "kernel_version": "3.0.0", # 选择的内核版本 + "subsystems": [ + { + "subsystem": "kernel", # 选择的子系统 + "components": [ + { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 + ] + }, + ... + { + 更多子系统和组件 + } + ] + } + ``` + + 注意:编译构建系统编译前会对device\_company,board,kernel\_type,kernel\_version、subsystem、component字段进行有效性检查,其中device\_company,board,kernel\_type,kernel\_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 + +3. 适配OS接口 + + 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 + +4. 配置系统服务 + + 在产品目录下创建init\_configs目录,并在init\_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 + +5. 配置init进程(仅linux内核需要) + + 在init\_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 + +6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) + + 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: + + ``` + - + fs_dir_name: rootfs # 镜像的名称 + fs_dirs: + - + # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin + source_dir: bin + target_dir: bin + ignore_files: + - Test.bin + - TestSuite.bin + - + # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 + source_dir: libs + target_dir: lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: usr/lib + target_dir: usr/lib + ignore_files: + - .a + dir_mode: 755 + file_mode: 644 + - + source_dir: config + target_dir: etc + - + source_dir: system + target_dir: system + - + source_dir: sbin + target_dir: sbin + - + source_dir: usr/bin + target_dir: usr/bin + - + source_dir: usr/sbin + target_dir: usr/sbin + - + # 创建一个proc空目录 + target_dir: proc + - + target_dir: mnt + - + target_dir: opt + - + target_dir: tmp + - + target_dir: var + - + target_dir: sys + - + source_dir: etc + target_dir: etc + - + source_dir: vendor + target_dir: vendor + - + target_dir: storage + + fs_filemode: + - + file_dir: lib/ld-uClibc-0.9.33.2.so + file_mode: 555 + - + file_dir: lib/ld-2.24.so + file_mode: 555 + - + file_dir: etc/init.cfg + file_mode: 400 + fs_symlink: + - + # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so + source: libc.so + link_name: ${fs_dir}/lib/ld-musl-arm.so.1 + - + source: mksh + link_name: ${fs_dir}/bin/sh + - + source: mksh + link_name: ${fs_dir}/bin/shell + fs_make_cmd: + # 使用脚本将rootfs制作为ext4格式的image + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + - + fs_dir_name: userfs + fs_dirs: + - + source_dir: storage/etc + target_dir: etc + - + source_dir: data + target_dir: data + fs_make_cmd: + - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 + + ``` + +7. 配置产品Patch(可选,视产品涉及组件是否需要打补丁而定) + + 在产品目录下创建patch.yml文件。patch.yml需按产品实际情况配置,一个典型的patch.yml文件如下: + + ``` + # 需要打patch的路径 + foundation/communication/dsoftbus: + # 该路径下需要打的patch存放路径 + - foundation/communication/dsoftbus/1.patch + - foundation/communication/dsoftbus/2.patch + third_party/wpa_supplicant: + - third_party/wpa_supplicant/1.patch + - third_party/wpa_supplicant/2.patch + - third_party/wpa_supplicant/3.patch + ... + ``` + + 配置完成后,编译时增加--patch参数,即可在产品编译前将配置的Patch文件打到对应目录中,再进行编译: + + ``` + hb build -f --patch + ``` + +8. 编写编译脚本 + + 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: + + ``` + group("wifiiot") { # target名称与产品名一致 + deps = [] + # 拷贝init配置 + deps += [ "init_configs" ] + # 将hals加入编译 + deps += [ "hals" ] + # 其他 + ...... + } + ``` + +9. 编译产品。 + + 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 + + +## 常见问题 + +### ninja版本问题导致编译失败 + +- **现象描述:** + + 编译失败,提示“usr/sbin/ninja: invalid option -- w”。 + +- **可能原因:** + + 编译环境中ninja版本太低,不支持--w选项。 + +- **解决办法:** + + 卸载环境中ninja和gn,按照HarmonyOS官网[获取工具](../get-code/gettools-ide.md)。 + + +### ncurses库缺失导致编译失败 + +- **现象描述:** + + 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 + +- **可能原因:** + + 编译环境ncurses库缺失。 + +- **解决办法:** + + ``` + sudo apt-get install lib32ncurses5-dev + ``` + + +### 未安装mcopy导致编译失败 + +- **现象描述:** + + ​编译失败,提示“line 77: mcopy: command not found”。 + +- **可能原因:** + + 编译环境未安装mcopy。 + +- **解决办法:** + + ``` + ​sudo apt-get install dosfstools mtools + ``` + + +### 权限问题导致编译失败 + +- **现象描述:** + + 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 + +- ​**可能原因:** + + 当前用户对riscv编译器路径下的文件访问权限不够。 + +- ​**解决办法:** + + 查询gcc\_riscv32所在目录。 + + ``` + which riscv32-unknown-elf-gcc + ``` + + 使用chmod命令修改目录权限为755。 + + +### 未安装Crypto导致编译失败 + +- **现象描述:** + + 编译失败,提示“No module named 'Crypto'”。 + +- **可能原因:** + + python3未安装Crypto。 + +- **解决办法:** + 1. 查询Python版本号。 + + ``` + python3 --version + ``` + + 2. 需使用python3.7以上版本,然后安装pycryptodome。 + + ``` + sudo pip3 install pycryptodome + ``` + + + +### 编译环境为shell导致编译失败 + +- **现象描述:** + + 编译失败:“xx.sh \[: xx unexpected operator”。 + +- **可能原因:** + + 编译环境shell不是bash。 + +- **解决办法:** + + ``` + sudo rm -rf /bin/sh + sudo ln -s /bin/bash /bin/sh + ``` + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-mini.md b/zh-cn/device-dev/subsystems/subsys-build-mini.md new file mode 100644 index 0000000000000000000000000000000000000000..df6e2e0c54c21c72fbecedb3c1c6dbf7132c87ed --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-mini.md @@ -0,0 +1,5 @@ +# 轻量和小型系统编译构建指导 + +- **[编译构建子系统—轻量和小型系统](subsys-build-mini-lite.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard-large.md b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md new file mode 100644 index 0000000000000000000000000000000000000000..9259a8073d9ae1a35c3fc17d4757bee73d72dab9 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-standard-large.md @@ -0,0 +1,235 @@ +# 标准系统编译构建指导 + +- [概述](#section17466112012244) + - [基本概念](#section445513507246) + - [运作机制](#section12541217142510) + - [约束与限制](#section886933762513) + +- [编译构建使用指导](#section16901215262) + - [目录结构](#section109065332264) + - [编译命令](#section123265539266) + - [开发步骤](#section591084422719) + + +## 概述 + +编译构建子系统提供了一个基于gn和ninja的编译构建框架。主要提供以下功能: + +- 构建不同芯片平台的产品。如:Hi3516DV300平台。 + +- 根据产品配置可以按照组件组装打包产品需要的能力。 + +### 基本概念 + +在了解编译构建子系统的能力前,应了解如下基本概念: + +- 平台 + + 开发板和内核的组合,不同平台支持的子系统和组件不同。 + +- 子系统 + + OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 + +- 组件 + + 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 + +- gn + + Generate ninja的缩写,用于产生ninja文件。 + +- ninja + + ninja是一个专注于速度的小型构建系统。 + + +### 运作机制 + +OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: + +- 命令行解析:解析待编译的产品名称,加载相关配置。 +- 调用gn: 根据命令行解析的产品名称和编译类型,配置编译工具链和全局的编译选项。 +- 执行ninja:启动编译并生成对应的产品版本。 + +### 约束与限制 + +- 需按照[源码获取](../get-code/sourcecode-acquire.md)指导下载全量源码(采用方式三获取)。 +- 编译环境需要Ubuntu18.04及以上版本。 +- 安装编译所需的程序包。 + + 安装命令: + + ``` + sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 + ``` + + +## 编译构建使用指导 + +### 目录结构 + +``` +/build # 编译构建主目录 +├── config # 编译相关的配置项 +├── core +│ └── gn # 编译入口BUILD.gn配置 +├── loader # 各个组件配置加载、模板生成 +├── ohos # OpenHarmony编译打包流程配置 +│ ├── kits # kits编译打包模板和处理流程 +│ ├── ndk # ndk模板和处理流程 +│ ├── notice # notice模板和处理流程 +│ ├── packages # 版本打包模板和处理流程 +│ ├── sa_profile # sa模板和处理流程 +│ ├── sdk # sdk模板和处理流程,包括sdk中包含的模块配置 +│ └── testfwk # 测试相关的处理 +├── scripts # 编译相关的python脚本 +├── templates # c/c++编译模板定义 +└── toolchain # 编译工具链配置 +``` + +### 编译命令 + +- 代码根目录下执行全量版本的编译命令: + + ``` + ./build.sh --product-name {product_name} + ``` + + \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 + + 编译完成后,结果镜像保存在 out/ohos-arm-release/packages/phone/images/ 目录下。 + +- 编译命令支持选项: + + ``` + --product-name # 必须 编译的产品名称,如:Hi3516DV300 + --build-target # 可选 指定编译目标,可以指定多个 + --gn-args # 可选 gn参数,支持指定多个 + --ccache # 可选 编译使用ccache,需要本地安装ccache + ``` + + +### 开发步骤 + +1. 添加组件。 + + 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 + + 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 + + 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem\_examples子系统中(subsystem\_examples子系统定义在test/examples/目录)。 + + 示例组件partA的完整目录结构如下: + + ``` + test/examples/partA + ├── feature1 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld1.h + │ └── src + │ └── helloworld1.cpp + ├── feature2 + │ ├── BUILD.gn + │ ├── include + │ │ └── helloworld2.h + │ └── src + │ └── helloworld2.cpp + └── feature3 + ├── BUILD.gn + └── src + └── config.conf + ``` + + 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: + + ``` + config("helloworld_lib_config") { + include_dirs = [ "include" ] + } + + ohos_shared_library("helloworld_lib") { + sources = [ + "include/helloworld1.h", + "src/helloworld1.cpp", + ] + public_configs = [ ":helloworld_lib_config" ] + part_name = "partA" + } + ``` + + 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: + + ``` + ohos_executable("helloworld_bin") { + sources = [ + "src/helloworld2.cpp" + ] + include_dirs = [ "include" ] + deps = [ # 依赖组件内模块 + "../feature1:helloworld_lib" + ] + external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” + install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 + part_name = "partA" + } + ``` + + 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: + + ``` + ohos_prebuilt_etc("feature3_etc") { + source = "src/config.conf" + relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 + part_name = "partA" + } + ``` + + 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: + + ``` + "partA": { + "module_list": [ + "//test/examples/partA/feature1:helloworld_lib", + "//test/examples/partA/feature2:helloworld_bin", + "//test/examples/partA/feature3:feature3_etc", + ], + "inner_kits": [ + + ], + "system_kits": [ + + ], + "test_list": [ + + ] + } + ``` + + 一个组件包含module\_list、inner\_kits、system\_kits、test\_list四个部分的声明,其中: + + - module\_list:组件所包含的模块列表; + - inner\_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external\_deps中添加依赖的模块; + - system\_kits:组件提供给开发者开发应用的接口; + - test\_list:组件中对应模块的测试用例; + +2. 将组件添加到产品配置中。 + + 在产品的配置中添加组件,产品对应的配置文件:productdefine/common/products/\{product-name\}.json。 + + 在产品配置文件中添加 "subsystem\_examples:partA",表示该产品中会编译并打包partA到版本中。 + +3. 编译。 + + 以编译Hi3516DV300为例,编译命令如下: + + ``` + ./build.sh --product-name Hi3516DV300 --ccache + ``` + +4. 编译输出。 + + 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 + + diff --git a/zh-cn/device-dev/subsystems/subsys-build-standard.md b/zh-cn/device-dev/subsystems/subsys-build-standard.md new file mode 100644 index 0000000000000000000000000000000000000000..d5d5ce6278bf65d44db5da6b8b7734e22463b486 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build-standard.md @@ -0,0 +1,5 @@ +# 标准系统编译构建指导 + +- **[编译构建子系统—标准系统](subsys-build-standard-large.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-build.md b/zh-cn/device-dev/subsystems/subsys-build.md new file mode 100644 index 0000000000000000000000000000000000000000..487b7bf7b22db66cf401cda724f9236f343e0a8a --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-build.md @@ -0,0 +1,7 @@ +# 编译构建 + +- **[轻量和小型系统编译构建指导](subsys-build-mini-lite.md)** + +- **[标准系统编译构建指导](subsys-build-standard-large.md)** + + diff --git "a/zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\345\256\236\344\276\213.md" b/zh-cn/device-dev/subsystems/subsys-densor-demo.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/Sensor\346\234\215\345\212\241\345\255\220\347\263\273\344\275\277\347\224\250\345\256\236\344\276\213.md" rename to zh-cn/device-dev/subsystems/subsys-densor-demo.md diff --git a/zh-cn/device-dev/subsystems/subsys-densor-guide.md b/zh-cn/device-dev/subsystems/subsys-densor-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..b8d7fa3101e40fe532be50aadfe065bdbd5dca9b --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-densor-guide.md @@ -0,0 +1,72 @@ +# Sensor服务子系使用指导 + +- [使用步骤](#section18816105182315) + +下面使用步骤以sensorTypeId为0的传感器为例,其他类型的传感器使用方式类似。 + +## 使用步骤 + +1. 导入需要的包 + +``` +#include "sensor_agent.h" +#include "sensor_agent_type.h" +``` + +1. 创建传感器回调函数 + +``` +void SensorDataCallbackImpl(SensorEvent *event) +{ + if(event == NULL){ + return; + } + float *sensorData=(float *)event->data; +} +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>回调函数的格式为RecordSensorCallback类型。 + +1. 获取设备支持sensor列表 + +``` +SensorInfo *sensorInfo = (SensorInfo *)NULL; +int32_t count = 0; +int32_t ret = GetAllSensors(&sensorInfo, &count); +``` + +1. 创建的传感器用户 + +``` +SensorUser sensorUser; +sensorUser.callback = SensorDataCallbackImpl; //成员变量callback指向创建的回调方法 +``` + +1. 使能传感器 + +``` +int32_t ret = ActivateSensor(0, &sensorUser); +``` + +1. 订阅传感器数据 + +``` +int32_t ret = SubscribeSensor(0, &sensorUser); +``` + +>![](../public_sys-resources/icon-note.gif) **说明:** +>到这步就可以在实现的回调方法中获取到传感器数据。 + +1. 取消传感器数据订阅 + +``` +int32_t ret = UnsubscribeSensor(0, &sensorUser); +``` + +1. 去使能一个传感器 + +``` +int32_t ret = DeactivateSensor(0, &sensorUser); +``` + diff --git a/zh-cn/device-dev/subsystems/subsys-densor-overview.md b/zh-cn/device-dev/subsystems/subsys-densor-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..caee5f57cad7a17eef842b59aba1eec3de56a1a0 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-densor-overview.md @@ -0,0 +1,99 @@ +# Sensor服务子系概述 + +- [简介](#section667413271505) +- [接口说明](#section7255104114110) + +## 简介 + +Sensor服务子系统提供了轻量级传感器服务基础框架,您可以使用该框架接口实现传感器列表查询、传感器控制、传感器订阅去订阅等功能。轻量级传感器服务框架如下图所示: + +**图1** Sensor服务框架图 + +![](figure/zh-cn_image_0000001077724150.png) + +- Sensor API:提供传感器的基础API,主要包含查询传感器的列表、订阅/取消传感器数据、执行控制命令等,简化应用开发。 +- Sensor Framework:主要实现传感器的订阅管理、数据通道的创建、销毁等,实现与传感器服务层的通信。 +- Sensor Service:主要实现HDF层数据接收、解析、分发,对设备传感器的管理,数据上报管理以及传感器权限管控等。 + +## 接口说明 + +**表 1** Sensor服务框架API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

接口说明

+

参数要求

+

int32_t GetAllSensors(SensorInfo **sensorInfo, int32_t *count)

+

作用:获取系统中所有传感器的信息。

+

返回值:0表示成功,其他返回值表示失败。

+

sensorInfo(NOT NULL):输出系统中所有传感器的信息;

+

count(NOT NULL):输出系统中所有传感器的数量。

+

int32_t SubscribeSensor(int32_t sensorTypeId, SensorUser *user)

+

作用:订阅传感器数据,系统会将获取到的传感器数据上报给订阅者。

+

返回值: 0为成功,其他返回值表示失败。

+

sensorTypeId:唯一标识一个传感器类型;

+

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

+

int32_t UnsubscribeSensor(int32_t sensorTypeId, SensorUser *user)

+

作用:去订阅传感器数据,系统将取消传感器数据上报给订阅者。

+

返回值:0为成功,其他返回值表示失败。

+

sensorTypeId:唯一标识一个传感器类型;

+

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

+

int32_t SetBatch(int32_t sensorTypeId, SensorUser *user, int64_t samplingInterval, int64_t reportInterval)

+

作用:设置传感器的数据采样间隔和数据上报间隔

+

返回值:0为成功,其他返回值表示失败。

+

sensorTypeId:唯一标识一个传感器类型;

+

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

+

samplingInterval:传感器数据采样间隔,单位纳秒;

+

reportInterval:传感器数据上报间隔,单位纳秒。

+

int32_t ActivateSensor(int32_t sensorTypeId, SensorUser *user)

+

作用:使能一个传感器订阅用户。

+

返回值:0为成功,其他返回值表示失败。

+

sensorTypeId:唯一标识一个传感器类型;

+

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

+

int32_t DeactivateSensor(int32_t sensorTypeId, SensorUser *user)

+

作用:去使能一个传感器订阅用户

+

返回值:0为成功,其他返回值表示失败。

+

sensorTypeId:唯一标识一个传感器类型;

+

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器。

+

int32_t SetMode(int32_t sensorTypeId, SensorUser *user, int32_t mode)

+

作用:设置传感器的工作模式

+

返回值:0为成功,其他返回值表示失败。

+

sensorTypeId:唯一标识一个传感器类型;

+

user(NOT NULL):传感器的用户,用于从传感器获取数据,一般一个用户只属于一个传感器;

+

mode:传感器的数据上报模式。

+
+ diff --git a/zh-cn/device-dev/subsystems/subsys-densor.md b/zh-cn/device-dev/subsystems/subsys-densor.md new file mode 100644 index 0000000000000000000000000000000000000000..2c5ea0dbbeeab7689d3120089e1f91e994cac8bb --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-densor.md @@ -0,0 +1,9 @@ +# Sensor服务 + +- **[Sensor服务子系概述](subsys-densor-overview.md)** + +- **[Sensor服务子系使用指导](subsys-densor-guide.md)** + +- **[Sensor服务子系使用实例](subsys-densor-demo.md)** + + diff --git "a/zh-cn/device-dev/subsystems/HiLog_Lite\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/HiLog_Lite\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-hilog-lite.md diff --git "a/zh-cn/device-dev/subsystems/HiLog\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/HiLog\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-hilog-rich.md diff --git "a/zh-cn/device-dev/subsystems/HiSysEvent\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/HiSysEvent\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-hisysevent.md diff --git a/zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md b/zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md new file mode 100644 index 0000000000000000000000000000000000000000..333dd112b45fe83e91673798d6fd125db71747e3 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx-hisyseventread.md @@ -0,0 +1,103 @@ +# HiSysEvent订阅指导 + +- [概述](#section315316685112) +- [接口说明](#section0342191810519) +- [开发实例](#section123181432175110) + +## 概述 + +HiSysEvent提供了跨进程订阅机制,用户可以通过注册订阅接口。 + +## 接口说明 + +**表 1** HiSysEvent订阅接口 + + + + + + + + + + + + + +

接口名

+

描述

+

int ISysEventService::AddListener(in SysEventRule[] rules, in ISysEventCallback callback)

+

接口功能:订阅HiSysEvent事件。

+

输入参数:

+
  • rules:事件订阅规则
  • callback:订阅回调对象
+

返回值:

+
  • 0:订阅成功,重复订阅
  • 1:订阅成功,初次订阅
  • 其他返回值:订阅失败
+

void ISysEventCallback::Handle(in String domain, in String eventName, in int eventType, in String eventDetail)

+

接口功能:订阅事件的回调接口。

+

输入参数:

+
  • domain:事件所属领域
  • eventName:事件的名称
  • eventType:事件类型
  • eventDetail:包含事件相关信息的字符串,以json的形式体现
+

返回值:无。

+
+ +**表 2** SysEventRule订阅规则对象 + + + + + + + + + + + + + + + + +

属性名称

+

描述

+

uint32_t ruleType

+

规则类型(匹配范围包括domain以及eventName):

+
  • 1:全字符匹配
  • 2:前缀匹配
  • 3:正则表达式匹配
  • 其他值:无效的匹配方式
+

std::string domain;

+
  • domain:事件所属领域,如果传入的是空字符串,则默认事件领域字段匹配成功
+

std::string eventName

+
  • eventName:事件的名称,如果传入的是空字符串,则默认事件名称字段匹配成功
+
+ +## 开发实例 + +1. 源代码开发: + + 引入对应的aidl文件,包括:ISysEventService.aidl、SysEventRule.aidl、ISysEventCallback.aidl。 + + 在相应的业务逻辑里面调用ISysEventService::AddListener\(in SysEventRule\[\] rules, in ISysEventCallback callback\)接口。 + + 实现对应的回调对象: + + ISysEventCallback::Handle\(in String domain, in String eventName, in int eventType, in String eventDetail\) + + +1. 源代码开发: + + 引入对应的aidl文件,包括:ISysEventService.aidl、SysEventRule.aidl、ISysEventCallback.aidl。 + + 在相应的业务逻辑里面调用ISysEventService::AddListener\(in SysEventRule\[\] rules, in ISysEventCallback callback\)接口。 + + 实现对应的回调对象: + + ISysEventCallback::Handle\(in String domain, in String eventName, in int eventType, in String eventDetail\) + +2. 编译设置: + +在编译子系统里面,需要依赖libbinder模块 + +aosp\_deps = \[ "shared\_library:libbinder", \] + +- **[bytrace使用指导](subsys-toolchain-bytrace-guide.md)** + +- **[hdc\_std 使用指导](subsys-toolchain-hdc-guide.md)** + + diff --git "a/zh-cn/device-dev/subsystems/DFX\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-dfx-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/DFX\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-dfx-overview.md diff --git a/zh-cn/device-dev/subsystems/subsys-dfx.md b/zh-cn/device-dev/subsystems/subsys-dfx.md new file mode 100644 index 0000000000000000000000000000000000000000..e4538aa73f4121b6ffcae48694a247fe2b84ef31 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-dfx.md @@ -0,0 +1,11 @@ +# DFX + +- **[DFX概述](subsys-dfx-overview.md)** + +- **[HiLog开发指导](subsys-dfx-hilog-rich.md)** + +- **[HiLog\_Lite开发指导](subsys-dfx-hilog-lite.md)** + +- **[HiSysEvent开发指导](subsys-dfx-hisysevent.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md b/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..8332aa22bd87afd1e6d8e6dff632b189cc0c19ea --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-animation-guide.md @@ -0,0 +1,190 @@ +# 动画开发指导 + +- [使用场景](#section726685714018) +- [接口说明](#section85794718418) +- [开发步骤](#section14101161317435) + +## 使用场景 + +UI动画通过task处理机制每个tick调用一下用户设置的callback函数来实现,具体实现为AnimatorManager、Animator、AnimatorCallback三个类实现。 + +- AnimatorManager:AnimatorManager为单例,在Init函数执行时将自己注册到系统task回调函数中,系统task机制保证每个tick会调用一下AnimatorManager的callback函数,同时AnimatorManager用来管理Animator实例。 +- Animator:Animator中可以设置动画相关的属性,包括动画的起止时间,动画开始和停止,动画状态的设置和获取等。 +- AnimatorCallback:具体每一个tick动画所要做的内容在AnimatorCallback类中实现,开发者需要自己实现Callback方法,动画执行时在Callback实现相应功能。 + +## 接口说明 + +**表 1** 动画接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

子模块

+

方法

+

功能

+

Animator

+

void Start ()

+

动画开始

+

Animator

+

void Stop ()

+

动画停止

+

Animator

+

void Pause ()

+

动画暂停

+

Animator

+

void Resume ()

+

动画恢复

+

Animator

+

uint8_t GetState () const

+

获取动画当前状态

+

Animator

+

void SetState (uint8_t state)

+

设置动画当前状态

+

Animator

+

uint32_t GetTime () const

+

获取动画总持续时间

+

Animator

+

void SetTime (uint32_t time)

+

设置动画总持续时间

+

Animator

+

uint32_t GetRunTime () const

+

获取动画当前已经持续的时间

+

Animator

+

void SetRunTime (uint32_t runTime)

+

设置动画当前已经持续的时间

+

Animator

+

bool IsRepeat () const

+

获取动画是否循环播放

+

AnimatorCallback

+

virtual void Callback (UIView *view)=0

+

由用户实现,动画回调函数

+

AnimatorCallback

+

virtual void OnStop(UIView& view) {}

+

由用户实现,动画停止后的回调函数

+

AnimatorManager

+

static AnimatorManager* GetInstance()

+

获取AnimatorManager实例

+

AnimatorManager

+

void Add (Animator *animator)

+

添加动画

+

AnimatorManager

+

void Remove(const Animator* animator);

+

删除动画

+
+ +## 开发步骤 + +1. 实现AnimatorCallback的回调函数。 + + ``` + class AnimatorCallbackDemo : public OHOS::AnimatorCallback { + public: + AnimatorCallbackDemo(int16_t startPos, int16_t endPos, uint16_t time) + : start_(startPos), end_(endPos), time_(time), curTime_(0) {} + + virtual void Callback(OHOS::UIView* view) + { + curTime_++; + int16_t pos = EasingEquation::CubicEaseIn(start_, end_, curTime_, time_); + view->Invalidate(); + view->SetPosition(pos, view->GetY()); + view->Invalidate(); + } + protected: + int16_t start_; + int16_t end_; + uint16_t time_; + uint16_t curTime_; + }; + ``` + +2. 将AnimatorCallback添加到Animator中。 + + ``` + UIImageView* image = new UIImageView(); + image->SetSrc("..\\config\\images\\A021_001.bin"); + image->SetPosition(0, 50); + AnimatorCallbackDemo* callback = new AnimatorCallbackDemo(0, 338, 60); + Animator* animator = new Animator(callback, image, 0, true); + ``` + +3. 将Animator添加到AnimatorManager中。 + + ``` + AnimatorManager::GetInstance()->Add(animator); + ``` + +4. 点击下图下方的按钮,检查对应的动画运行效果。 + + **图 1** 动画实现效果图 + ![](figure/动画实现效果图.gif "动画实现效果图") + + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md new file mode 100644 index 0000000000000000000000000000000000000000..52da564931e3f8ff58c2e0379c98dbcbc993aa58 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide1.md @@ -0,0 +1,244 @@ +# 容器类组件开发指导 + +- [UIViewGroup](#section145471898812) +- [使用场景](#section0916112362216) +- [接口说明](#section12641756192212) +- [开发步骤](#section5412161692311) +- [UIScrollView](#section174961523161315) +- [使用场景](#section8937101902413) +- [接口说明](#section14789133142420) +- [开发步骤](#section1769754422417) + +容器类组件,指能包含其它UI组件的组件,容器类组件继承于UIViewGroup(带Add方法),基于实际组件的使用场景,将需要增加其他子组件的组件,放置到容器类继承结构下。如UIAnalogClock内,通常会Add需要的计步信息,时分秒图标等。 + +**图 1** 普通容器类组件结构 +![](figure/普通容器类组件结构.png "普通容器类组件结构") + +RootView、UIAbstractScroll、UIPicker组件从UIViewGroup继承,UIList、UIScrollView、UISwipeView组件从UIAbstractScroll继承。 + +## UIViewGroup + +## 使用场景 + +UIViewGroup是容器类组件基类,实现增加、删除、插入等操作,通过增加方法可以添加子组件。普通容器类组件子组件需要设置位置信息,位置信息为相对父组件的相对坐标。组件树结构如下图: + +**图 2** 组件树结构示意图 +![](figure/组件树结构示意图.png "组件树结构示意图") + +往根节点rootView里添加ViewGroup1容器组件和View1组件,往ViewGroup1容器组件里再添加View2组件和ViewGroup2容器组件,在View1之后添加View3组件。 + +- 关于渲染:容器类组件在渲染时会遍历所有子组件OnDraw方法,以达到刷新所有组件的目的。 +- 关于坐标:子组件位置信息为相对父组件的相对坐标,系统在渲染时计算绝对坐标并显示。 +- 关于树结构遍历:UIViewGroup提供如下方法实现遍历、查找、管理组件树。 + +## 接口说明 + +**表 1** ViewGroup接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

功能

+

virtual void Add(UIView* view)

+

添加子组件

+

virtual void Insert(UIView* prevView, UIView* insertView)

+

插入子组件

+

virtual void Remove(UIView* view)

+

删除子组件

+

virtual void RemoveAll()

+

删除所有子组件

+

virtual void GetTargetView(const Point& point, UIView** last)

+

获取目标视图

+

virtual void MoveChildByOffset(int16_t x, int16_t y)

+

偏移子组件

+

UIView* GetChildrenHead() const

+

获取视图头节点

+

UIView* GetChildrenTail() const

+

获取视图最后那个节点

+

virtual UIView* GetChildById(const char* id) const override

+

通过id获取子视图

+
+ +## 开发步骤 + +1. 构造button实例并设置坐标信息。 + + ``` + UILabelButton* btn1 = new UILabelButton(); + btn1->SetPosition(0, 0, 100, 50); + btn1->SetText("btn1"); + + UILabelButton* btn2 = new UILabelButton(); + btn2->SetPosition(50, 50, 100, 50); + btn2->SetText("btn2"); + + UILabelButton* btn3 = new UILabelButton(); + btn3->SetPosition(100, 100, 100, 50); + btn3->SetText("btn3"); + ``` + +2. 构造UIViewGroup实例,并设置坐标信息。 + + ``` + UIViewGroup* group = new UIViewGroup(); + group->SetPosition(0, 0, 300, 300); + ``` + +3. 使用Add方法添加Button实例到UIViewGroup。 + + ``` + group->Add(btn1); + group->Add(btn2); + group->Add(btn3); + ``` + +4. 检查ViewGroup效果如下图所示。 + + **图 3** ViewGroup添加view实例效果图 + ![](figure/ViewGroup添加view实例效果图.png "ViewGroup添加view实例效果图") + + +## UIScrollView + +## 使用场景 + +UIScrollView提供可滑动的容器类组件,子组件可在触摸事件驱动下上下、左右滑动,并提供水平和垂直方向的游标显示功能。 + +## 接口说明 + +**表 2** ScrollView接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

功能

+

void ScrollBy(int16_t xDistance, int16_t yDistance)

+

移动视图

+

void SetScrollbarWidth(uint8_t width)

+

设置滑动条宽度

+

void SetHorizontalScrollState(bool state)

+

设置水平滑动状态

+

bool GetHorizontalScrollState() const

+

获取水平是否可滑动状态

+

void SetVerticalScrollState(bool state)

+

设置垂直滑动状态

+

bool GetVerticalScrollState() const

+

获取垂直是否可滑动状态

+

void SetXScrollBarVisible(bool state)

+

设置X轴滑动条是否可见

+

void SetYScrollBarVisible(bool state)

+

设置Y轴滑动条是否可见

+

void RegisterScrollListener(OnScrollListener* scrollListener)

+

注册滑动事件回调类

+

void RefreshScrollBar()

+

刷新滑动条

+

virtual void OnScrollStart() {}

+

滚动开始回调函数

+

virtual void OnScrollEnd() {}

+

滚动结束回调函数

+

uint8_t GetScrollState() const

+

获取滚动状态

+

void SetScrollState(uint8_t state)

+

设置滚动状态

+
+ +## 开发步骤 + +添加两个button子组件,并显示水平、垂直方向游标。 + +``` +scrollView* scroll = new UIScrollView(); +scroll->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full); +scroll->SetPosition(0,0, 200, 200); +scroll->SetXScrollBarVisible(true); +scroll->SetYScrollBarVisible(true); +UILabelButton* button1 = new UILabelButton(); +button1->SetText("button1"); +button1->SetPosition(0, 0, 300, 300); +UILabelButton* button2 = new UILabelButton(); +button2->SetText("button2"); +button2->SetPosition(0, 300, 300, 300); +scroll->Add(button1); +scroll->Add(button2); +``` + +**图 4** 水平、垂直方向可滑动效果图 +![](figure/水平-垂直方向可滑动效果图.gif "水平-垂直方向可滑动效果图") + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md new file mode 100644 index 0000000000000000000000000000000000000000..f03df38642b7f5892957eedc54a9648b0168e3be --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide2.md @@ -0,0 +1,216 @@ +# 布局容器类组件开发指导 + +- [UISwipeView](#section13631719181717) +- [使用场景](#section11299120102617) +- [接口说明](#section767434119261) +- [开发步骤(水平滑动,不可循环)](#section111911175287) +- [开发步骤(水平滑动,可循环)](#section1976914915282) +- [GridLayout](#section46819199173) +- [使用场景](#section831618247294) +- [接口说明](#section597214622912) +- [开发步骤](#section1418253410306) + +布局类容器组件由视图基础类组成,通过直接设置视图位置,可以达到嵌套和重叠布局的目的;通过设置布局类型和边距达到规格化布局子组件的目的;通过调用相关接口可实现根据父组件及兄弟节点布局视图的目的。 + +## UISwipeView + +## 使用场景 + +UISwipeView继承UIViewGroup,除提供容器类组件Add、Remove、Insert等方法外还提供按页面滑动功能,滑动结束后当前页面居中对齐显示。该组件分为水平方向和垂直方向,通过Add方法添加的子组件会根据Add的顺序和UISwipeView方向自动水平对齐或则垂直对齐。 + +## 接口说明 + +**表 1** SwipeView接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

功能

+

void SetCurrentPage(uint16_t index);

+

设置当前页

+

uint16_t GetCurrentPage()

+

获取当前页

+

UIView* GetCurrentView() const

+

获取当前页组件

+

void SetOnSwipeListener(OnSwipeListener& onSwipeListener)

+

设置滑动回调类

+

void SetAnimatorTime(uint16_t time);

+

设置动画事件

+

void SetLoopState(bool loop)

+

设置是否循环

+

UIView* GetViewByIndex(uint16_t index);

+

通过index获取view

+
+ +## 开发步骤(水平滑动,不可循环) + +1. 创建一个水平滑动的UISwipeView。 + + ``` + UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); + ``` + +2. 向UISwipeView中添加子组件。 + + ``` + UILabelButton* button1 = new UILabelButton(); + button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button1->SetText("button1"); + swipe->Add(button1); + UILabelButton* button2 = new UILabelButton(); + button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button2->SetText("button2"); + swipe->Add(button2); + UILabelButton* button3 = new UILabelButton(); + button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button3->SetText("button3"); + swipe->Add(button3); + ``` + +3. 检查实现效果,水平滑动,不可循环。 + + **图 1** UISwipeView水平滑动效果图 + + + ![](figure/zh-cn_image_0000001053247975.gif) + + +## 开发步骤(水平滑动,可循环) + +1. 创建一个水平滑动的UISwipeView并添加子组件。 + + ``` + UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); + UILabelButton* button1 = new UILabelButton(); + button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button1->SetText("button1"); + swipe->Add(button1); + UILabelButton* button2 = new UILabelButton(); + button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button2->SetText("button2"); + swipe->Add(button2); + UILabelButton* button3 = new UILabelButton(); + button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); + button3->SetText("button3"); + swipe->Add(button3); + ``` + +2. 设置UISwipeView循环滑动。 + + ``` + swipe->SetLoopState(true); + ``` + +3. 检查实现效果,水平循环滑动。 + + **图 2** UISwipeView水平滑动循环效果图 + + + ![](figure/zh-cn_image_0000001053207924.gif) + + +## GridLayout + +## 使用场景 + +提供基础布局能力,可设置网格行数和列数,通过Add方法添加的子组件在调用LayoutChildren\(\)方法后自动进行排列布局。 + +## 接口说明 + +**表 2** GridLayout接口说明 + + + + + + + + + + + + + + + + +

方法

+

功能

+

void SetRows(const uint16_t& rows)

+

设置行数

+

void SetCols(const uint16_t& cols)

+

设置列数

+

void LayoutChildren(bool needInvalidate = false)

+

布局子组件

+
+ +## 开发步骤 + +1. 构造GridLayout并设置位置、大小信息。 + + ``` + GridLayout* layout_ = new GridLayout(); + layout_->SetPosition(0, g_y, HROIZONTAL_RESOLUTION, 200); + layout_->SetLayoutDirection(LAYOUT_HOR); + layout_->SetRows(2); + layout_->SetCols(2); + ``` + +2. 构造子组件button。 + + ``` + UILabelButton* bt1 = new UILabelButton(); + bt1->SetPosition(0,0,100,50); + bt1->SetText("bt1"); + UILabelButton* bt2 = new UILabelButton(); + bt2->SetPosition(0, 0, 100, 50); + bt2->SetText("bt2"); + UILabelButton* bt3 = new UILabelButton(); + bt3->SetPosition(0, 0, 100, 50); + bt3->SetText("bt3"); + UILabelButton* bt4 = new UILabelButton(); + bt4->SetPosition(0, 0, 100, 50); + bt4->SetText("bt4"); + ``` + +3. 添加子组件并调用LayoutChildren\(\)。 + + ``` + layout_->Add(bt1); + layout_->Add(bt2); + layout_->Add(bt3); + layout_->Add(bt4); + layout_->LayoutChildren(); + ``` + +4. 检查button组件布局效果如下图所示。 + + **图 3** 设置2\*2网格并添加4个button组件进行布局 + ![](figure/设置2-2网格并添加4个button组件进行布局.png "设置2-2网格并添加4个button组件进行布局") + + diff --git a/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md new file mode 100644 index 0000000000000000000000000000000000000000..d9b0d48c87587588b3bbd4b39c83e636001dcbd6 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics-bundle-guide3.md @@ -0,0 +1,555 @@ +# 普通组件开发指导 + +- [UIButton](#section145353310214) +- [使用场景](#section1169616141577) +- [接口说明](#section341211538315) +- [开发步骤](#section22501726193214) +- [UIImageView](#section19523161611259) +- [使用场景](#section1274484210400) +- [接口说明](#section74981992411) +- [开发步骤(自适应)](#section144341333134114) +- [开发步骤(平铺模式)](#section97178160421) +- [UILabel](#section16588132012911) +- [使用场景](#section6870195634218) +- [接口说明](#section2012714510433) +- [开发步骤(默认模式)](#section83221538114410) +- [开发步骤(背景色和透明度)](#section933360204510) +- [开发步骤(字符间距)](#section19447826124518) +- [开发步骤(大小自适应)](#section101711842154617) +- [开发步骤(省略号模式)](#section1249519410471) +- [开发步骤(滚动模式)](#section15643122618478) + +普通组件均继承于基类UIView,不可以添加子组件,常用的普通组件有button、image、label等。 + +**图 1** 普通组件树结构 +![](figure/普通组件树结构.png "普通组件树结构") + +UIView为基础类,UIAbstractProgress、UIArcLabel(旋转字体)、UIButton(按键)、UICanvas(画布)、UILabel(字体)、UIImageView(图片)从UIView继承。UIBoxProgress、UICircleProgress从UIAbstractProgress继承,UILabelButton和UIRepeatButton从UIButton继承,UIImageAnimatorView和UITextureMapper从UIImageView继承。 + +## UIButton + +## 使用场景 + +UIButton组件,提供可点击功能,同时可设置不同状态下样式。 + +## 接口说明 + +**表 1** button接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

功能

+

void SetImageSrc (const char *defaultImgSrc, const char *triggeredImgSrc)

+

设置button图片

+

void SetImagePosition (const int16_t x, const int16_t y)

+

设置button图片位置

+

int16_t GetImageX () const

+

获取图片X坐标

+

int16_t GetImageY () const

+

获取图片Y坐标

+

const ImageInfo* GetCurImageSrc() const

+

获取当前状态图片

+

Style& GetStyleForState (ButtonState state)

+

设置button当前状态的style

+

voidSetStyleForState (const Style &style, ButtonState state)

+

设置button指定状态的style

+

void Disable ()

+

去使能button

+

void Enable ()

+

使能button

+
+ +## 开发步骤 + +1. 实现点击事件。 + + ``` + class TestBtnOnClickListener : public OHOS::UIView::OnClickListener { + bool OnClick(UIView& view, const ClickEvent& event) override + { + int16_t width = view.GetWidth() + 10; + int16_t height = view.GetHeight() + 10; + view.Resize(width, height); + view.Invalidate(); + return true; + } + }; + ``` + +2. 创建一个UIButton。 + + ``` + UIButton* button = new UIButton(); + button->SetPosition(50, 50); + button->SetWidth(100); + button->SetHeight(50); + ``` + +3. 给UIButton注册点击事件回调。 + + ``` + button->SetOnClickListener(new TestBtnOnClickListener()); + ``` + +4. 检查Button点击效果如下图所示,Button逐渐变大。 + + **图 2** UIButton点击效果 + ![](figure/UIButton点击效果.gif "UIButton点击效果") + + +## UIImageView + +## 使用场景 + +图片组件,提供图片显示,透明度设置,图片旋转、缩放功能。支持的图片格式为RGB565、RGB888、RGBA8888、PNG、JPG。 + +## 接口说明 + +**表 2** image接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

功能

+

void SetSrc (const char *src)

+

设置二进制图片路径

+

void SetSrc (const ImageInfo *src)

+

设置图片指针

+

void SetAutoEnable (bool enable)

+

设置组件大小跟随image大小变化

+

const void* GetSrcType () const

+

获取图片类型

+

bool GetAutoEnable () const

+

获取组件大小是否跟随image大小变化

+

void SetBlurLevel(BlurLevel level)

+

设置模糊等级

+

BlurLevel GetBlurLevel() const

+

获取模糊等级

+

void SetTransformAlgorithm(TransformAlgorithm algorithm)

+

设置旋转算法

+

TransformAlgorithm GetTransformAlgorithm() const

+

获取旋转算法

+
+ +## 开发步骤(自适应) + +1. 创建一个UIImageView。 + + ``` + UIImageView* imageView = new UIImageView(); + imageView->SetPosition(0, 30); + ``` + +2. 设置二进制格式的图片。 + + ``` + imageView->SetSrc("..\\config\\images\\A021_001.bin"); + ``` + +3. 检查UIImageView控件大小与图片相同。 + + **图 3** 自适应模式图片效果图 + ![](figure/自适应模式图片效果图.png "自适应模式图片效果图") + + +## 开发步骤(平铺模式) + +1. 创建一个UIImageView。 + + ``` + UIImageView* imageView = new UIImageView(); + imageView->SetPosition(0, 30); + ``` + +2. 设置图片。 + + ``` + imageView->SetSrc("..\\config\\images\\A021_001.bin"); + ``` + +3. 取消图片自适应,设置图片大小,平铺显示效果。 + + ``` + imageView->SetAutoEnable(false); + imageView->Resize(454, 150); + ``` + +4. 检查UIImageView控件显示为平铺效果。 + + **图 4** 平铺模式图片效果图 + ![](figure/平铺模式图片效果图.png "平铺模式图片效果图") + + +## UILabel + +## 使用场景 + +标签(label)是在一块区域上显示文本字符串的组件,可设置区域背景色、文字的显示样式和长文本的显示效果等。 + +## 接口说明 + +**表 3** label接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

方法

+

功能

+

void SetText(const char* text);

+

设置文字

+

const char* GetText() const;

+

获取text

+

void SetLineBreakMode(const uint8_t lineBreakMode);

+

设置label模式,例如截断,自动扩展等。

+

uint8_t GetLineBreakMode() const

+

获取label模式

+

void SetTextColor(ColorType color)

+

设置文本颜色

+

ColorType GetTextColor() const

+

获取文本颜色

+

void SetAlign(UITextLanguageAlignment horizontalAlign,

+

UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP);

+

设置文本对齐方式

+

UITextLanguageAlignment GetHorAlign() const

+

获取文本水平对齐方式

+

UITextLanguageAlignment GetVerAlign() const

+

获取文本竖直对齐方式

+

void SetDirect(UITextLanguageDirect direct)

+

设置文本显示方向

+

UITextLanguageDirect GetDirect() const

+

获取文本显示方向

+

void SetFontId(uint8_t fontId);

+

设置动态字体id

+

uint8_t GetFontId() const

+

获取动态字体id

+

void SetFont(const char *name, uint8_t size);

+

设置字的名字和大小

+

void SetAnimatorSpeed(uint16_t animSpeed);

+

设置字体旋转的速度

+

uint16_t GetTextWidth();

+

获取字体的宽

+

uint16_t GetTextHeight();

+

获取字体的高

+

void SetRollStartPos(int16_t pos)

+

设置旋转的位置

+

int16_t GetRollStartPos() const

+

获取旋转的位置

+

void SetTextRotation(LabelRotateDegree angle)

+

设置文本旋转角度枚举值

+

LabelRotateDegree GetTextRotation() const

+

获取文本旋转角度枚举值

+

uint16_t GetTextRotateDegree() const

+

获取文本旋转角度数值

+
+ +## 开发步骤(默认模式) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置文本数据。 + + ``` + label->SetText("label"); + ``` + +4. 检查label大小和显示效果正常,如下图所示。 + + ![](figure/zh-cn_image_0000001051782526.png) + + +## 开发步骤(背景色和透明度) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置背景颜色及透明度效果。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_BACKGROUND_OPA, 127); + label->SetText("Label"); + ``` + +4. 检查label背景色为Gray,如下图所示。 + + ![](figure/zh-cn_image_0000001052582522.png) + + +## 开发步骤(字符间距) + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置字体颜色和字间距效果。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_LETTER_SPACE, 5); + label->SetText("Label"); + ``` + +4. 检查label字符间距为5,如下图所示。 + + ![](figure/zh-cn_image_0000001052942531.png) + + +## 开发步骤(大小自适应) + +当文本过长时,可根据文本信息自动调整label组件大小,也可以设置文本截断或者文本滚动效果。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置字体颜色为Gray,组件大小自适应文本内容。 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); + label->SetText("123\n567890"); + ``` + +4. 检查label大小自适应文本内容,如下图所示。 + + ![](figure/zh-cn_image_0000001052782555.png) + + +## 开发步骤(省略号模式) + +省略号模式指文本内容显示不下时,在末尾显示省略号。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置换行模式为DOT模式 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); + label->SetText("123567890"); + ``` + +4. 检查label DOT模式效果,如下图所示,末尾显示省略号。 + + ![](figure/zh-cn_image_0000001052662559.png) + + +## 开发步骤(滚动模式) + +文本滚动显示。 + +1. 创建label,设置大小和位置信息。 + + ``` + UILabel* label = new UILabel(); + label->SetPosition(x, y); + label->Resize(width, height); + ``` + +2. 设置字形信息。 + + ``` + label->SetFont("SourceHanSansSC-Regular.otf", 30); + ``` + +3. 设置换行模式为滚动模式 + + ``` + label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); + label->SetStyle(STYLE_BACKGROUND_OPA, 127); + label->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); + label->SetText("123567890"); + ``` + +4. 检查label滚动模式效果,如下图所示。 + + ![](figure/20200721-223604(eSpace).gif) + + diff --git "a/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-graphics-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-graphics-overview.md diff --git a/zh-cn/device-dev/subsystems/subsys-graphics.md b/zh-cn/device-dev/subsystems/subsys-graphics.md new file mode 100644 index 0000000000000000000000000000000000000000..bb255fa159a9823a6ddbfc724ba7b9ba4c5ac9cd --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-graphics.md @@ -0,0 +1,13 @@ +# 图形图像 + +- **[图形图像概述](subsys-graphics-overview.md)** + +- **[容器类组件开发指导](subsys-graphics-bundle-guide1.md)** + +- **[布局容器类组件开发指导](subsys-graphics-bundle-guide2.md)** + +- **[普通组件开发指导](subsys-graphics-bundle-guide3.md)** + +- **[动画开发指导](subsys-graphics-animation-guide.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..75b2033e9c72cb5541ed32a6d7a8e098e748a526 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-overview.md @@ -0,0 +1,116 @@ +# 相机开发概述 + +- [基本概念](#section175012297491) +- [运作机制](#section193961322175011) + +## 基本概念 + +相机是OpenHarmony多媒体进程提供的服务之一,提供了相机的录像、预览、拍照功能,支持多用户并发取流。 + +在进行应用的开发前,开发者应了解以下基本概念: + +- 视频帧 + + 视频流指的是将一系列图片数据按照固定时间间隔排列形成的数据流,每一张图片数据成为一帧,这样的一帧称为视频帧。 + +- 帧速率\(FPS: Frames Per Second\) + + 视频播放每秒钟刷新图片的速度,或是视频每秒的帧数,帧速率越高,视频的观感越流畅。 + +- 分辨率 + + 每一帧的图片信息都是由像素点组成的,分辨率描述了一张图片中像素点的个数。例如1920\*1080\(1080P\),是指图片宽1920像素,高1080像素。 + + +## 运作机制 + +- 多媒体服务进程 + + 多媒体服务作为系统服务,在系统启动时由Init进程拉起,并初始化和分配媒体硬件资源(内存/显示硬件/图像传感器/编解码器等)。初始化过程解析配置文件,确定了多媒体各个服务的能力和资源上限,通常由OEM厂商通过配置文件进行配置。相机服务在多媒体进程初始化时有以下配置项: + + - 内存池:所有媒体服务依赖于内存池中的内存轮转运行 + - 图像传感器:包括了传感器类型、分辨率、ISP等 + - 图像处理器:分辨率、码率、图像翻转等 + - 图像编码器:编码格式、码率、分辨率等 + + +- 关键类的解释 + + 应用通过持有下面4个类,配置和使用Camera的功能,包括了Camera类和它的三个异步回调类,三类回调分别对应了不同类型的异步处理场景,详见[表1](#table486418149411)。 + + **表 1** 关键类的解释 + + + + + + + + + + + + + + + + + + + + + + + + +

对象

+

用途

+

举例

+

Camera

+

对相机进行静态配置(通过配置类),触发相机基本功能

+

拍照/录像/预览

+

CameraDeviceCallback

+

处理相机硬件状态变化

+

可用/不可用

+

CameraStateCallback

+

处理camera自身状态变化

+

创建/释放

+

FrameStateCallback

+

处理帧状态的变化

+

拍照开始和结束/帧率发生变化

+
+ +- 流的传递 + + Surface是多媒体传递音视频的基本数据结构,Camera一般作为Surface中数据的生产者,在不同的场景下有特定的消费者。 + + 相机的预览和录像输出均为视频流,拍照输出为图像帧,二者均通过Surface类进行传递。Surface类可以屏蔽进程内/跨进程的场景,进行多媒体信息流的传递。 + + 以录像为例,用户首先创建Recorder实例,并从Recorder中获取对应Surface,再将此Surface传递给Camera实例,此时Camera将作为生产者向Surface注入视频流,而Recorder作为消费者从Surface中取出视频流进行保存,用户的行为类似桥接,把二者通过Surface连接起来。 + + 类似的,用户也可以自行创建Surface传递给Camera实例,并实现消费者逻辑(例如通过网络传输视频流,或是将拍照的帧数据保存成图片文件)。 + + 图形图像模块也通过Surface从Camera获取流资源,具体步骤详见[图形图像开发指导](subsys-graphics-overview.md)。 + +- 相机运行流程 + 1. Camera创建流程 + + 本进程通过CameraManager创建Camera实例,并从服务端绑定camera设备,创建成功后异步通知developer。类之间的时序图如下: + + **图 1** Camera创建时序图 + + + ![](figure/zh-cn_image_0000001054101094.png) + + + 1. Camera录像/预览流程 + + 开发者首先通过CameraKit创建Camera,然后FrameConfig类对录像或者预览帧属性进行配置。录像/预览时序如下: + + **图 2** Camera录像/预览时序图 + + + ![](figure/zh-cn_image_0000001054421113.png) + + + diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..0e1ebbfecfc56b1d4eecf483c07c4c646cb85e0b --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-photo-guide.md @@ -0,0 +1,396 @@ +# 拍照开发指导 + +- [使用场景](#section1963312376119) +- [接口说明](#section56549532016) +- [约束与限制](#section1165911177314) +- [开发步骤](#section138543918214) + +## 使用场景 + +使用Camera产生图片帧(拍照)。 + +## 接口说明 + +**表 1** API列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

类名

+

接口名

+

描述

+

CameraKit

+

int32_t GetCameraIds(std::list<string> cameraList)

+

获取cameraId列表

+

CameraKit

+

CameraAbility& GetCameraAbility(string cameraId)

+

获取指定camera的能力

+

CameraKit

+

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

+

注册camera设备状态回调

+

CameraKit

+

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

+

去注册camera设备状态回调

+

CameraKit

+

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

+

创建camera实例

+

Camera

+

string GetCameraId()

+

获取cameraID

+

Camera

+

CameraConfig& GetCameraConfig()

+

获取camera配置信息

+

Camera

+

FrameConfig& GetFrameConfig(int32_t type)

+

获取捕获帧类型

+

Camera

+

void Configure(CameraConfig& config)

+

配置camera

+

Camera

+

void Release()

+

释放camera

+

Camera

+

int TriggerLoopingCapture(FrameConfig& frameConfig)

+

开始循环帧捕获

+

Camera

+

void StopLoopingCapture()

+

停止循环帧捕获

+

Camera

+

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

+

抓图

+

CameraConfig

+

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

+

设置帧状态回调

+

CameraConfig

+

static CameraConfig* CreateCameraConfig()

+

创建camera配置信息实例

+

CameraAbility

+

std::list<Size> GetSupportedSizes(int format)

+

根据类型获取支持输出图像尺寸大小

+

CameraAbility

+

std::list<T> GetParameterRange(uint32_t key)

+

获取支持的参数范围

+

CameraDevice

+

CameraDeviceCallback()

+

camera设备回调类构造函数

+

CameraDevice

+

void OnCameraStatus​(std::string cameraId, int32_t status)

+

camera设备状态变化时的回调

+

CameraStateCallback

+

CameraStateCallback​()

+

camera状态回调类构造函数

+

CameraStateCallback

+

void OnConfigured​(Camera& camera)

+

camera配置成功回调

+

CameraStateCallback

+

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

+

camera配置失败回调

+

CameraStateCallback

+

void OnCreated​(Camera& camera)

+

camera创建成功回调

+

CameraStateCallback

+

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

+

camera创建失败回调

+

CameraStateCallback

+

void OnReleased​(Camera& camera)

+

camera释放回调

+

FrameStateCallback

+

FrameStateCallback​()

+

帧状态回调类构造函数

+

FrameStateCallback

+

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

+

拍照帧完成回调

+

FrameStateCallback

+

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

+

拍照帧异常回调

+

FrameConfig

+

int32_t GetFrameConfigType()

+

获取帧配置类型

+

FrameConfig

+

std::list<OHOS::Surface> GetSurfaces()

+

获取帧配置的surface

+

FrameConfig

+

void AddSurface(OHOS::AGP::UISurface& surface);

+

添加surface

+

FrameConfig

+

void RemoveSurface(OHOS::AGP::UISurface& surface);

+

删除surface

+
+ +## 约束与限制 + +无。 + +## 开发步骤 + +1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 + + ``` + class SampleCameraDeviceCallback : public CameraDeviceCallback { + void OnCameraStatus(std::string cameraId, int32_t status) override + { + //do something when camera is available/unavailable + } + }; + ``` + +2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 + + ``` + static void SampleSaveCapture(const char *p, uint32_t size) + { + cout << "Start saving picture" << endl; + struct timeval tv; + gettimeofday(&tv, NULL); + struct tm *ltm = localtime(&tv.tv_sec); + if (ltm != nullptr) { + ostringstream ss("Capture_"); + ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; + + ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); + cout << "write " << size << " bytes" << endl; + pic.write(p, size); + cout << "Saving picture end" << endl; + } + } + + class TestFrameStateCallback : public FrameStateCallback { + void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override + { + cout << "Receive frame complete inform." << endl; + if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { + cout << "Capture frame received." << endl; + list surfaceList = fc.GetSurfaces(); + for (Surface *surface : surfaceList) { + SurfaceBuffer *buffer = surface->AcquireBuffer(); + if (buffer != nullptr) { + char *virtAddr = static_cast(buffer->GetVirAddr()); + if (virtAddr != nullptr) { + SampleSaveCapture(virtAddr, buffer->GetSize()); + } + surface->ReleaseBuffer(buffer); + } + delete surface; + } + delete &fc; + } + } + }; + ``` + +3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 + + ``` + class SampleCameraStateMng : public CameraStateCallback { + public: + SampleCameraStateMng() = delete; + SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} + ~SampleCameraStateMng() + { + if (recordFd_ != -1) { + close(recordFd_); + } + } + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} + void OnReleased(Camera &c) override {} + }; + ``` + +4. 创建CameraKit,用于创建和获取camera信息。 + + ``` + CameraKit *camKit = CameraKit::GetInstance(); + list camList = camKit->GetCameraIds(); + string camId; + for (auto &cam : camList) { + cout << "camera name:" << cam << endl; + const CameraAbility *ability = camKit->GetCameraAbility(cam); + /* find camera which fits user's ability */ + list sizeList = ability->GetSupportedSizes(0); + if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { + camId = cam; + break; + } + } + ``` + +5. 创建Camera实例。 + + ``` + EventHandler eventHdlr; // Create a thread to handle callback events + SampleCameraStateMng CamStateMng(eventHdlr); + + camKit->CreateCamera(camId, CamStateMng, eventHdlr); + ``` + +6. 根据[步骤1](#li378084192111)、[步骤2](#li8716104682913)、[步骤3](#li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 + + ``` + void OnCreated(Camera &c) override + { + cout << "Sample recv OnCreate camera." << endl; + auto config = CameraConfig::CreateCameraConfig(); + config->SetFrameStateCallback(&fsCb_, &eventHdlr_); + c.Configure(*config); + cam_ = &c; + } + + void Capture() + { + if (cam_ == nullptr) { + cout << "Camera is not ready." << endl; + return; + } + FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); + Surface *surface = Surface::CreateSurface(); + if (surface == nullptr) { + delete fc; + return; + } + surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ + fc->AddSurface(*surface); + cam_->TriggerSingleCapture(*fc); + } + ``` + + diff --git "a/zh-cn/device-dev/subsystems/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\242\204\350\247\210\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-camera-preview-guide.md diff --git "a/zh-cn/device-dev/subsystems/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\275\225\345\203\217\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-camera-record-guide.md diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md b/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md new file mode 100644 index 0000000000000000000000000000000000000000..ad7796b6926b7f89505b6508cda2e796fd961e64 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-camera.md @@ -0,0 +1,11 @@ +# 相机 + +- **[相机开发概述](subsys-multimedia-camera-overview.md)** + +- **[拍照开发指导](subsys-multimedia-camera-photo-guide.md)** + +- **[录像开发指导](subsys-multimedia-camera-record-guide.md)** + +- **[预览开发指导](subsys-multimedia-camera-preview-guide.md)** + + diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\274\200\345\217\221\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\274\200\345\217\221\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-video-overview.md diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\346\222\255\346\224\276\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\346\222\255\346\224\276\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-video-play-guide.md diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\275\225\345\210\266\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221\345\275\225\345\210\266\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-multimedia-video-record-guide.md diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia-video.md b/zh-cn/device-dev/subsystems/subsys-multimedia-video.md new file mode 100644 index 0000000000000000000000000000000000000000..2a59765280656395693afc362f32fac0bc6c1447 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia-video.md @@ -0,0 +1,9 @@ +# 音视频 + +- **[音视频开发概述](subsys-multimedia-video-overview.md)** + +- **[音视频播放开发指导](subsys-multimedia-video-play-guide.md)** + +- **[音视频录制开发指导](subsys-multimedia-video-record-guide.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-multimedia.md b/zh-cn/device-dev/subsystems/subsys-multimedia.md new file mode 100644 index 0000000000000000000000000000000000000000..50fb9b91f2f47741ba7aa0efe8fa2935e52fd1de --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-multimedia.md @@ -0,0 +1,7 @@ +# 媒体 + +- **[相机](subsys-multimedia-camera.md)** + +- **[音视频](subsys-multimedia-video.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-ota-guide.md b/zh-cn/device-dev/subsystems/subsys-ota-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..8b7978468325b860b0c8f02a5fdb3d1ce4d6a650 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-ota-guide.md @@ -0,0 +1,358 @@ +# OTA升级 + +- [约束与限制](#section691733275418) +- [生成公私钥对](#section94411533155010) +- [生成升级包](#section632383718539) +- [上传升级包](#section5772112473213) +- [下载升级包](#section251732474917) +- [厂商应用集成OTA能力](#section298217330534) +- [API应用场景-默认场景](#section7685171192916) + - [开发指导](#section0745926153017) + - [示例代码](#section1337111363306) + +- [API应用场景-定制场景](#section1686395317306) + - [开发指导](#section524515314317) + - [示例代码](#section525974743120) + +- [系统升级](#section151997114334) + +OTA(Over the Air)提供对设备远程升级的能力,可以让您的设备(如IP摄像头等),轻松支持远程升级能力。目前仅支持全量包升级,暂不支持差分包升级。全量包升级是将新系统全部内容做成升级包,进行升级;差分包升级是将新老系统的差异内容做成升级包,进行升级。 + +## 约束与限制 + +- 支持基于Hi3861/Hi3518EV300/Hi3516DV300芯片的开源套件。 +- 对Hi3518EV300/Hi3516DV300开源套件,设备需要支持SD卡(VFAT格式)。 + +## 生成公私钥对 + +1. 准备工作:在Windows PC 上,下载安装OpenSSL工具,并配置环境变量。OpenSSL下载路径: + + [http://slproweb.com/products/Win32OpenSSL.html](http://slproweb.com/products/Win32OpenSSL.html) + +2. 在tools\\update\_tools\\update\_pkg\_tools目录下,下载升级包制作工具,保存到Windows本地路径,例如D:\\ota\_tools。 +3. 如图,运行ota\_tools\\key下的Generate\_public\_private\_key.bat ,生成公钥Metis\_PUBLIC.key、私钥private.key和公钥对应的数组public\_arr.txt文件,请妥善保管私钥private.key。 + + **图 1** 生成公私钥对 + + + ![](figure/zh-cn_image_0000001060200050.png) + +4. 用public\_arr.txt里面的全部内容替换OTA模块base\\update\\ota\_lite\\frameworks\\source\\verify\\hota\_verify.c中的g\_pubKeyBuf 。 + + 示例,public\_arr.txt内容 + + ``` + 0x30,0x82,0x1,0xa,0x2,0x82,0x1,0x1,0x0,0xc7,0x8c,0xf3,0x91,0xa1,0x98,0xbf,0xb1,0x8c, + 0xbe,0x22,0xde,0x32,0xb2,0xfa,0xec,0x2c,0x69,0xf6,0x8f,0x43,0xa7,0xb7,0x6f,0x1e,0x4a,0x97, + 0x4b,0x27,0x5d,0x56,0x33,0x9a,0x73,0x4e,0x7c,0xf8,0xfd,0x1a,0xf0,0xe4,0x50,0xda,0x2b,0x8, + 0x74,0xe6,0x28,0xcc,0xc8,0x22,0x1,0xa8,0x14,0x9,0x46,0x46,0x6a,0x10,0xcd,0x39,0xd,0xf3, + 0x4a,0x7f,0x1,0x63,0x21,0x33,0x74,0xc6,0x4a,0xeb,0x68,0x40,0x55,0x3,0x80,0x1d,0xd9,0xbc, + 0xd4,0xb0,0x4a,0x84,0xb7,0xac,0x43,0x1d,0x76,0x3a,0x61,0x40,0x23,0x3,0x88,0xcc,0x80,0xe, + 0x75,0x10,0xe4,0xad,0xac,0xb6,0x4c,0x90,0x8,0x17,0x26,0x21,0xff,0xbe,0x1,0x82,0x16,0x76, + 0x9a,0x1c,0xee,0x8e,0xd9,0xb0,0xea,0xd5,0x50,0x61,0xcc,0x9c,0x2e,0x78,0x15,0x2d,0x1f,0x8b, + 0x94,0x77,0x30,0x39,0x70,0xcf,0x16,0x22,0x82,0x99,0x7c,0xe2,0x55,0x37,0xd4,0x76,0x9e,0x4b, + 0xfe,0x48,0x26,0xc,0xff,0xd9,0x59,0x6f,0x77,0xc6,0x92,0xdd,0xce,0x23,0x68,0x83,0xbd,0xd4, + 0xeb,0x5,0x1b,0x2a,0x7e,0xda,0x9a,0x59,0x93,0x41,0x7b,0x4d,0xef,0x19,0x89,0x4,0x8d,0x5, + 0x7d,0xbc,0x3,0x1f,0x77,0xe6,0x3d,0xa5,0x32,0xf5,0x4,0xb7,0x9c,0xe9,0xfa,0x6e,0xc,0x9f, + 0x4,0x62,0xfe,0x2a,0x5f,0xbf,0xeb,0x9a,0x73,0xa8,0x2a,0x72,0xe3,0xf0,0x57,0x56,0x5c,0x59, + 0x14,0xdd,0x79,0x11,0x42,0x3a,0x48,0xf7,0xe8,0x80,0xb1,0xaf,0x1c,0x40,0xa2,0xc6,0xec,0xf5, + 0x67,0xc1,0x88,0xf6,0x26,0x5c,0xd3,0x11,0x5,0x11,0xed,0xb1,0x45,0x2,0x3,0x1,0x0,0x1, + ``` + + 示例,OTA模块的公钥 + + ``` + #define PUBKEY_LENGTH 270 + + static uint8 g_pubKeyBuf[PUBKEY_LENGTH] = { + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, + 0x63, 0x07, 0x84, 0xCF, 0x37, 0xF0, 0x45, 0xE8, 0xB9, 0x6E, 0xEF, 0x04, 0x88, 0xD3, 0x43, 0x06, + ``` + +5. 对Hi3518EV300/Hi3516DV300套件,在上一步的基础上,还需用public\_arr.txt里面的全部内容替换uboot模块device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\verify\\update\_public\_key.c中的g\_pub\_key中的全部内容。 + + 示例,uboot模块的公钥 + + ``` + static unsigned char g_pub_key[PUBKEY_LEN] = { + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xBF, 0xAA, 0xA5, 0xB3, 0xC2, 0x78, 0x5E, + ``` + + +## 生成升级包 + +1. 在ota\_tools\\Components目录下,归放需要升级的文件。 + + **图 2** 原始镜像归放位置 + + + ![](figure/zh-cn_image_0000001061889268.png) + + **表 1** 升级包内的文件 + + + + + + + + + + + + + + + + + + + + + + +

包内文件名

+

说明

+

u-boot.bin

+

将编译生成的u-boot-hi351XevX00.bin文件重命名后得到。

+

kernel.bin

+

将编译生成的liteos.bin/kernel文件重命名后得到。

+

rootfs.img

+

将编译生成的rootfs_xxxxx.img文件重命名后得到。

+

config

+

与开发板类型和内核类型相关,参考开源套件的SD卡烧写说明。

+

OTA.tag

+

共32字节,内容为:“package_type:otaA1S2D3F4G5H6J7K8”;其中后16字节为随机数,需要随版本变化。

+
+ +2. 修改ota\_tools\\xml下的packet\_harmony.xml文件,配置compAddr分区名,对应ota\_tools\\Components\\的文件,其它项不需修改,作为扩展项预留。 + + 示例,配置组件信息 + + ``` + + + .\Components\rootfs_jffs2.img + .\Components\liteos.bin + .\Components\userfs_jffs2.img + + ``` + +3. 将生成的公私钥路径配置到ota\_tools\\xml路径下的packet\_harmony.xml中。 + + 示例,配置公私钥路径 + + ``` + + .\key\private.key + .\key\Metis_PUBLIC.key + + ``` + +4. 在ota\_tools\\VersionDefine.bat中设置产品名称、软件版本号(用于防回滚校验)。 + + 示例,配置产品名称和版本号 + + ``` + set FILE_PRODUCT_NAME=Hisi + + @rem 设置软件版本号 不要超过16位 + set SOFTWARE_VER=OpenHarmony 1.1 + ``` + +5. 执行ota\_tools下的Make\_Harmony\_PKG.bat,生成升级包Hisi\_OpenHarmony 1.1.bin。升级包通过SHA256+RSA2048方式签名,保证完整性和合法性。 + + **图 3** 升级包制作工具 + + + ![](figure/zh-cn_image_0000001059334449.png) + + +## 上传升级包 + +将升级包Hisi\_OpenHarmony 1.1.bin上传到厂商的OTA服务器。 + +## 下载升级包 + +1. 厂商应用从OTA服务器下载Hisi\_OpenHarmony 1.1.bin。 +2. 对Hi3518EV300/Hi3516DV300开源套件,需要插入SD卡\(容量\>100MBytes\)。 + +## 厂商应用集成OTA能力 + +- 调用OTA模块的动态库libhota.so,对应头文件位于:base\\update\\ota\_lite\\interfaces\\kits\\hota\_partition.h&hota\_updater.h; +- libhota.so对应的源码路径为base\\update\\ota\_lite\\frameworks\\source。 +- API的使用方法,见本文“API应用场景”和API文档的OTA接口章节。 +- 如果需要适配开发板,请参考HAL层头文件:base\\update\\ota\_lite\\hals\\hal\_hota\_board.h。 + +## API应用场景-默认场景 + +升级包是按照上文“生成公私钥对”和“生成升级包”章节制作的。 + +### **开发指导** + +1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化OTA模块。 +2. 调用HotaWrite接口传入升级包数据流,接口内部实现校验、解析及写入升级数据流。 +3. 写入完成后,调用HotaRestart接口重启系统。 + + 升级过程中,使用HotaCancel接口可以取消升级。 + + +### **示例代码** + +使用OpenHarmony的“升级包格式和校验方法“进行升级。 + +``` +int main(int argc, char **argv) +{ + printf("this is update print!\r\n"); + if (HotaInit(NULL, NULL) < 0) { + printf("ota update init fail!\r\n"); + return -1; + } + int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); + if (fd < 0) { + printf("file open failed, fd = %d\r\n", fd); + (void)HotaCancel(); + return -1; + } + int offset = 0; + int fileLen = lseek(fd, 0, SEEK_END); + int leftLen = fileLen; + while (leftLen > 0) { + if (lseek(fd, offset, SEEK_SET) < 0) { + close(fd); + printf("lseek fail!\r\n"); + (void)HotaCancel(); + return -1; + } + int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; + (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); + if (read(fd, g_readBuf, tmpLen) < 0) { + close(fd); + printf("read fail!\r\n"); + (void)HotaCancel(); + return -1; + } + if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { + printf("ota write fail!\r\n"); + close(fd); + (void)HotaCancel(); + return -1; + } + offset += READ_BUF_LEN; + leftLen -= tmpLen; + } + close(fd); + printf("ota write finish!\r\n"); + printf("device will reboot in 10s...\r\n"); + sleep(10); + (void)HotaRestart(); + return 0; +} +``` + +## API应用场景-定制场景 + +升级包不是按照上文“生成公私钥对”和“生成升级包”章节制作的,是通过其它方式制作的。 + +### **开发指导** + +1. 应用侧通过下载,获取当前设备升级包后,调用HotaInit接口初始化。 +2. 使用HotaSetPackageType接口设置NOT\_USE\_DEFAULT\_PKG,使用"定制"流程。 +3. 调用HotaWrite接口传入升级包数据流,写入设备。 +4. 写入完成后,调用HotaRead接口读取数据,厂商可以自行校验升级包。 +5. 调用HotaSetBootSettings设置启动标记,在重启后需要进入uboot模式时使用(可选)。 +6. 调用HotaRestart接口,进行重启。 + + 升级过程中,使用HotaCancel接口可以取消升级。 + + +### **示例代码** + +使用非OpenHarmony的“升级包格式和校验方法“进行升级。 + +``` +int main(int argc, char **argv) +{ + printf("this is update print!\r\n"); + if (HotaInit(NULL, NULL) < 0) { + printf("ota update init fail!\r\n"); + (void)HotaCancel(); + return -1; + } + (void)HotaSetPackageType(NOT_USE_DEFAULT_PKG); + int fd = open(OTA_PKG_FILE, O_RDWR, S_IRUSR | S_IWUSR); + if (fd < 0) { + printf("file open failed, fd = %d\r\n", fd); + (void)HotaCancel(); + return -1; + } + int offset = 0; + int fileLen = lseek(fd, 0, SEEK_END); + int leftLen = fileLen; + while (leftLen > 0) { + if (lseek(fd, offset, SEEK_SET) < 0) { + close(fd); + printf("lseek fail!\r\n"); + (void)HotaCancel(); + return -1; + } + int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; + (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); + if (read(fd, g_readBuf, tmpLen) < 0) { + close(fd); + printf("read fail!\r\n"); + (void)HotaCancel(); + return -1; + } + if (HotaWrite((unsigned char *)g_readBuf, offset, tmpLen) != 0) { + printf("ota write fail!\r\n"); + close(fd); + (void)HotaCancel(); + return -1; + } + offset += READ_BUF_LEN; + leftLen -= tmpLen; + } + close(fd); + printf("ota write finish!\r\n"); + leftLen = fileLen; + while (leftLen > 0) { + int tmpLen = leftLen >= READ_BUF_LEN ? READ_BUF_LEN : leftLen; + (void)memset_s(g_readBuf, READ_BUF_LEN, 0, READ_BUF_LEN); + if (HotaRead(offset, READ_BUF_LEN, (unsigned char *)g_readBuf) != 0) {} + printf("ota write fail!\r\n"); + (void)HotaCancel(); + return -1; + } + /* do your verify and parse */ + offset += READ_BUF_LEN; + leftLen -= tmpLen; + } + /* set your boot settings */ + (void)HotaSetBootSettings(); + printf("device will reboot in 10s...\r\n"); + sleep(10); + (void)HotaRestart(); + return 0; +} +``` + +## 系统升级 + +厂商应用调用OTA模块的API,OTA模块执行升级包的签名验证、版本防回滚、烧写落盘功能,升级完成后自动重启系统。 + +对Hi3518EV300/Hi3516DV300开源套件,在需要实现防回滚功能的版本中,需要增加LOCAL\_VERSION的值,如"ohos default 1.0"-\>"ohos default 1.1",LOCAL\_VERSION在device\\hisilicon\\third\_party\\uboot\\u-boot-2020.01\\product\\hiupdate\\ota\_update\\ota\_local\_info.c中。 + +示例,增加版本号 + +``` +const char *get_local_version(void) +{ +#if defined(CONFIG_TARGET_HI3516EV200) || \ + defined(CONFIG_TARGET_HI3516DV300) || \ + defined(CONFIG_TARGET_HI3518EV300) +#define LOCAL_VERSION "ohos default 1.0" /* increase: default release version */ +``` + diff --git "a/zh-cn/device-dev/subsystems/\345\210\206\345\270\203\345\274\217\350\277\234\347\250\213\345\220\257\345\212\250.md" b/zh-cn/device-dev/subsystems/subsys-remote-start.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\210\206\345\270\203\345\274\217\350\277\234\347\250\213\345\220\257\345\212\250.md" rename to zh-cn/device-dev/subsystems/subsys-remote-start.md diff --git "a/zh-cn/device-dev/subsystems/IPC\351\200\232\344\277\241\351\211\264\346\235\203\345\274\200\345\217\221\346\214\207\345\257\274.md" b/zh-cn/device-dev/subsystems/subsys-security-communicationverify.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/IPC\351\200\232\344\277\241\351\211\264\346\235\203\345\274\200\345\217\221\346\214\207\345\257\274.md" rename to zh-cn/device-dev/subsystems/subsys-security-communicationverify.md diff --git a/zh-cn/device-dev/subsystems/subsys-security-overview.md b/zh-cn/device-dev/subsystems/subsys-security-overview.md new file mode 100644 index 0000000000000000000000000000000000000000..5c47b308081819cc88c581f359cca3b4dc8cdd8f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-overview.md @@ -0,0 +1,76 @@ +# 概述 + +- [基本概念](#section175012297491) +- [约束与限制](#section2029921310472) + +OpenHarmony安全子系统目前提供给开发者的安全能力主要包含应用可信、权限管理、设备可信。涉及以下几个模块: + +- 应用验签 + + 为了确保应用内容的完整性,系统通过应用签名和Profile对应用的来源进行管控,同时对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 + +- 应用权限管理 + + 应用权限是管理应用访问系统资源和使用系统能力的一种通用方式,应用在开发阶段需要在profile.json中指明此应用在运行过程中可能会调用哪些权限,其中静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示涉及到敏感信息,所以需要用户进行动态授权。 + +- IPC通信鉴权 + + 系统服务通过IPC暴露接口给其他进程访问,这些接口需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则拒绝访问该接口。 + +- 可信设备群组管理 + + 提供基于群组概念的同华为账号群组、点对点群组(如二维码、碰一碰等)的设备安全可信关系的创建和查询,分布式应用可基于该能力进行设备间的可信认证,然后向分布式软总线请求设备间安全会话。 + + +## 基本概念 + +在进行依赖验签组件的应用开发前,开发者应了解以下基本概念: + +- Samgr + + Samgr\(System Ability Manager\)系统能力管理,在OpenHarmony上作为一个管理系统能力的模块,详见系统服务框架子系统。 + + +- BMS + + BMS\(Bundle Manager Service\)包管理管理,在OpenHarmony上主要负责应用的安装、卸载和数据管理。 + + +- 描述文件 + + 本文中的描述文件,指HarmonyAppProvision,简称profile。HarmonyAppProvision采用json文件格式进行描述。 + + +- 叶子证书 + + 最终用于为整包或profile签名的证书称为叶子证书,位于数字证书链的最末端。 + + +- 调试应用 + + 指开发者从应用市场申请调试证书与调试描述文件,并以此签名的hap包。 + + +- 待上架应用 + + 指开发者从应用市场申请发布证书与发布描述文件,以此签名,未通过应用市场正式发布的hap包。 + + +- 发布应用 + + 指开发者从应用市场申请发布证书与发布描述文件,以此签名的hap包,上传至应用市场,并由应用市场正式发布的hap包。 + + +- OpenHarmony自签名应用 + + 当开发者自行编译OpenHarmony系统应用后,采用原应用描述文件,以及公开的OpenHarmony公私钥对和证书进行自签名产生的hap包。 + + +## 约束与限制 + +- 仅支持以下三类应用的验签:应用市场调试应用、应用市场发布应用、OpenHarmony自签名应用的验签。 +- 若对应用市场调试应用验签,则本机UDID需要在描述文件包含的UDID列表中。 +- 待上架应用无法验签通过。 +- 验签组件提供的接口都位于security\_interfaces\_innerkits\_app\_verify仓[app\_verify\_pub.h](https://gitee.com/fork_ohos_wj/security_interfaces_innerkits_app_verify/blob/master/app_verify_pub.h)中,仅支持系统应用开发者调用。 +- 可信设备群组管理接口,目前只对系统签名权限才可以使用。 + diff --git a/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md b/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md new file mode 100644 index 0000000000000000000000000000000000000000..37f3cdbbf7c82ceb3489f67358c7ac0f1b07e2bf --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-rightmanagement.md @@ -0,0 +1,228 @@ +# 应用权限管理开发指导 + +- [运作机制](#section193961322175011) +- [场景介绍](#section18502174174019) +- [接口说明](#section1633115419401) +- [开发步骤](#section022611498210) + +## 运作机制 + +由于OpenHarmony允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 + +**表 1** OpenHarmony权限列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

OpenHarmony权限

+

授权方式

+

权限说明

+

ohos.permission.LISTEN_BUNDLE_CHANGE

+

system_grant(静态权限)

+

允许该应用获取应用变化消息。

+

ohos.permission.GET_BUNDLE_INFO

+

system_grant(静态权限)

+

允许该应用获取应用信息。

+

ohos.permission.INSTALL_BUNDLE

+

system_grant(静态权限)

+

允许该应用安装应用。

+

ohos.permission.CAMERA

+

user_grant(动态权限)

+

此应用可随时使用相机拍摄照片和录制视频。

+

ohos.permission.MODIFY_AUDIO_SETTINGS

+

system_grant(静态权限)

+

允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

+

ohos.permission.READ_MEDIA

+

user_grant(动态权限)

+

允许该应用读取您的视频收藏。

+

ohos.permission.MICROPHONE

+

user_grant(动态权限)

+

此应用可随时使用麦克风进行录音。

+

ohos.permission.WRITE_MEDIA

+

user_grant(动态权限)

+

允许该应用写入您的音乐收藏。

+

ohos.permission.DISTRIBUTED_DATASYNC

+

user_grant(动态权限)

+

管控分布式数据传输能力。

+

ohos.permission.DISTRIBUTED_VIRTUALDEVICE

+

user_grant(动态权限)

+

允许应用使用分布式虚拟能力

+
+ +>![](../public_sys-resources/icon-note.gif) **说明:** +>静态权限:应用安装时由系统授予的权限,对应于权限敏感级别的system\_grant +>动态权限:应用在运行过程中需要用户授权的权限,对应于权限敏感级别的user\_grant + +## 场景介绍 + +应用权限是软件用来访问系统资源和使用系统能力的一种通行方式。在涉及用户隐私相关功能和数据的场景,例如:访问个人设备的硬件特性,如摄像头、麦克风,以及读写媒体文件等,OpenHarmony通过应用权限管理组件来保护这些数据以及能力。 + +在系统应用开发过程中,如果应用要使用敏感权限,开发者可以调用应用权限管理组件接口检查待访问权限是否被授权,如果未授权,操作不允许。 + +## 接口说明 + +应用权限管理提供的API接口,当前仅供系统应用和系统服务调用,具体API接口如下。 + +**表 2** 应用权限管理API接口功能介绍 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

int CheckPermission(int uid, const char *permissionName)

+

检查指定UID的应用进程是否具有访问系统服务API的权限

+

int CheckSelfPermission(const char *permissionName)

+

检查调用者是否具有访问系统服务API的权限

+

int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

+

查询应用申请的所有权限,并检查权限是否被授予

+

int GrantPermission(const char *identifier, const char *permName)

+

将指定权限授予应用程序

+

int RevokePermission(const char *identifier, const char *permName)

+

收回应用程序的指定权限

+

int GrantRuntimePermission(int uid, const char *permissionName)

+

应用运行时动态授予指定权限

+

int RevokeRuntimePermission(int uid, const char *permissionName)

+

应用运行时动态撤销指定权限

+
+ +## 开发步骤 + +本部分以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 + +1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL\_BUNDLE),并在config.json中声明该权限; + + ``` + { + ... + "module": { + "package": "com.huawei.kitframework", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" + ], + "reqPermissions": [{ + // 声明需要的权限:安装应用程序的权限名 + "name": "ohos.permission.INSTALL_BUNDLE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + }, + { + "name": "ohos.permission.GET_BUNDLE_INFO", + "reason": "install bundle", + "usedScene": { + "ability": [ + "KitFramework" + ], + "when": "always" + } + } + ], + ... + } + ``` + +2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL\_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; + + ``` + constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; + + bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) + { + if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); + return false; + } + // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 + if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { + HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); + return false; // 返回安装失败 + } + // 安装流程 + ... + } + ``` + + diff --git a/zh-cn/device-dev/subsystems/subsys-security-sigverify.md b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md new file mode 100644 index 0000000000000000000000000000000000000000..a7e2f85b64ec50c09ad516a117b157d71907c11f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security-sigverify.md @@ -0,0 +1,272 @@ +# 应用验签开发指导 + +- [场景介绍](#section18502174174019) +- [验签流程](#section554632717226) +- [接口说明](#section1633115419401) +- [开发步骤(场景一)](#section4207112818418) + - [验签指导](#section11470123816297) + - [生成OpenHarmony自签名应用](#section167151429133312) + - [开发示例](#section174318361353) + +- [开发步骤(场景二)](#section81272563427) + - [验签指导](#section07028210442) + - [开发示例](#section1930711345445) + +- [调测验证](#section427316292411) + +## 场景介绍 + +当需要验证调试应用、发布应用,OpenHarmony自签名应用的完整性是否被破坏时,可以调用验签组件的接口进行验证。如有需要还可通过验签接口获取部分描述文件信息,如appid。对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 + +## 验签流程 + +未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。 + +经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由文件签名数据块(data sign block)、描述文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。 + +**图 1** 经过签名的Hap包结构 + + +![](figure/安全子系统.png) + +整个验签流程,主要分为三部分:整包验签、描述文件签名块验签,以及描述文件内容校验。 + +**整包验签** + +用设备的预置根证书,通过证书链来证明叶子证书本身是可信的,然后用叶子证书的公钥解密出的摘要证明整包是未篡改的。 + +具体操作步骤如下: + +1. 对文件签名数据块中的证书链进行校验,确定其叶子证书是可信的。 +2. 用叶子证书中的公钥对文件签名块进行验签,证明其未被篡改。 +3. 计算并合并文件块,中心目录块和中心目录结尾块的摘要。然后将计算结果,再与签名块中的描述文件签名块的摘要合并,将最终合并的摘要与文件签名块中包含的摘要对比,如果两者相等,则整包验签通过。 + +**描述文件签名块验签** + +首先判断文件签名的签发单位,如果是应用市场签发的发布应用,则无需对描述文件进行验签,直接信任,否则要对其验签。先取出整个描述文件签名块,然后验证证书链,最后用叶子证书对描述文件数据块验签,证明其未被篡改。 + +**描述文件内容校验** + +取出描述文件,并对其内容进行合法性检查。其中若hap包为调试应用,则会比对本机UDID与描述文件中包含的UDID列表,如果本机UDID在描述文件的UDID列表中包含,则验证通过。比较描述文件中包含的证书(如果是应用市场发布应用或OpenHarmony自签名则无需比较),和整包校验时使用的叶子证书,如果相同,认为整个验签流程完成。 + +## 接口说明 + +验签组件当前提供innerkits接口,仅供系统应用调用,相关接口及功能描述如下: + +**表 1** 验签组件API接口功能介绍 + + + + + + + + + + + + + + + + +

接口名

+

描述

+

int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst)

+

主入口函数,输入文件路径,进行验签,并将从描述文件中获取的数据通过verifyRst返回给调用者

+

int APPVERI_SetDebugMode(bool mode)

+

设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。

+

注:当前没有基于现有测试根密钥的证书,开发者可根据自身需要,替换测试根密钥并进行相关验证。

+

void APPVERI_FreeVerifyRst(VerifyResult *verifyRst)

+

释放verifyRst中申请的内存

+
+ +## 开发步骤(场景一) + +### 验签指导 + +对应用市场发布应用、基于应用市场调试证书签发的调试应用、OpenHarmony自签名应用的校验。 + +1. 定义出参结构体变量VerifyResult; + + ``` + VerifyResult verifyResult = {0}; + ``` + +2. 以文件路径及VerifyResult为入参,调用APPVERI\_AppVerify进行文件校验; + + ``` + int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); + ``` + +3. 判断返回结果,如果校验通过的话,获取VerifyResult中的数据,进行业务处理; + + ``` + signatureInfo.appId = verifyResult.profile.appid; + signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; + ``` + +4. 调用APPVERI\_FreeVerifyRst,释放VerifyResult中申请的内存。 + + ``` + APPVERI_FreeVerifyRst(&verifyResult); + ``` + + +### 生成OpenHarmony自签名应用 + +如果是OpenHarmony自签名应用的校验,开发者可通过以下方式生成OpenHarmony自签名应用。 + +1. 材料备齐。 + + 生成自签名应用需要的材料有:签名工具、系统应用hap包、系统应用profile文件\(\*.p7b\)、签名证书\(\*.cer\)、签名公私钥对\(\*.jks\)。 + +2. 将所有材料放在同一个目录下,打开shell。 +3. 根据应用、描述文件的实际名称修改指令,并在shell中输入,完成签名。 + + ``` + java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1 + ``` + + 关键字段说明: + + -jar:签名工具,[hapsigntool](https://repo.huaweicloud.com/harmonyos/develop_tools/hapsigntoolv2.jar) + + -mode:本地签名标记位,固定为localjks + + -privatekey:密钥对别名,签名公私钥对的别名为OpenHarmony Software Signature + + -inputFile:待签名应用,通过编译产生 + + -outputFile:签名后应用,最终输出 + + -signAlg:签名算法,当前固定为SHA256withECDSA + + -keystore:公私钥对,使用签名公私钥对,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.jks](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks)。默认密码为123456 ,用户可采用工具\(例如keytool\)更改默认密码 + + -keystorepasswd:公私钥对密码,默认签名公私钥对密码为123456 + + -keyaliaspasswd:公私钥对别名密码,默认签名公私钥对别名密码为123456 + + -profile:描述文件,应用的描述文件位于对应源代码目录中 + + -certpath:使用签名证书,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.cer](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer) + + -profileSigned:签名块中是否包含描述文件\(profile\)。固定为1(包含) + + +### 开发示例 + +以应用管理框架组件在应用安装时进行验签的实际调用为例: + +``` +uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) +{ + bool mode = ManagerService::GetInstance().IsDebugMode(); + HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); + // 定义结果结构体 + VerifyResult verifyResult = {0}; + // 输入待验签文件路径进行验签 + int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); + uint8_t errorCode = SwitchErrorCode(ret); + if (errorCode != ERR_OK) { + return errorCode; + } + // 从结果结构体中获取appid + signatureInfo.appId = verifyResult.profile.appid; + // 从结果结构体中获取描述文件中书写的应用名 + signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; + int32_t restricNum = verifyResult.profile.permission.restricNum; + for (int32_t i = 0; i < restricNum; i++) { + signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); + } + // 释放结果结构体中申请的内存 + APPVERI_FreeVerifyRst(&verifyResult); + return ERR_OK; +} +``` + +## 开发步骤(场景二) + +### 验签指导 + +对采用基于测试根密钥证书签名的应用的校验。 + +1. 调用APPVERI\_SetDebugMode\(true\)开启测试模式; + + ``` + ManagerService::SetDebugMode(true); + ... + uint8_t ManagerService::SetDebugMode(bool enable) + { + int32_t ret = APPVERI_SetDebugMode(enable); + if (ret < 0) { + HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); + return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; + } + isDebugMode_ = enable; + HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); + return ERR_OK; + } + ``` + +2. 同场景一中步骤一至四,定义结构体,校验、释放结构体; +3. 调用APPVERI\_SetDebugMode\(false\)关闭测试模式。 + + ``` + ManagerService::SetDebugMode(false); + ``` + + +### 开发示例 + +完整开发示例如下(在场景一代码示例的基础上进行补充): + +``` +uint8_t ManagerService::SetDebugMode(bool enable) +{ + int32_t ret = APPVERI_SetDebugMode(enable); + if (ret < 0) { + HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); + return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; + } + isDebugMode_ = enable; + HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); + return ERR_OK; +} +uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) +{ + // 开启支持测试服务器签名应用验证 + ManagerService::SetDebugMode(true); + bool mode = ManagerService::GetInstance().IsDebugMode(); + HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); + // 定义结果结构体 + VerifyResult verifyResult = {0}; + // 输入待验签文件路径进行验签 + int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); + uint8_t errorCode = SwitchErrorCode(ret); + if (errorCode != ERR_OK) { + return errorCode; + } + // 从结果结构体中获取appid + signatureInfo.appId = verifyResult.profile.appid; + // 从结果结构体中获取描述文件中书写的应用名 + signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; + int32_t restricNum = verifyResult.profile.permission.restricNum; + for (int32_t i = 0; i < restricNum; i++) { + signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); + } + // 释放结果结构体中申请的内存 + APPVERI_FreeVerifyRst(&verifyResult); + // 关闭支持测试服务器签名应用验证 + ManagerService::SetDebugMode(false); + return ERR_OK; +} +``` + +## 调测验证 + +1. 选取一个在OpenHarmony上能够正常安装的应用A。 +2. 根据开发指导开发。 +3. 对应用A,采用自开发程序进行验签,验签通过,能获取到appid。即为开发成功。 + diff --git a/zh-cn/device-dev/subsystems/subsys-security.md b/zh-cn/device-dev/subsystems/subsys-security.md new file mode 100644 index 0000000000000000000000000000000000000000..1a0b0eb10140d07891972385e3ba30d5018d0f63 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-security.md @@ -0,0 +1,11 @@ +# 安全 + +- **[概述](subsys-security-overview.md)** + +- **[应用验签开发指导](subsys-security-sigverify.md)** + +- **[应用权限管理开发指导](subsys-security-rightmanagement.md)** + +- **[IPC通信鉴权开发指导](subsys-security-communicationverify.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-testguide-test.md b/zh-cn/device-dev/subsystems/subsys-testguide-test.md new file mode 100644 index 0000000000000000000000000000000000000000..2403929934b2c2860c3e2dd2200e9a9046930e64 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-testguide-test.md @@ -0,0 +1,989 @@ +# 测试 + +- [概述](#section12403172115920) + - [基本概念](#section53632272090) + - [运作机制](#section2394431106) + +- [约束与限制](#section2029921310472) +- [搭建环境](#section175012297491) + - [环境要求](#section935055691014) + - [安装环境](#section6511193210111) + - [检验环境是否搭建成功](#section1899144517117) + +- [开发指导](#section16741101301210) + - [场景介绍](#section93782214124) + - [接口说明](#section54131732101218) + - [开发步骤](#section53541946111218) + +- [开发实例](#section7477121918136) +- [测试平台使用](#section76401945124810) +- [包结构说明](#section1875515364133) + +## 概述 + +### 基本概念 + +测试子系统提供基于python开发的一键式的开发者自测试平台,支持跨平台使用以及三方测试框架拓展,主要包括测试用例编译、测试用例管理、测试用例调度分发、测试用例执行、测试结果收集、测试报告生成、测试用例模板、测试环境管理等模块。 + +在测试子系统开发前,开发者应先了解以下概念: + +- 测试用例编译 + + 支持将测试用例源代码编译成可在被测设备侧执行的二进制文件。 + +- 测试用例调度分发 + + 支持将测试用例通过网口通道或者串口通道分发到不同的被测设备上,并且为每一个测试用例分配特定的测试用例执行器。 + +- 测试用例执行器 + + 负责测试用例的预处理,用例执行,结果记录等执行逻辑。 + +- 测试用例模板 + + 定义了测试用例以及用例编译配置GN文件的统一格式。 + +- 测试平台kit + + 测试平台运行过程中公共方法,如提供测试用例目录向被测设备挂载文件系统,测试用例推送到被测设备,或者从被测设备获取测试结果等操作。 + +- 测试报告生成 + + 定义开发者自测试报告模板,生成web测试报告。 + +- 测试环境管理 + + 支持通过USB、串口等方式管理被测设备,功能包括设备发现,设备状态查询等。 + + +### 运作机制 + +- 测试平台架构图如下: + +**图 1** 测试平台架构 +![](figure/测试平台架构.png "测试平台架构") + +- 测试平台运行时序图如下: + +**图 2** 测试平台运行时序 +![](figure/测试平台运行时序.png "测试平台运行时序") + +- 测试平台运行原理 + +测试平台通过shell脚本启动,以命令行方式支持一系列的测试指令执行,通过命令行输出测试结果。 + +## 约束与限制 + +- 功能使用范围:开发自测试平台仅支持代码级的测试用例开发和验证,如单元测试,模块测试。 +- 规格限制:当前测试框架的适用范围仅支持白盒测试。 +- 操作限制:一台测试设备上仅支持启动单个测试平台。 + +## 搭建环境 + +### 环境要求 + +**表 1** **环境要求** + + + + + + + + + + + + + + + + +

项目

+

测试设备

+

被测设备

+

硬件

+
  • 内存:8G及以上
  • 硬盘:100G及以上
  • 硬件架构:X86或ARM64
+
  • Hi3516 DV300开发板
  • Hi3518 EV300开发板
+

软件

+
  • 操作系统:Windows 10 64位 或 Ubuntu 18.04

    系统组件(Linux): libreadline-dev

    +
  • Python:3.7.5及以上
  • Python插件:pyserial3.3及以上、paramiko2.7.1及以上、setuptools40.8.0及以上,rsa4.0及以上
  • NFS Server:haneWIN NFS Server1.2.50及以上或者 NFSv4及以上
+
  • 系统软件:版本不低于OpenHarmony 1.0
  • 内核类型:LiteOS-A或者Linux
+
+ +### 安装环境 + +1. 如测试环境为Linux,需要安装系统组件readline,命令如下: + + ``` + sudo apt-get install libreadline-dev + ``` + + 安装成功提示如下: + + ``` + Reading package lists... Done + Building dependency tree + Reading state information... Done + libreadline-dev is already the newest version (7.0-3). + 0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded. + ``` + +2. 安装Python扩展组件setuptools、(rsa、paramiko、以及pyserial,设备仅支持串口时安装),命令如下: + + 1、安装setuptools,安装命令如下: + + ``` + pip install setuptools + ``` + + 安装成功提示如下: + + ``` + Requirement already satisfied: setuptools in d:\programs\python37\lib\site-packages (41.2.0) + ``` + + 2、安装rsa,安装命令如下: + + ``` + pip install rsa + ``` + + 安装成功提示如下: + + ``` + Installing collected packages: pyasn1, rsa + Successfully installed pyasn1-0.4.8 rsa-4.7 + ``` + + 3、安装Paramiko,安装命令如下: + + ``` + pip install paramiko + ``` + + 安装成功提示如下: + + ``` + Installing collected packages: pycparser, cffi, pynacl, bcrypt, cryptography, paramiko + Successfully installed bcrypt-3.2.0 cffi-1.14.4 cryptography-3.3.1 paramiko-2.7.2 pycparser-2.20 pynacl-1.4.0 + ``` + + 4、安装pyserial(被测设备仅支持串口时安装),安装命令如下: + + ``` + pip install pyserial + ``` + + 安装成功提示如下: + + ``` + Requirement already satisfied: pyserial in d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg (3.4) + ``` + +3. 安装NFS server(被测设备仅支持串口时安装)。 + + **Windows环境安装** + + 下载并安装haneWIN NFS Server1.2.50,地址:https://www.hanewin.net/nfs-e.htm + + **Linux环境下安装** + + ``` + sudo apt install nfs-kernel-server + ``` + + 所有环境配置安装完成,即可在IDE中进行测试平台代码开发调试,推荐的IDE为 DevEco Studio。 + + +### 检验环境是否搭建成功 + +**表 2** **检验环境** + + + + + + + + + + + + + + + + + + + + +

检查项

+

操作

+

满足条件

+

检查python安装与否,版本是否满足要求。

+

命令行窗口执行命令:python --version。

+

版本不小于3.7.5即可。

+

检查python扩展插件安装与否。

+

打开test/xdevice目录,执行run.bat或run.sh。

+

可进入提示符“>>>”界面即可。

+

检查NFS Server启动状态(被测设备仅支持串口时检测)。

+

通过串口登录开发板,执行mount命令挂载NFS。

+

可正常挂载文件目录即可。

+
+ +## 开发指导 + +### 场景介绍 + +针对对开发的业务代码进行白盒测试验证。 + +### 接口说明 + +测试框架集成了开源的单元测试框架,并对测试用例的宏定义做了扩展,具体框架说明详见开源官方文档。 + +**表 3** 测试框架扩展宏定义说明 + + + + + + + + + + + + + + + + +

宏定义

+

描述

+

HWTEST

+

测试用例执行不依赖Setup&Teardown。HWTEST对TEST增加了“用例级别”参数“TestSize.Level1”,例如HWTEST(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

+

HWTEST_F

+

测试用例(不带参数)执行依赖Setup&Teardown。HWTEST_F对TEST_F增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_F(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

+

HWTEST_P

+

测试用例(带参数)执行依赖Setup&Teardown。HWTEST_P对TEST_P增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_P(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

+
+ +### 开发步骤 + +1. 按照开发者测试用例目录规划定义测试套文件,需要继承testing::Test类,命名以被测特性+Test命名,示例代码路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp + + ``` + /* + * Copyright (c) 2020 OpenHarmony. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include + + using namespace std; + using namespace testing::ext; + + class CalcSubtractionTest : public testing::Test { + public: + static void SetUpTestCase(void); + static void TearDownTestCase(void); + void SetUp(); + void TearDown(); + }; + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >测试用例规范 + >- 命名规范 + > 测试用例源文件名称和测试套内容保持一致,测试套与用例之间关系1:N,测试套与测试源文件之间关系1:1,每个源文件全局唯一,格式:\[特性\]\_\[功能\]\_\[子功能1\]\_\[子功能1.1\],子功能支持向下细分。 + > 文件命名采用全小写+下划线方式命名,以test结尾,如demo用例:developertest/examples/lite/cxx\_demo + >- 测试用例编码规范 + > 开发者测试用例原则上与特性代码编码规范保持一致,另外需要添加必要的用例描述信息,详见[•自测试用例模板](#li2069415903917)。 + >- 测试用例编译配置规范 + > 测试用例采用GN方式编译,配置遵循本开源项目的[编译指导](subsys-build-mini-lite.md)。 + >- 测试用例模板 + > 详见测试demo用例:developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp + +2. 实现测试套执行过程需要的预处理操作和后处理操作,即实现SetUp和TearDown方法。 + + ``` + void CalcSubtractionTest::SetUpTestCase(void) + { + // step 1: input testsuite setup step + } + + void CalcSubtractionTest::TearDownTestCase(void) + { + // step 2: input testsuite teardown step + } + + void CalcSubtractionTest::SetUp(void) + { + // step 3: input testcase setup step + } + + void CalcSubtractionTest::TearDown(void) + { + // step 4: input testcase teardown step + } + ``` + +3. 针对被测对象的特性编写测试用例,以使用HWTEST\_F为例说明。 + + ``` + /** + * @tc.name: integer_sub_001 + * @tc.desc: Test Calculator + * @tc.type: FUNC + * @tc.require: AR00000000 SR00000000 + */ + HWTEST_F(CalcSubtractionTest, integer_sub_001, TestSize.Level1) + { + EXPECT_EQ(0, Subtraction(1, 0)); + } + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >- @tc.name:用例名称,对测试目的简要描述。 + >- @tc.desc:描述用例详细描述,包括测试目的、测试步骤、期望结果等。 + >- @tc.type:测试属性分类(FUNC、PERF、SECU、RELI)。 + >- @tc.require:需求编号或者issue编号,用来将修改与用例关联。 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

序号

+

测试类型名称

+

缩写

+

测试类型描述

+

1

+

功能测试(functionality)

+

FUNC

+

验证软件各个功能满足功能设计与规格。

+

2

+

性能测试(performance)

+

PERF

+

验证软件是否满足性能设计指标。包含负载测试容量测试,压力测试等。

+

3

+

安全性测试(security)

+

SECU

+

验证软件在生命周期内符合安全需求定义和相关法规。

+

4

+

可靠性测试(reliability)

+

RELI

+

在规定的条件下,在规定的时间内,软件不引起系统失效的概率,这里也包含稳定性。

+
+ +4. 编写用例编译GN文件,其中包括定义用例编译目标,添加编译配置依赖,源文件等,举例说明: + + 示例文件路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/BUILD.gn)。 + + ``` + import("//build/lite/config/test.gni") + + unittest("CalcSubTest") { + output_extension = "bin" + sources = [ + "calc_subtraction_test.cpp" + ] + include_dirs = [] + deps = [] + } + ``` + +5. 将用例编译目标添加到子系统编译配置中,保证用例随版本一起编译,举例说明: + 1. 支持hdc连接的设备,编译配置示例路径:test/developertest/examples/ohos.build。 + + ``` + { + "subsystem": "subsystem_examples", + "parts": { + "subsystem_examples": { + "module_list": [ + "//test/developertest/examples/detector:detector", + ... ... + ], + "test_list": [ + "//test/developertest/examples/detector/test:unittest", + ... ... + ] + }, + ... ... + } + ``` + + 2. 仅支持串口的设备,编译配置示例路径:test/developertest/examples/lite/BUILD.gn。 + + ``` + import("//build/lite/config/test.gni") + + subsystem_test("test") { + test_components = [] + if(ohos_kernel_type == "liteos_riscv") { + features += [ + ] + }else if(ohos_kernel_type == "liteos_a") { + test_components += [ + "//test/developertest/examples/lite/cxx_demo/test/unittest/common:CalcSubTest" + ] + } + } + ``` + + +6. 编写测试用例资源配置,当测试用例需要使用静态测试资源文件时使用该配置。 + 1. 在部件或者模块的test目录下创建resource目录。 + 2. 在resource目录下创建形态目录,如phone。 + 3. 在设备形态目录下创建一个以模块名命名的文件夹,如testmodule。 + 4. 在模块目录下创建一个ohos\_test.xml文件,文件内容格式如下: + + ``` + + + + + + + + ``` + + 5. 在测试用例的编译配置文件中定义resource\_config\_file,用来指定对应的资源文件ohos\_test.xml。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >如上资源文件功能:将resource目录下的test.txt文件通过hdc push命令推送到被测设备的/data/test/resource目录下。 + + +7. 以上步骤完成即完成测试用例编写,即可执行测试用例。 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >- 支持hdc连接的设备,测试用例支持单独编译。 + >- 仅支持串口连接的设备,在代码根路径下执行编译debug版本的命令,即可编译测试用例。 + > 测试用例用例的执行详见[测试平台使用](#section76401945124810)。 + + +## 开发实例 + +测试子系统代码仓提供了完整demo用例,demo用例路径:test/developertest/examples/。以一个减法运算方法编写测试用例举例说明: + +- 被测代码如下: + + ``` + static int Subtraction(int a, int b) + { + return a - b; + } + ``` + +- 测试用例代码如下: + + ``` + /** + * @tc.name: integer_sub_002 + * @tc.desc: Verify the Subtraction function. + * @tc.type: FUNC + * @tc.require: AR00000000 SR00000000 + */ + HWTEST_F(CalcSubtractionTest, integer_sub_002, TestSize.Level1) + { + EXPECT_EQ(1, Subtraction(2, 1)); + } + ``` + + +## 测试平台使用 + +1. (可选)安装xdevice组件。安装xdevice后,xdevice组件可以作为python的扩展包使用。 + + 打开xdevice安装目录:test/xdevice,执行如下命令: + + ``` + python setup.py install + ``` + + 安装成功提示如下: + + ``` + ... ... + Installed d:\programs\python37\lib\site-packages\xdevice-0.0.0-py3.7.egg + Processing dependencies for xdevice==0.0.0 + Searching for pyserial==3.4 + Best match: pyserial 3.4 + Processing pyserial-3.4-py3.7.egg + pyserial 3.4 is already the active version in easy-install.pth + Installing miniterm.py script to D:\Programs\Python37\Scripts + + Using d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg + Finished processing dependencies for xdevice==0.0.0 + ``` + +2. 修改developertest/config/user\_config.xml 文件配置developertest组件。 + 1. 测试框架通用配置。 + + \[build\] \# 配置测试用例的编译参数,例如: + + ``` + + false + false + true + ... ... + + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >测试用例的编译参数说明如下: + >example:是否编译测试用例示例,默认false。 + >version:是否编译测试版本,默认false。 + >testcase:是否编译测试用例,默认true。 + + 2. 支持hdc连接的被测设备。 + + \[device\] \# 配置标签为usb-hdc的环境信息,测试设备的IP地址和hdc映射的端口号,例如: + + ``` + + 192.168.1.1 + 9111 + + + ``` + + 3. 仅支持串口的被测设备。 + + \[board\_info\] \# 开发板配置信息,例如: + + ``` + + hispark + taurus + ipcamera + hb build + + ``` + + >![](../public_sys-resources/icon-note.gif) **说明:** + >开发板配置信息如下: + >board\_series:开发板系列,默认hispark。 + >board\_type:开发板类型,默认taurus。 + >board\_product:目标产品,默认ipcamera。 + >build\_command:测试版本和用例的编译命令,默认hb build。 + + \[device\] \# 配置标签为ipcamera的串口信息,COM口和波特率,例如: + + ``` + + + COM1 + cmd + 115200 + 8 + 1 + 1 + + + ``` + + +3. (可选)修改developertest组件配置。如果测试用例已完成编译,可以直接指定测试用例的编译输出路径,测试平台执行用例时即不会重新编译测试用例。 + + 配置文件:config/user\_config.xml + + 1. \[test\_cases\] \# 指定测试用例的输出路径,编译输出目录,例如: + + ``` + + /home/opencode/out/release/tests + + ``` + + 2. \[NFS\] \# 被测设备仅支持串口时配置,指定NFS的映射路径,host\_dir为PC侧的NFS目录,board\_dir为板侧创建的目录,例如: + + ``` + + D:\nfs + user + + ``` + + +4. (可选)测试环境准备。当被测设备仅支持串口时,需要检查。 + - 系统镜像与文件系统已烧录进开发板,开发板上系统正常运行,在系统模式下,如使用shell登录时,设备提示符是“OHOS\#”。 + - 开发主机和开发板串口连接正常,网口连接正常。 + - 开发主机IP与开发板IP处在同一小网网段,相互可以ping通。 + - 开发主机侧创建空目录用于开发板通过NFS挂载测试用例,并且NFS服务启动正常。 + +5. (必选)启动测试平台,执行测试用例。 + - 启动测试框架,打开test/developertest目录,执行启动脚本。 + 1. Windows环境启动测试框架,执行如下脚本: + + ``` + start.bat + ``` + + 2. Linux环境启动测试框架。 + + ``` + ./start.sh + ``` + + + - 设备形态选择。 + + 根据实际的开发板选择,设备形态配置:developertest/config/framework\_config.xml。 + + - 执行测试指令。 + 1. 查询测试用例支持的子系统,模块,产品形态以及测试类型,使用show命令,示例如下: + + ``` + usage: + show productlist Querying Supported Product Forms + show typelist Querying the Supported Test Type + show subsystemlist Querying Supported Subsystems + show modulelist Querying Supported Modules + ``` + + 2. 执行测试指令,其中-t为必选,-ss和-tm为可选字段,示例如下: + + ``` + run -t ut -ss subsystem_examples -tm calculator + ``` + + 3. 参数说明:指定参数可以执行特定特性、模块对应的测试套。 + + ``` + usage: run [-h] [-p PRODUCTFORM] [-t [TESTTYPE [TESTTYPE ...]]] + [-ss SUBSYSTEM] [-tm TESTMODULE] [-ts TESTSUIT] + [-tc TESTCASE] [-tl TESTLEVEL] + + optional arguments: + -h, --help show this help message and exit + -p PRODUCTFORM, --productform PRODUCTFORM Specified product form + -t [TESTTYPE [TESTTYPE ...]], --testtype [TESTTYPE [TESTTYPE ...]] + Specify test type(UT,MST,ST,PERF,ALL) + -ss SUBSYSTEM, --subsystem SUBSYSTEM Specify test subsystem + -tm TESTMODULE, --testmodule TESTMODULE Specified test module + -ts TESTSUIT, --testsuite TESTSUIT Specify test suite + -tc TESTCASE, --testcase TESTCASE Specify test case + -tl TESTLEVEL, --testlevel TESTLEVEL Specify test level + ``` + + + - 测试框架帮助。 + + 帮助指令,用于查询测试平台支持哪些测试指令,如下: + + ``` + help + ``` + + - 退出自测试平台。 + + 退出自测试平台,使用如下命令退出测试平台,如下: + + ``` + quit + ``` + + +6. (必选)查看测试结果与日志,通过在测试平台中执行测试指令,即可在developertest/reports目录下生成测试日志和测试报告。 + - 测试用例的结果会直接显示在控制台上,执行一次的测试结果根路径如下: + + ``` + reports/xxxx-xx-xx-xx-xx-xx + ``` + + - 测试用例格式化结果目录如下: + + ``` + result/ + ``` + + - 测试用例日志目录如下: + + ``` + log/plan_log_xxxx-xx-xx-xx-xx-xx.log + ``` + + - 测试报告汇总: + + ``` + summary_report.html + ``` + + - 测试报告详情: + + ``` + details_report.html + ``` + + + - 测试平台日志目录如下: + + ``` + reports/platform_log_xxxx-xx-xx-xx-xx-xx.log + ``` + + + +## 包结构说明 + +开发者测试平台xdevice组件包结构说明,代码目录test/xdevice,详见下表所示: + +**表 4** xdevice组件包结构说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

功能描述

+

xdevice

+

测试平台基础组件。

+

xdevice/src/xdevice

+

基础测试框架源码。

+

xdevice/config

+

基础测试框架配置文件定义。

+

xdevice/src/xdevice/__main__.py

+

基础测试框架内部入口。

+

xdevice/src/xdevice/__init__.py

+

包依赖定义,插件依赖。

+

xdevice/src/xdevice/variables.py

+

全局变量定义。

+

xdevice/src/xdevice/_core/command

+

用例输入的命令行处理。

+

xdevice/src/xdevice/_core/config

+

基础测试框架的配置管理。

+

xdevice/src/xdevice/_core/environment

+

基础测试框架的环境管理,包括设备管理。

+

xdevice/src/xdevice/_core/executor

+

基础测试框架用例调度和分发。

+

xdevice/src/xdevice/_core/driver

+

基础测试框架测试执行器。

+

xdevice/src/xdevice/_core/resource

+

基础测试框架资源文件以及测试报告模板。

+

xdevice/src/xdevice/_core/testkit

+

基础测试框架公共操作,包括NFS文件系统挂载等。

+

xdevice/src/xdevice/_core/logger.py

+

基础测试框架日志管理。

+

xdevice/src/xdevice/_core/plugin.py

+

基础测试框架插件管理。

+

xdevice/src/xdevice/_core/interface.py

+

基础测试框架插件接口定义。

+

xdevice/setup.py

+

基础测试框架的安装脚本。

+

xdevice/run.bat

+

基础测试框架启动脚本(Windows)。

+

xdevice/run.sh

+

基础测试框架启动脚本(Linux)。

+
+ +开发者测试平台developertest组件包结构说明,代码目录test/developertest,详见下表所示: + +**表 5** developertest组件包结构说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

名称

+

描述

+

developertest

+

开发测试框架。

+

developertest/src

+

测试框架源码。

+

developertest/src/core

+

测试执行器。

+

developertest/src/core/build

+

测试用例编译。

+

developertest/src/core/command

+

对用户输入的命令行处理。

+

developertest/src/core/config

+

测试框架配置管理。

+

developertest/src/core/driver

+

测试框架驱动执行器。

+

developertest/src/core/resource

+

测试框架配置文件。

+

developertest/src/core/testcase

+

测试用例管理。

+

developertest/src/core/common.py

+

测试框架公共操作。

+

developertest/src/core/constants.py

+

测试框架全局常量。

+

developertest/src/core/exception.py

+

测试框架异常定义。

+

developertest/src/core/utils.py

+

测试框架工具方法。

+

developertest/src/main

+

测试框架平台。

+

developertest/src/main/__main__.py

+

测试框架内部入口。

+

developertest/examples

+

测试框架demo用例。

+

developertest/third_party

+

测试框架依赖第三方组件适配。

+

developertest/BUILD.gn

+

测试子系统编译配置。

+

developertest/start.bat

+

开发者测试入口(Windows)。

+

developertest/start.sh

+

开发者测试入口(Linux)。

+
+ diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md b/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..2c443396aca58e31aa099a8de06db028781c7fdd --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-bytrace-guide.md @@ -0,0 +1,115 @@ +# bytrace使用指导 + +- [简介](#section11388623181619) +- [开发指导](#section1595564317164) +- [使用实例](#section667273201818) + +## 简介 + +bytrace是开发人员用于追踪进程轨迹、分析性能的一种工具,主要对内核ftrace进行了封装和扩展,来支持用户态的打点。通过该工具可以打开想要查看的用户态和内核label(通过下面命令行bytrace -l,查看支持的所有label),然后通过命令行进行抓取trace信息到指定文件中。 + +## 开发指导 + +bytrace当前支持以下命令: + +**表 1** 命令行列表 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

Option

+

Description

+

-h,--help

+

查看option帮助

+

-b n,--buffer_size n

+

指定n(KB)内存大小用于存取trace日志,默认2048KB

+

-t n,--time n

+

用来指定trace运行的时间(单位:s),取决于需要分析过程的时间

+

--trace_clock clock

+

trace输出的时钟类型,一般设备支持boot、global、mono、uptime、perf等,默认为boot

+

--trace_begin

+

启动抓trace

+

--trace_dump

+

将数据输出到指定位置(默认控制台)

+

--trace_finish

+

停止抓trace,并将数据输出到指定位置(默认控制台)

+

-l,--list_categories

+

输出手机能支持的trace模块

+

--overwrite

+

当缓冲区满的时候,将丢弃最新的信息。(默认丢弃最老的日志)

+

-o filename,--output filename

+

指定输出的目标文件名称

+

-z

+

抓取trace后进行压缩

+
+ +## 使用实例 + +以下是常用bytrace命令示例,供开发者参考: + +- 查询支持的label。 + +``` +bytrace -l +``` + +或者 + +``` +bytrace --list_categories +``` + +- 设置4M缓存,抓取10秒,抓取label为ability的trace信息。 + +``` +bytrace -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace +``` + +- 设置trace的输出时钟为mono。 + +``` +bytrace --trace_clock mono -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace +``` + +- 抓取trace后进行压缩。 + +``` +bytrace -z -b 4096 -t 10 --overwrite ability > /data/mytrace.ftrace +``` + diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md b/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..93b765389398c04173ff43ab84aa32cf4eff038c --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-toolchain-hdc-guide.md @@ -0,0 +1,685 @@ +# hdc\_std 使用指导 + +- [环境准备](#section05992022154916) +- [注意事项](#section19543134915210) +- [option相关的命令](#section618522925119) +- [查询设备列表的命令](#section174891132104218) +- [服务进程相关命令](#section680531510497) +- [网络相关的命令](#section71176123212) +- [文件相关的命令](#section173133523013) +- [应用相关的命令](#section2072647133819) +- [调试相关的命令](#section112861250195015) +- [常见问题](#section592920255582) + - [hdc\_std连接不到设备](#section74019384588) + - [hdc\_std运行不了](#section63291491267) + + +hdc\_std(OpenHarmony Device Connector)是OpenHarmony为开发人员提供的用于调试的命令行工具,通过该工具可以在Windows/Linux等系统上与开发机或者模拟器进行交互。 + +下文将介绍hdc\_std的环境准备和常用命令及使用举例。 + +## 环境准备 + +**hdc\_std 工具获取方式:** + +从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 + +**使用举例:** + +下面以windows侧使用方式举例: + +从prebuilt/windows侧获取可执行文件hdc\_std.exe,放到磁盘某个位置即可使用。 + +## 注意事项 + +- 使用hdc\_std,如果出现异常,可以尝试通过hdc\_std kill命令杀掉hdc\_std服务,或者通过hdc\_std start -r命令重启服务进程进行解决。 +- 如果出现hdc\_std list targets获取不到设备信息,通过任务管理器查看是否有hdc.exe进程存在,如果进程存在,可以通过杀掉该进程进行解决。 + +## option相关的命令 + +option涉及以下命令: + +**-h/help -v/version** + +用于显示hdc相关的帮助、版本信息。 + +**表 1** 命令说明 + + + + + + + + + +

返回值

+

返回值说明

+

返回对应信息

+

帮助或者版本信息

+
+ +使用方法: + +hdc\_std -h / hdc\_std help + +hdc\_std -v / hdc\_std version + +**-t key** + +用于连接指定设备标识为key的设备。 + +**表 2** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

key

+

为tcp:port格式,或者USB序列号

+

返回值

+

返回值说明

+

①error: device '***' not found

+

②Nothing to do...

+

①设备不存在

+

②附加的命令不存在

+
+ +使用方法: + +该option需要与具体的操作命令搭配使用,下面以shell命令举例: + +hdc\_std list targets (获取设备信息) + +hdc\_std -t _key_ shell (-t后面添加的_key_ 需要替换为上面查询的设备信息) + +>![](../public_sys-resources/icon-note.gif) **说明:** +>一台开发机可支持多个设备连接,每个设备有其唯一的设备标识,如果通过网络与设备连接,其标识为tcp:port格式,如果通过usb连接则标识为设备sn号。该命令需要跟随具体操作命令。 + +## 查询设备列表的命令 + +查询设备列表涉及以下命令: + +**list targets\[-v\]** + +显示所有已经连接的目标设备列表 + +**表 3** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

-v

+

添加-v选项,则会打印设备详细信息

+

返回值

+

返回值说明

+

①返回设备信息

+

②[Empty]

+

①已经连接的设备列表信息

+

②没有查询到设备信息

+
+ +使用方法: + +hdc\_std list targets + +hdc\_std list targets -v + +## 服务进程相关命令 + +服务进程涉及以下命令: + +**target mount** + +以读写模式挂载/system等分区。 + +**表 4** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

+

+

返回值

+

返回值说明

+

①Mount finish

+

②返回具体信息

+

①成功情况下返回的信息

+

②失败情况下的具体信息

+
+ +使用方法: + +hdc\_std target mount + +**smode \[off\]** + +授予后台服务进程root权限, 使用off参数取消授权。 + +使用方法: + +hdc\_std smode + +hdc\_std smode off + +**kill \[-r\]** + +终止服务进程。 + +**表 5** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

-r

+

触发服务重启

+

返回值

+

返回值说明

+

①Kill server finish

+

②返回具体信息

+

①成功情况下返回的信息

+

②失败情况下的具体信息

+
+ +使用方法: + +hdc\_std kill + +**start \[-r\]** + +启动服务进程。 + +**表 6** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

-r

+

如果服务进程已经启动,-r选项会触发服务进程重新启动

+

返回值

+

返回值说明

+

+

+
+ +使用方法: + +hdc\_std start + +## 网络相关的命令 + +网络部分涉及以下命令: + +**tconn host\[:port\]\[-remove\]** + +通过【ip地址:端口号】来指定连接的设备 + +**表 7** 命令说明 + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

host[:port]

+

为tcp:port格式

+

-remove

+

表示断开与指定设备的连接

+

返回值

+

返回值说明

+

①返回具体信息

+

②无

+

①失败情况下的具体信息

+

②成功情况下无返回值

+
+ +使用方法(举例): + +hdc\_std tconn 192.168.0.100:8710 + +**tmode usb** + +执行后设备端对应daemon进程重启,并首先选用usb连接方式。 + +**表 8** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

+

+

返回值

+

返回值说明

+

①返回具体信息

+

②无

+

①失败情况下的具体信息

+

②成功情况下无返回值

+
+ +使用方法: + +hdc\_std tmode usb + +**tmode port port-number** + +执行后设备端对应daemon进程重启,并优先使用网络方式连接设备,如果连接设备再选择usb连接。 + +**表 9** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

port-number

+

listen连接的网络端口

+

返回值

+

返回值说明

+

①返回具体信息

+

②无

+

①失败情况下的具体信息

+

②成功情况下无返回值

+
+ +使用方法: + +hdc\_std tmode port 8710 + +>![](../public_sys-resources/icon-note.gif) **说明:** +>执行完毕后,远端daemon将会退出并重启,默认启用TCP连接,如果不加上listen端口则listen随机端口。 + +## 文件相关的命令 + +文件部分涉及以下命令: + +**file send local remote** + +发送文件至远端设备。 + +**表 10** 命令说明 + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

local

+

本地待发送文件路径

+

remote

+

远程待接收文件路径

+

返回值

+

返回值说明

+

①返回具体信息

+

②返回传输结果

+

①失败情况下的具体信息

+

②成功传输的结果信息

+
+ +使用方法(举例): + +hdc\_std file send E:\\a.txt /data/local/tmp/a.txt + +**file recv \[-a\] remote local** + +从远端设备接收文件至本地。 + +**表 11** 命令说明 + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

-a

+

文件保留时间戳模式

+

local

+

本地待接收文件路径

+

remote

+

远程待发送文件路径

+

返回值

+

返回值说明

+

①返回具体信息

+

②无

+

①失败情况下的具体信息

+

②成功情况下无返回值

+
+ +使用方法(举例): + +hdc\_std file recv /data/local/tmp/a.txt ./a.txt + +## 应用相关的命令 + +应用部分涉及以下命令: + +**install \[-r/-d/-g\] _package_** + +安装OpenHarmony package。 + +**表 12** 命令说明 + + + + + + + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

package

+

OpenHarmony应用安装包

+

-r

+

替换已存在应用

+

-d

+

允许降级安装

+

-g

+

动态授权

+

返回值

+

返回值说明

+

①返回具体信息

+

②无

+

①失败情况下的具体信息

+

②成功情况下无返回值

+
+ +使用方法(举例): + +hdc\_std install _hwadmin.hap_ + +**uninstall \[-k\] package** + +卸载OpenHarmony应用。 + +**表 13** 命令说明 + + + + + + + + + + + + + + + + + + +

参数

+

参数说明

+

package

+

OpenHarmony应用安装包

+

-k

+

保留/data/cache

+

返回值

+

返回值说明

+

①返回具体信息

+

②无

+

①失败情况下的具体信息

+

②成功情况下无返回值

+
+ +使用方法(举例): + +hdc\_std uninstall _package_ + +## 调试相关的命令 + +调试涉及以下命令: + +**hilog** + +支持抓取log信息。 + +**表 14** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

+

+

返回值

+

返回值说明

+

返回具体信息

+

抓取的日志信息

+
+ +使用方法: + +hdc\_std hilog + +**shell \[_command_\]** + +远程执行命令或进入交互命令环境。 + +**表 15** 命令说明 + + + + + + + + + + + + + + + +

参数

+

参数说明

+

command

+

需要执行的单次命令

+

返回值

+

返回值说明

+

返回具体信息

+

shell后面执行命令的结果信息

+
+ +使用方法: + +hdc\_std shell + +## 常见问题 + +### hdc\_std连接不到设备 + +- **现象描述** + + 执行 "hdc\_std list targets"命令后结果为:\[Empty\] + +- **解决方法** + 1. 设备没有被识别: + + 在设备管理器中查看是否有hdc设备,在通用串行总线设备中会有“HDC Device”信息。如果没有,hdc无法连接。此时需要插拔设备,或者烧写最新的镜像。 + + 2. hdc\_std工作异常: + + 可以执行"hdc kill"或者"hdc start -r"杀掉hdc服务或者重启hdc服务,然后再执行hdc list targets查看是否已经可以获取设备信息。 + + 3. hdc\_std与设备不匹配: + + 如果设备烧写的是最新镜像,hdc\_std也需要使用最新版本。由于hdc\_std会持续更新,请从开源仓developtools\_hdc\_standard中获取,具体位置在该开源仓的prebuilt目录。 + + + +### hdc\_std运行不了 + +- **现象描述** + + 点击hdc\_std.exe文件无法运行。 + +- **解决方法** + + hdc\_std.exe不需要安装,直接放到磁盘上就能使用,也可以添加到环境变量中。通过打开cmd执行hdc\_std命令直接使用。 + + diff --git a/zh-cn/device-dev/subsystems/subsys-toolchain.md b/zh-cn/device-dev/subsystems/subsys-toolchain.md new file mode 100644 index 0000000000000000000000000000000000000000..fcf4e3ed14c0ce6975b04b70d0e9a0bd9c21f06e --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-toolchain.md @@ -0,0 +1,6 @@ +# 研发工具链 + +- [bytrace使用指导](subsys-toolchain-bytrace-guide.md) +- [hdc\_std 使用指导](subsys-toolchain-hdc-guide.md) + + diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\270\270\350\247\201\351\227\256\351\242\230.md" b/zh-cn/device-dev/subsystems/subsys-utils-faqs.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\270\270\350\247\201\351\227\256\351\242\230.md" rename to zh-cn/device-dev/subsystems/subsys-utils-faqs.md diff --git a/zh-cn/device-dev/subsystems/subsys-utils-guide.md b/zh-cn/device-dev/subsystems/subsys-utils-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..1cabae57341e29c31a2ebf0b47e670e438f27444 --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-utils-guide.md @@ -0,0 +1,298 @@ +# 公共基础库开发指导 + +- [接口说明](#section1633115419401) +- [开发步骤](#section17450172710292) + - [LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤:](#section258354119295) + - [Dump系统属性在LiteOS-M内核平台使用指南:](#section9179161863014) + - [Dump系统属性在LiteOS-A内核平台使用指南:](#section3179121853017) + + +## 接口说明 + +**表 1** 文件操作接口说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

接口名

+

描述

+

int UtilsFileOpen(const char* path, int oflag, int mode)

+

打开或创建文件

+

int UtilsFileClose(int fd)

+

关闭文件

+

int UtilsFileRead(int fd, char *buf, unsigned int len)

+

读取特定长度的文件数据

+

int UtilsFileWrite(int fd, const char *buf, unsigned int len)

+

向文件写入特定大小的数据

+

int UtilsFileDelete(const char *path)

+

删除指定文件

+

int UtilsFileStat(const char *path, unsigned int *fileSize)

+

获取文件大小

+

int UtilsFileSeek(int fd, int offset, unsigned int whence)

+

重新定位文件读/写偏移量

+

int UtilsFileCopy(const char* src, const char* dest)

+

将源文件复制一份并存储到目标文件

+

int UtilsFileMove(const char* src, const char* dest)

+

将源文件移动到指定目标文件

+
+ +文件操作使用示例: + +``` +// open && write +char fileName[] = "testfile"; +static const char def[] = "utils_file_operation implement."; +int fd = UtilsFileOpen(fileName, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0); +printf("file handle = %d\n", fd); +int ret = UtilsFileWrite(fd, def, strlen(def)); +printf("write ret = %d\n", ret); + +// seek +ret = UtilsFileSeek(fd, 5, SEEK_SET_FS); +printf("lseek ret = %d\n", ret); + +// read && close +char buf[64] = {0}; +int readLen = UtilsFileRead(fd, buf, 64); +ret = UtilsFileClose(fd); +printf("read len = %d : buf = %s\n", readLen, buf); + +// stat +int fileLen = 0; +ret = UtilsFileStat(fileName, &fileLen); +printf("file size = %d\n", fileLen); + +// delete +ret = UtilsFileDelete(fileName); +printf("delete ret = %d\n", ret); +``` + +**表 2** KV存储接口说明 + + + + + + + + + + + + + + + + +

接口名

+

描述

+

int UtilsGetValue(const char* key, char* value, unsigned int len)

+

提供给上层应用根据key获取对应数据项

+

int UtilsSetValue(const char* key, const char* value)

+

提供给上层应用用于存储/更新key对应数据项

+

int UtilsDeleteValue(const char* key)

+

提供给上层应用删除key对应数据项

+
+ +KV存储使用示例: + +``` +// set +char key[] = "rw.sys.version_100"; +char value[] = "Hello kv operation implement!"; +int ret = UtilsSetValue(key, value); +printf("UtilsSetValue set ret = %d\n", ret); + +// get +char temp[128] = {0}; +ret = UtilsGetValue(key, temp, 128); +printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); + +// delete +ret = UtilsDeleteValue(key); +printf("UtilsDeleteValue delete ret = %d\n", ret); +``` + + + + +
+ +## 开发步骤 + +### LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤: + +1. 基于AbilityKit开发KV存储的native应用。 + - 基于KV存储提供的接口编写用户程序,并编译出so(libLauncher.so)文件。 + + ``` + // set + char key[] = "rw.sys.version_100"; + char value[] = "Hello kv operation implement!"; + int ret = UtilsSetValue(key, value); + printf("UtilsSetValue set ret = %d\n", ret); + + // get + char temp[128] = {0}; + ret = UtilsGetValue(key, temp, 128); + printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); + + // delete + ret = UtilsDeleteValue(key); + printf("UtilsDeleteValue delete ret = %d\n", ret); + ``` + + - 编写config.json文件,内容如下: + + ``` + { + "app": { + "bundleName": "com.huawei.launcher", + "vendor": "huawei", + "version": { + "code": 1, + "name": "1.0" + } + }, + "deviceConfig": { + "default": { + "reqSdk": { + "compatible": "zsdk 1.0.0", + "target": "zsdk 1.0.1" + }, + "keepAlive": false + }, + "smartCamera": { + "reqSdk": { + "compatible": "zsdk 1.0.0", + "target": "zsdk 1.0.1" + }, + "keepAlive": false + } + }, + "module": { + "package": "com.huawei.launcher", + "name": ".MyHarmonyAbilityPackage", + "deviceType": [ + "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "Launcher", + "moduleType": "entry" + }, + "abilities": [{ + "name": "MainAbility", + "icon": "res/drawable/phone.png", + "label": "test app 1", + "launchType": "standard", + "type": "page" + }, + { + "name": "SecondAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "page" + }, + { + "name": "ServiceAbility", + "icon": "res/drawable/phone.png", + "label": "test app 2", + "launchType": "standard", + "type": "service" + } + ] + } + } + ``` + + + - 生成hap包。 + + - 按照如下目录结构存放文件,res/drawable下面放置资源文件: + + ![](figure/unnaming.png) + + - 将上述文件打包生成zip包,修改后缀为.hap,例如Launcher.hap + + +2. 连接单板,通过串口向单板发送安装KV存储native应用的命令。 + + ``` + ./nfs/dev_tools/bin/bm install -p /nfs/Launcher.hap + ``` + +3. 通过串口向单板发送运行KV存储native应用的命令。 + + ``` + ./nfs/dev_tools/bin/aa start -p com.huawei.launcher -n ServiceAbility + ``` + + +### Dump系统属性在LiteOS-M内核平台使用指南: + +1. 连接单板,通过串口向单板发送AT+SYSPARA命令。 + + ``` + AT+SYSPARA + ``` + + **图 1** LiteOS-M平台dump系统属性输出 + ![](figure/LiteOS-M平台dump系统属性输出.png "LiteOS-M平台dump系统属性输出") + + +### Dump系统属性在LiteOS-A内核平台使用指南: + +1. 连接单板,运行bin路径下的os\_dump加参数--help,查看os\_dump使用指导。 + + ``` + ./bin/os_dump --help + ``` + +2. os\_dump加参数-l,查看当前系统有哪些模块支持获取属性。 + + ``` + ./bin/os_dump -l + ``` + +3. os\_dump加参数syspara,查看当前系统属性 + + ``` + ./bin/os_dump syspara + ``` + + **图 2** LiteOS-A平台dump系统属性输出 + ![](figure/LiteOS-A平台dump系统属性输出.png "LiteOS-A平台dump系统属性输出") + + diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\346\246\202\350\277\260.md" b/zh-cn/device-dev/subsystems/subsys-utils-overview.md old mode 100755 new mode 100644 similarity index 100% rename from "zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\346\246\202\350\277\260.md" rename to zh-cn/device-dev/subsystems/subsys-utils-overview.md diff --git a/zh-cn/device-dev/subsystems/subsys-utils.md b/zh-cn/device-dev/subsystems/subsys-utils.md new file mode 100644 index 0000000000000000000000000000000000000000..28a5d910c2862796d71aba1463dda945b1a5e64f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-utils.md @@ -0,0 +1,9 @@ +# 公共基础 + +- **[公共基础库概述](subsys-utils-overview.md)** + +- **[公共基础库开发指导](subsys-utils-guide.md)** + +- **[公共基础库常见问题](subsys-utils-faqs.md)** + + diff --git a/zh-cn/device-dev/subsystems/subsys-xts-guide.md b/zh-cn/device-dev/subsystems/subsys-xts-guide.md new file mode 100644 index 0000000000000000000000000000000000000000..1240c60b9d64b230d4415ddf74c37477f57b27ed --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys-xts-guide.md @@ -0,0 +1,715 @@ +# XTS认证子系统开发指南 + +- [简介](#section465982318513) +- [系统类型](#section125090457443) +- [目录](#section161941989596) +- [约束](#section119744591305) +- [使用说明](#section137768191623) +- [用例开发指导](#section3695134065513) + - [C语言用例开发编译指导(适用于轻量系统产品用例开发)](#section198193336544) + - [C语言用例执行指导(适用于轻量系统产品用例开发)](#section13820233175418) + - [C++语言用例开发编译指导(适用于小型系统、标准系统用例开发)](#section3822123311540) + - [C++语言用例执行指导(适用于小型系统、标准系统用例开发)](#section128222336544) + - [JS语言用例开发指导(适用于标准系统)](#section159801435165220) + - [JS语言用例编译打包指导(适用于标准系统)](#section445519106559) + - [\#ZH-CN\_TOPIC\_0000001126156429/section191521423950](#section191521423950) + +- [全量编译指导(适用于标准系统)](#section1519992743415) +- [全量用例执行指导(适用于小型系统、标准系统)](#section118149111426) + +## 简介 + +XTS子系统是OpenHarmony生态认证测试套件的集合,当前包括acts(application compatibility test suite)应用兼容性测试套件,后续会拓展dcts(device compatibility test suite)设备兼容性测试套件等。 + +XTS子系统当前包括acts与tools软件包: + +- acts,存放acts相关测试用例源码与配置文件,其目的是帮助终端设备厂商尽早发现软件与OpenHarmony的不兼容性,确保软件在整个开发过程中满足OpenHarmony的兼容性要求。 +- tools,存放acts相关测试用例开发框架。 + +## 系统类型 + +OpenHarmony支持如下几种系统类型: + +- 轻量系统(mini system) + + 面向MCU类处理器例如Arm Cortex-M、RISC-V 32位的设备,硬件资源极其有限,支持的设备最小内存为128KiB,可以提供多种轻量级网络协议,轻量级的图形框架,以及丰富的IOT总线读写部件等。可支撑的产品如智能家居领域的连接类模组、传感器设备、穿戴类设备等。 + +- 小型系统(small system) + + 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为1MiB,可以提供更高的安全能力、标准的图形框架、视频编解码的多媒体能力。可支撑的产品如智能家居领域的IP Camera、电子猫眼、路由器以及智慧出行域的行车记录仪等。 + +- 标准系统(standard system) + + 面向应用处理器例如Arm Cortex-A的设备,支持的设备最小内存为128MiB,可以提供增强的交互能力、3D GPU以及硬件合成能力、更多控件以及动效更丰富的图形能力、完整的应用框架。可支撑的产品如高端的冰箱显示屏。 + + +## 目录 + +``` +/test/xts +├── acts # 测试代码存放目录 +│ └── subsystem # 标准系统子系统测试用例源码存放目录 +│ └── subsystem_lite # 轻量系统、小型系统子系统测试用例源码存放目录 +│ └── BUILD.gn # 标准系统测试用例编译配置 +│ └── build_lite # 轻量系统、小型系统测试用例编译配置存放目录 +│ └── BUILD.gn # 轻量系统、小型系统测试用例编译配置 +└── tools # 测试工具代码存放目录 +``` + +## 约束 + +轻量系统用例开发语言是C,小型系统用例开发语言是C++。 + +## 使用说明 + +**表 1** 用例级别说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

级别名称

+

基本定义

+

测试范围

+

Level0

+

冒烟

+

验证关键功能点基本功能/最基本DFX属性在最常见输入下的表现,通过表示功能基本可运行。

+

Level1

+

基本

+

验证各功能点基本功能/基本DFX属性在常见输入下的表现,通过表示功能基本可测试。

+

Level2

+

重要

+

验证各功能点的基本功能/基本DFX属性在常规输入/常见异常情况下的表现,通过表示功能基本正常可用,可开展Beta。

+

Level3

+

一般

+

验证各功能点的全部功能/全部DFX属性在各种常规/非常规输入组合下,或各种正常/异常预置条件组合下的表现。

+

Level4

+

生僻

+

验证关键功能点在极端异常预置条件下、用户难以触及的异常输入组合下的表现。

+
+ +**表 2** 用例粒度说明 + + + + + + + + + + + + + + + + + + + + +

用例规模

+

被测试对象

+

测试环境

+

LargeTest

+

业务功能/全场景特性/整机及场景级DFX

+

尽量使用贴近真实的环境设备

+

MediumTest

+

模块/子系统集成至设备后的功能/DFX

+

使用真实的单设备进行验证,可进行消息模拟,尽量不对函数进行MOCK

+

SmallTest

+

模块/类/函数

+

在开发者个人环境进行测试,尽量不依赖其他模块,存在大量的MOCK

+
+ +**表 3** 测试类型说明 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

测试类型名称

+

测试类型定义

+

Function

+

验证被测对象提供给用户的业务功能实现正确性的测试项,这里的“用户”可以是终端用户或开发者,功能包括业务功能及平台功能

+

Performance

+

验证被测对象在特定预置条件/负载模型下的处理能力的测试项,“处理能力”一般以单位时间内可处理的业务量来衡量,如呼叫/秒,帧率/秒,事件处理量/秒等

+

Power

+

验证被测对象在特定预置条件/负载模型下在一定时间内能源消耗量的测试项

+

Reliability

+

验证被测对象在正常/异常输入情况下,或业务量压力和长时间连续运行压力情况下业务表现的测试项,含稳定性、压力、故障注入、Monkey测试项

+

Security

+

验证系统对恶意威胁的防护能力,威胁包括但不限于未授权访问、使用、泄露、破坏、修改、毁灭,以保障信息的机密性、完整性和可用性; 验证系统对用户隐私的保护能力,保障用户的隐私数据被收集、使用、保有、披露和处置符合法律规范,保障用户的隐私权; 验证对各类安全规范的遵从情况,如安全设计规范、安全红线、工信部安全认证规范等,保障安全相关法律法规的合规。

+

Global

+

验证被测对象在是否具有国际化数据支持和本地化能力的测试项,包括语言显示、输入/输出习惯、时间显示、区域特性如货币时间禁忌等等

+

Compatibility

+

当被测对象为应用时,包括被测对象对于自身数据的后向兼容性、对于系统的前后向兼容性、对于不同用户数据(如播放器之音频文件格式/智能短信之用户短信内容)的兼容性测试项; 当被测对象为系统时,包括被测系统对于系统自身数据的后向兼容性、以及对于生态中常用应用的兼容性测试项;当被测对象为软件时,包括被测系统对于相关的硬件的兼容性;

+

User

+

验证被测对象在真实用户场景下的用户体验感受的测试项,注意此种情况下没有客观的“正确”与“失败”,所有的结论及评价都应该来自于用户

+

Standard

+

验证被测对象对于行业及公司内标准/协议/规范的遵从情况的测试项,注意此处的“标准”不包含任何安全标准,针对安全标准的测试项划归为“安全测试”类型

+

Safety

+

验证被测对象的Safety属性,避免产品可能对人身安全、健康以及产品本身带来的危害。

+

Resilience

+

验证被测对象的韧性属性,确保系统受攻击时承受并保持在有定义的运行状态(包括降级)、恢复并适应攻击以保障Mission达成。

+
+ +## 用例开发指导 + +根据测试系统选择测试框架和对应测试用例语言。 + +**表 4** 系统和测试框架、开发语言对应关系 + + + + + + + + + + + + + + + + + + + + +

系统

+

测试框架

+

语言

+

轻量系统

+

hctest

+

c

+

小型系统

+

hcpptest

+

c++

+

标准系统

+

HJSUnit、hcpptest

+

js、c++

+
+ +### C语言用例开发编译指导(适用于轻量系统产品用例开发) + +**示例:轻量系统测试用例开发** + +当前使用的测试框架是hctest,hctest测试框架支持使用C语言编写测试用例,是在开源测试框架unity的基础上进行增强和适配。 + +1. 用例目录规范:测试用例存储到test/xts/acts仓中 + + ``` + ├── acts + │ └──subsystem_lite + │ │ └── module_hal + │ │ │ └── BUILD.gn + │ │ │ └── src + │ └──build_lite + │ │ └── BUILD.gn + ``` + +2. src目录下用例编写样例。 + + 1.引用测试框架 + + ``` + #include "hctest.h" + ``` + + 2. 使用宏定义LITE\_TEST\_SUIT定义子系统、模块、测试套件名称 + + ``` + /** + * @brief register a test suit named "IntTestSuite" + * @param test subsystem name + * @param example module name + * @param IntTestSuite test suit name + */ + LITE_TEST_SUIT(test, example, IntTestSuite); + ``` + + 3. 定义Setup与TearDown + + 命名方式:测试套件名称+Setup,测试套件名称+TearDown。 + + Setup与TearDown必须存在,可以为空函数。 + + 4. 使用宏定义LITE\_TEST\_CASE写测试用例 + + 包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + + ``` + LITE_TEST_CASE(IntTestSuite, TestCase001, Function | MediumTest | Level1) + { + //do something + }; + ``` + + 5. 使用宏定义 RUN\_TEST\_SUITE注册测试套件 + + ``` + RUN_TEST_SUITE(IntTestSuite); + ``` + +3. 测试模块的配置文件(BUILD.gn)样例: + + 在每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后静态库的名称、依赖的头文件、依赖的库等;具体写法如下: + + ``` + import("//test/xts/tools/lite/build/suite_lite.gni") + hctest_suite("ActsDemoTest") { + suite_name = "acts" + sources = [ + "src/test_demo.c", + ] + include_dirs = [ ] + cflags = [ "-Wno-error" ] + } + ``` + +4. acts下BUILD.gn增加编译选项。 + + 需要将测试模块加入到acts目录下的编译脚本中,编译脚本路径:test/xts/acts/build\_lite/BUILD.gn。 + + ``` + lite_component("acts") { + ... + if(board_name == "liteos_m") { + features += [ + ... + "//xts/acts/subsystem_lite/module_hal:ActsDemoTest" + ] + } + } + ``` + +5. 测试套件编译命令。 + + 随版本编译,debug版本编译时会同步编译acts测试套件 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >acts测试套件编译中间件为静态库,最终链接到版本镜像中 。 + + +### C语言用例执行指导(适用于轻量系统产品用例开发) + +**示例:轻量系统测试用例执行** + +将版本镜像烧录进开发板。 + +**测试步骤** + +1. 使用串口工具登录开发板,并保存串口打印信息。 +2. 重启设备,查看串口日志。 + +**测试结果分析指导** + +基于串口打印日志进行分析; + +每个测试套件执行以Start to run test suite开始,以xx Tests xx Failures xx Ignored结束。 + +### C++语言用例开发编译指导(适用于小型系统、标准系统用例开发) + +**示例:小型系统测试用例开发**(标准参考具体样例目录:global/i18n\_standard) + +当前使用的测试框架是hcpptest,hcpptest测试框架是在开源的googletest测试框架的基础上进行的增强和适配。 + +1. 规范用例目录:测试用例存储到test/xts/acts仓中。 + + ``` + ├── acts + │ └──subsystem_lite + │ │ └── module_posix + │ │ │ └── BUILD.gn + │ │ │ └── src + │ └──build_lite + │ │ └── BUILD.gn + ``` + +2. 测试模块src下用例编写样例: + + 1. 引用测试框架: + + 需要引用gtest.h 如:\#include "gtest/gtest.h" + + ``` + #include "gtest/gtest.h" + ``` + + 2. 定义Setup与TearDown + + ``` + using namespace std; + using namespace testing::ext; + class TestSuite: public testing::Test { + protected: + // Preset action of the test suite, which is executed before the first test case + static void SetUpTestCase(void){ + } + // Test suite cleanup action, which is executed after the last test case + static void TearDownTestCase(void){ + } + // Preset action of the test case + virtual void SetUp() + { + } + // Cleanup action of the test case + virtual void TearDown() + { + } + }; + ``` + + 3. 使用宏定义HWTEST或HWTEST\_F写测试用例 + + 普通测试用例的定义:HWTEST(测试套名称, 测试用例名称, 用例标注)。 + + 包含SetUp和TearDown的测试用例的定义 :HWTEST\_F(测试套名称, 测试用例名称,用例标注)。 + + 宏定义包括三个参数:测试套件名称,测试用例名称,用例属性(测试类型、用例粒度、用例级别)。 + + ``` + HWTEST_F(TestSuite, TestCase_0001, Function | MediumTest | Level1) { + // do something + } + ``` + +3. 测试模块下用例配置文件(BUILD.gn)样例: + + 每个测试模块目录下新建BUILD.gn编译文件,用于指定编译后可执行文件的名称、依赖的头文件、依赖的库等;具体写法如下。每个测试模块将独立编译成.bin可执行文件, 该文件可直接push到单板上进行测试。 + + 举例: + + ``` + import("//test/xts/tools/lite/build/suite_lite.gni") + hcpptest_suite("ActsDemoTest") { + suite_name = "acts" + sources = [ + "src/TestDemo.cpp" + ] + + include_dirs = [ + "src", + ... + ] + deps = [ + ... + ] + cflags = [ "-Wno-error" ] + } + + ``` + +4. acts目录下增加编译选项(BUILD.gn)样例: + + 将测试模块加入到acts目录下的编译脚本中,编译脚本为:test/xts/acts/build\_lite/BUILD.gn。 + + ``` + lite_component("acts") { + ... + else if(board_name == "liteos_a") { + features += [ + ... + "//xts/acts/subsystem_lite/module_posix:ActsDemoTest" + ] + } + } + ``` + +5. 测试套件编译命令。 + + 随版本编译,debug版本编译时会同步编译acts测试套件 + + >![](../public_sys-resources/icon-note.gif) **说明:** + >小型系统acts独立编译成可执行文件(bin格式), 在编译产物的suites\\acts目录下归档。 + + +### C++语言用例执行指导(适用于小型系统、标准系统用例开发) + +**示例:小型系统测试用例执行** + +目前的用例执行采用nfs共享的方式,mount到单板去执行。 + +**环境搭建** + +1. 使用有限网线或无线将开发板与PC进行连接。 +2. 开发板配置IP、子网掩码、网关,确保开发板与PC处于同一个网段。 +3. PC安装nfs服务器并完成注册,启动nfs服务。 +4. 开发板配置mount命令,确保开发板可以访问PC端的nfs共享文件。 + + 格式:mount \[nfs服务器IP\]:\[/nfs共享目录\] \[/开发板目录\] nfs + + 举例: + + ``` + mount 192.168.1.10:/nfs /nfs nfs + ``` + + +**用例执行** + +测试套件执行 ActsDemoTest.bin 触发用例执行,基于串口打印日志进行分析。 + +### JS语言用例开发指导(适用于标准系统) + +当前使用的测试框架是HJSUnit,用于支撑OpenHarmony application测试(特指基于JS应用框架使用 Javascript 语言开发的 APP)进行自动化测试。 + +**用例编写基础语法** + +测试用例为 js 语言,必须满足 JavaScript 语言编程规范: + +**表 5** + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

用例语法

+

描述

+

要求

+

beforeAll

+

测试套级别的预置条件,在所有测试用例开始前执行且仅执行一次,支持一个参数:预置动作函数

+

可选

+

afterAll

+

测试套级别的清理条件,在所有测试用例结束后执行且仅执行一次,支持一个参数:清理动作函数

+

可选

+

beforeEach

+

测试用例级别的预置条件,在每条测试用例开始前执行,执行次数与 it 定义的测试用例数一致,支持一个参数:预置动作函数

+

可选

+

afterEach

+

测试用例级别的清理条件,在每条测试用例结束后执行,执行次数与 it 定义的测试用例数一致,支持一个参数:清理动作函数

+

可选

+

describe

+

定义一个测试套,支持两个参数:测试套名称和测试套函数; describe 支持嵌套,每个 describe 内均可以定义 beforeAll 、beforeEach 、afterEach 和 afterAll

+

必选

+

it

+

定义一条测试用例,支持三个参数:用例名称,过滤参数和用例函数

+

备注:

+

过滤参数:过滤参数为一个 32 位的 Int 类型参数,0 位 置1表示不筛选、默认执行;0-10 位 置1表示测试用例类型;16-18 位 置1表示测试用例规模;24-28 位 置1表示测试层级

+

测试用例类型。置位0-10分别表示:FUNCTION 方法类测试、PERFORMANCE 性能类测试、POWER 功耗类测试、RELIABILITY 可靠性测试、SECURITY 安全合规测试、GLOBAL 整体性测试、COMPATIBILITY 兼容性测试、USER 用户测试、STANDARD 标准测试、SAFETY 安全特性测试,RESILIENCE 压力测试。

+

测试用例规模。置位16-18分别表示:SMALL 小型测试、MEDIUM 中型测试、LARGE 大型测试。

+

测试层级。置位24-28分别表示:LEVEL0-0 级测试、LEVEL1-1 级测试、LEVEL2-2 级测试、LEVEL3-3 级测试、LEVEL4-4 级测试。

+

必选

+
+ +用例编写语法采用 jasmine 的标准语法,格式支持ES6格式。 + +1. 规范用例目录:测试用例存储到entry/src/main/js/test目录。 + + ``` + ├── BUILD.gn + │ └──entry + │ │ └──src + │ │ │ └──main + │ │ │ │ └──js + │ │ │ │ │ └──default + │ │ │ │ │ │ └──pages + │ │ │ │ │ │ │ └──index + │ │ │ │ │ │ │ │ └──index.js # 入口文件 + │ │ │ │ │ └──test # 测试代码存放目录 + │ │ │ └── resources # hap资源存放目录 + │ │ │ └── config.json # hap配置文件 + ``` + +2. index.js示例 + + ``` + // 拉起js测试框架,加载测试用例 + import {Core, ExpectExtend} from 'deccjsunit/index' + + export default { + data: { + title: "" + }, + onInit() { + this.title = this.$t('strings.world'); + }, + onShow() { + console.info('onShow finish') + const core = Core.getInstance() + const expectExtend = new ExpectExtend({ + 'id': 'extend' + }) + core.addService('expect', expectExtend) + core.init() + const configService = core.getDefaultService('config') + configService.setConfig(this) + require('../../../test/List.test') + core.execute() + }, + onReady() { + }, + } + ``` + +3. 单元测试用例示例 + + ``` + // Example1: 使用HJSUnit进行单元测试 + describe('appInfoTest', function () { + it('app_info_test_001', 0, function () { + var info = app.getInfo() + expect(info.versionName).assertEqual('1.0') + expect(info.versionCode).assertEqual('3') + }) + }) + ``` + + +### JS语言用例编译打包指导(适用于标准系统) + +hap包编译请参考[标准系统js应用开发指导](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/build_overview-0000001055075201)。 + +## 全量编译指导(适用于标准系统) + +1. 全量编译 + + **命令**: + + ``` + ./build.sh suite=acts system_size=standard + ``` + + **测试用例输出目录**:out/release/suites/acts/testcases + + **测试框架&用例整体输出目录:**out/release/suites/acts(编译用例时会同步编译测试套执行框架) + + +## 全量用例执行指导(适用于小型系统、标准系统) + +**搭建测试环境** + +Windows工作台下安装python3.7及以上版本,确保工作台和测试设备正常连接。 + +**测试执行目录**(对应编译生成的out/release/suites/acts目录) + +``` +├── testcase # 测试套文件存放目录 +│ └──xxx.hap # 测试套可执行hap文件 +│ └──xxx.json # 测试套对应执行配置文件 +├── tools # 测试框架工具目录 +├── run.bat # window平台测试套启动执行文件 +├── report # 测试报告生成目录 +``` + +**用例执行** + +1. 在Windows工作台上,找到从Linux服务器上拷贝下来的测试套件用例目录\(对应编译生成的out/release/suites/acts目录\),在Windows命令窗口进入对应目录,直接执行acts\\run.bat。 + +1. 界面启动后,输入用例执行指令。 + + - 全量执行 + + ``` + run acts + ``` + + ![](figure/zh-cn_image_0000001119924146.gif) + + + - 模块执行\(具体模块可以查看\\acts\\testcases\\\) + + ``` + run –l ActsSamgrTest + ``` + + ![](figure/zh-cn_image_0000001166643927.jpg) + + + 等待执行完成。 + + +1. 查看测试报告。 + + 进入acts\\reports\\,获取当前的执行记录,打开“summary\_report.html”可以获取到测试报告。 + + diff --git a/zh-cn/device-dev/subsystems/subsys.md b/zh-cn/device-dev/subsystems/subsys.md new file mode 100644 index 0000000000000000000000000000000000000000..d4d48224367765f4f4ff66568e3e7d0c9df1d72f --- /dev/null +++ b/zh-cn/device-dev/subsystems/subsys.md @@ -0,0 +1,33 @@ +# 子系统开发指南 + +- **[编译构建](subsys-build.md)** + +- **[分布式远程启动](subsys-remote-start.md)** + +- **[图形图像](subsys-graphics.md)** + +- **[媒体](subsys-multimedia.md)** + +- **[公共基础](subsys-utils.md)** + +- **[AI框架](subsys-aiframework.md)** + +- **[Sensor服务](subsys-densor.md)** + +- **[用户程序框架](subsys-application-framework.md)** + +- **[OTA升级](subsys-ota-guide.md)** + +- **[安全](subsys-security.md)** + +- **[启动恢复](subsys-boot.md)** + +- **[测试](subsys-testguide-test.md)** + +- **[DFX](subsys-dfx.md)** + +- **[HiSysEvent订阅指导](subsys-dfx-hisyseventread.md)** + +- **[XTS认证子系统开发指南](subsys-xts-guide.md)** + + diff --git "a/zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" "b/zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" deleted file mode 100755 index 25dde0bbc86164b4d7a0e2bec0e5b06b87d175dd..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\344\273\243\347\240\201\347\256\241\347\220\206\350\247\204\350\214\203.md" +++ /dev/null @@ -1,40 +0,0 @@ -# 代码管理规范 - -- [建议:插件与北向SDK在AI引擎指定的路径下进行代码开发](#section17176374131) -- [规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录](#section2551029111312) -- [规则:插件编译输出路径必须是在/usr/lib](#section97021558121310) - -AI引擎框架包含client、server和common三个主要模块,其中client提供server端连接管理功能,北向SDK在算法对外接口中需封装调用client提供的公共接口;server提供插件加载以及任务管理等功能,各Plugin实现由server提供的插件接口,完成插件接入;common提供与平台相关的操作方法、引擎协议以及相关工具类,供其他各模块调用。 - -AI引擎框架各模块之间的代码依赖关系如下[图1](#fig171811112818)所示: - -**图 1** ****AI引擎代码依赖关系 - - -![](figures/插件依赖-(2).jpg) - -## 建议:插件与北向SDK在AI引擎指定的路径下进行代码开发 - -在AI引擎框架的整体规划中,北向SDK属于client端的一部分,插件由server端调用,属于server端的一部分,因此AI引擎框架为接入的插件与北向SDK规划的路径: - -- SDK代码路径://foundation/ai/engine/services/client/algorithm\_sdk - - e.g. //foundation/ai/engine/services/client/algorithm\_sdk/cv - - e.g. //foundation/ai/engine/services/client/algorithm\_sdk/nlu - -- 插件代码路径://foundation/ai/engine/services/server/plugin - - e.g. //foundation/ai/engine/services/server/plugin/cv - - e.g. //foundation/ai/engine/services/server/plugin/nlu - - -## 规则:插件提供的全部对外接口,统一存放在AI业务子系统interfaces/kits目录 - -北向SDK对外接口是AI业务子系统提供能力的对外暴露方式,按照OpenHarmony的接口管理要求,需统一存放在各子系统的interfaces/kits目录中。当前AI业务子系统插件对外接口路径为//foundation/ai/engine/interfaces/kits,不同插件可在该路径下添加目录,比如增加cv插件,则在路径//foundation/ai/engine/interfaces/kits/cv下面存放接口文件。 - -## 规则:插件编译输出路径必须是在/usr/lib - -server端加载插件是采用dlopen方式,只支持在/usr/lib路径进行,因此插件在编译so时,需要在编译配置文件中指定输出路径为/usr/lib。 - diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" "b/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" deleted file mode 100755 index 5a9dc698745f0ec1dc3c6dc9fa361f75740a940d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 公共基础 - -- **[公共基础库概述](公共基础库概述.md)** - -- **[公共基础库开发指导](公共基础库开发指导.md)** - -- **[公共基础库常见问题](公共基础库常见问题.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 38a64bb9ebb5b0e5fc669019b436fd68d03c4fce..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\205\254\345\205\261\345\237\272\347\241\200\345\272\223\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,298 +0,0 @@ -# 公共基础库开发指导 - -- [接口说明](#section1633115419401) -- [开发步骤](#section17450172710292) - - [LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤:](#section258354119295) - - [Dump系统属性在LiteOS-M内核平台使用指南:](#section9179161863014) - - [Dump系统属性在LiteOS-A内核平台使用指南:](#section3179121853017) - - -## 接口说明 - -**表 1** 文件操作接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int UtilsFileOpen(const char* path, int oflag, int mode)

-

打开或创建文件

-

int UtilsFileClose(int fd)

-

关闭文件

-

int UtilsFileRead(int fd, char *buf, unsigned int len)

-

读取特定长度的文件数据

-

int UtilsFileWrite(int fd, const char *buf, unsigned int len)

-

向文件写入特定大小的数据

-

int UtilsFileDelete(const char *path)

-

删除指定文件

-

int UtilsFileStat(const char *path, unsigned int *fileSize)

-

获取文件大小

-

int UtilsFileSeek(int fd, int offset, unsigned int whence)

-

重新定位文件读/写偏移量

-

int UtilsFileCopy(const char* src, const char* dest)

-

将源文件复制一份并存储到目标文件

-

int UtilsFileMove(const char* src, const char* dest)

-

将源文件移动到指定目标文件

-
- -文件操作使用示例: - -``` -// open && write -char fileName[] = "testfile"; -static const char def[] = "utils_file_operation implement."; -int fd = UtilsFileOpen(fileName, O_RDWR_FS | O_CREAT_FS | O_TRUNC_FS, 0); -printf("file handle = %d\n", fd); -int ret = UtilsFileWrite(fd, def, strlen(def)); -printf("write ret = %d\n", ret); - -// seek -ret = UtilsFileSeek(fd, 5, SEEK_SET_FS); -printf("lseek ret = %d\n", ret); - -// read && close -char buf[64] = {0}; -int readLen = UtilsFileRead(fd, buf, 64); -ret = UtilsFileClose(fd); -printf("read len = %d : buf = %s\n", readLen, buf); - -// stat -int fileLen = 0; -ret = UtilsFileStat(fileName, &fileLen); -printf("file size = %d\n", fileLen); - -// delete -ret = UtilsFileDelete(fileName); -printf("delete ret = %d\n", ret); -``` - -**表 2** KV存储接口说明 - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int UtilsGetValue(const char* key, char* value, unsigned int len)

-

提供给上层应用根据key获取对应数据项

-

int UtilsSetValue(const char* key, const char* value)

-

提供给上层应用用于存储/更新key对应数据项

-

int UtilsDeleteValue(const char* key)

-

提供给上层应用删除key对应数据项

-
- -KV存储使用示例: - -``` -// set -char key[] = "rw.sys.version_100"; -char value[] = "Hello kv operation implement!"; -int ret = UtilsSetValue(key, value); -printf("UtilsSetValue set ret = %d\n", ret); - -// get -char temp[128] = {0}; -ret = UtilsGetValue(key, temp, 128); -printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); - -// delete -ret = UtilsDeleteValue(key); -printf("UtilsDeleteValue delete ret = %d\n", ret); -``` - - - - -
- -## 开发步骤 - -### LiteOS-A内核\(Hi3516、Hi3518平台\)KV存储的native应用开发步骤: - -1. 基于AbilityKit开发KV存储的native应用。 - - 基于KV存储提供的接口编写用户程序,并编译出so(libLauncher.so)文件。 - - ``` - // set - char key[] = "rw.sys.version_100"; - char value[] = "Hello kv operation implement!"; - int ret = UtilsSetValue(key, value); - printf("UtilsSetValue set ret = %d\n", ret); - - // get - char temp[128] = {0}; - ret = UtilsGetValue(key, temp, 128); - printf("UtilsGetValue get ret = %d, temp = %s\n", ret, temp); - - // delete - ret = UtilsDeleteValue(key); - printf("UtilsDeleteValue delete ret = %d\n", ret); - ``` - - - 编写config.json文件,内容如下: - - ``` - { - "app": { - "bundleName": "com.huawei.launcher", - "vendor": "huawei", - "version": { - "code": 1, - "name": "1.0" - } - }, - "deviceConfig": { - "default": { - "reqSdk": { - "compatible": "zsdk 1.0.0", - "target": "zsdk 1.0.1" - }, - "keepAlive": false - }, - "smartCamera": { - "reqSdk": { - "compatible": "zsdk 1.0.0", - "target": "zsdk 1.0.1" - }, - "keepAlive": false - } - }, - "module": { - "package": "com.huawei.launcher", - "name": ".MyHarmonyAbilityPackage", - "deviceType": [ - "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera" - ], - "distro": { - "deliveryWithInstall": true, - "moduleName": "Launcher", - "moduleType": "entry" - }, - "abilities": [{ - "name": "MainAbility", - "icon": "res/drawable/phone.png", - "label": "test app 1", - "launchType": "standard", - "type": "page" - }, - { - "name": "SecondAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "page" - }, - { - "name": "ServiceAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "service" - } - ] - } - } - ``` - - - - 生成hap包。 - - - 按照如下目录结构存放文件,res/drawable下面放置资源文件: - - ![](figures/unnaming.png) - - - 将上述文件打包生成zip包,修改后缀为.hap,例如Launcher.hap - - -2. 连接单板,通过串口向单板发送安装KV存储native应用的命令。 - - ``` - ./nfs/dev_tools/bin/bm install -p /nfs/Launcher.hap - ``` - -3. 通过串口向单板发送运行KV存储native应用的命令。 - - ``` - ./nfs/dev_tools/bin/aa start -p com.huawei.launcher -n ServiceAbility - ``` - - -### Dump系统属性在LiteOS-M内核平台使用指南: - -1. 连接单板,通过串口向单板发送AT+SYSPARA命令。 - - ``` - AT+SYSPARA - ``` - - **图 1** LiteOS-M平台dump系统属性输出 - ![](figures/LiteOS-M平台dump系统属性输出.png "LiteOS-M平台dump系统属性输出") - - -### Dump系统属性在LiteOS-A内核平台使用指南: - -1. 连接单板,运行bin路径下的os\_dump加参数--help,查看os\_dump使用指导。 - - ``` - ./bin/os_dump --help - ``` - -2. os\_dump加参数-l,查看当前系统有哪些模块支持获取属性。 - - ``` - ./bin/os_dump -l - ``` - -3. os\_dump加参数syspara,查看当前系统属性 - - ``` - ./bin/os_dump syspara - ``` - - **图 2** LiteOS-A平台dump系统属性输出 - ![](figures/LiteOS-A平台dump系统属性输出.png "LiteOS-A平台dump系统属性输出") - - diff --git "a/zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index e58aed68c06c7bda4fa8491a80f6ff68f0b720ce..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\212\250\347\224\273\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,190 +0,0 @@ -# 动画开发指导 - -- [使用场景](#section726685714018) -- [接口说明](#section85794718418) -- [开发步骤](#section14101161317435) - -## 使用场景 - -UI动画通过task处理机制每个tick调用一下用户设置的callback函数来实现,具体实现为AnimatorManager、Animator、AnimatorCallback三个类实现。 - -- AnimatorManager:AnimatorManager为单例,在Init函数执行时将自己注册到系统task回调函数中,系统task机制保证每个tick会调用一下AnimatorManager的callback函数,同时AnimatorManager用来管理Animator实例。 -- Animator:Animator中可以设置动画相关的属性,包括动画的起止时间,动画开始和停止,动画状态的设置和获取等。 -- AnimatorCallback:具体每一个tick动画所要做的内容在AnimatorCallback类中实现,开发者需要自己实现Callback方法,动画执行时在Callback实现相应功能。 - -## 接口说明 - -**表 1** 动画接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

子模块

-

方法

-

功能

-

Animator

-

void Start ()

-

动画开始

-

Animator

-

void Stop ()

-

动画停止

-

Animator

-

void Pause ()

-

动画暂停

-

Animator

-

void Resume ()

-

动画恢复

-

Animator

-

uint8_t GetState () const

-

获取动画当前状态

-

Animator

-

void SetState (uint8_t state)

-

设置动画当前状态

-

Animator

-

uint32_t GetTime () const

-

获取动画总持续时间

-

Animator

-

void SetTime (uint32_t time)

-

设置动画总持续时间

-

Animator

-

uint32_t GetRunTime () const

-

获取动画当前已经持续的时间

-

Animator

-

void SetRunTime (uint32_t runTime)

-

设置动画当前已经持续的时间

-

Animator

-

bool IsRepeat () const

-

获取动画是否循环播放

-

AnimatorCallback

-

virtual void Callback (UIView *view)=0

-

由用户实现,动画回调函数

-

AnimatorCallback

-

virtual void OnStop(UIView& view) {}

-

由用户实现,动画停止后的回调函数

-

AnimatorManager

-

static AnimatorManager* GetInstance()

-

获取AnimatorManager实例

-

AnimatorManager

-

void Add (Animator *animator)

-

添加动画

-

AnimatorManager

-

void Remove(const Animator* animator);

-

删除动画

-
- -## 开发步骤 - -1. 实现AnimatorCallback的回调函数。 - - ``` - class AnimatorCallbackDemo : public OHOS::AnimatorCallback { - public: - AnimatorCallbackDemo(int16_t startPos, int16_t endPos, uint16_t time) - : start_(startPos), end_(endPos), time_(time), curTime_(0) {} - - virtual void Callback(OHOS::UIView* view) - { - curTime_++; - int16_t pos = EasingEquation::CubicEaseIn(start_, end_, curTime_, time_); - view->Invalidate(); - view->SetPosition(pos, view->GetY()); - view->Invalidate(); - } - protected: - int16_t start_; - int16_t end_; - uint16_t time_; - uint16_t curTime_; - }; - ``` - -2. 将AnimatorCallback添加到Animator中。 - - ``` - UIImageView* image = new UIImageView(); - image->SetSrc("..\\config\\images\\A021_001.bin"); - image->SetPosition(0, 50); - AnimatorCallbackDemo* callback = new AnimatorCallbackDemo(0, 338, 60); - Animator* animator = new Animator(callback, image, 0, true); - ``` - -3. 将Animator添加到AnimatorManager中。 - - ``` - AnimatorManager::GetInstance()->Add(animator); - ``` - -4. 点击下图下方的按钮,检查对应的动画运行效果。 - - **图 1** 动画实现效果图 - ![](figures/动画实现效果图.gif "动画实现效果图") - - diff --git "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" "b/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" deleted file mode 100755 index 0514d4bd500c9a0de7dd78af98f690b09fd16cc1..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215.md" +++ /dev/null @@ -1,17 +0,0 @@ -# 启动恢复 - -- **[启动恢复子系统概述](启动恢复子系统概述.md)** - -- **[init启动引导组件](init启动引导组件.md)** - -- **[appspawn应用孵化组件](appspawn应用孵化组件.md)** - -- **[bootstrap服务启动组件](bootstrap服务启动组件.md)** - -- **[syspara系统属性组件](syspara系统属性组件.md)** - -- **[常见问题](常见问题.md)** - -- **[参考](参考.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" deleted file mode 100755 index 1287b4212dbaf8470686796086bdcd06c0faa20b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\220\257\345\212\250\346\201\242\345\244\215\345\255\220\347\263\273\347\273\237\346\246\202\350\277\260.md" +++ /dev/null @@ -1,66 +0,0 @@ -# 启动恢复子系统概述 - -- [约束与限制](#section2029921310472) - -启动恢复子系统负责从内核启动之后到应用启动之前的系统关键服务进程的启动过程以及设备恢复出厂设置的功能。涉及以下组件: - -- init启动引导组件 - - init启动引导组件对应的进程为init进程,是内核完成初始化后启动的第一个用户态进程。init进程启动之后,读取init.cfg配置文件,根据解析结果,执行相应命令(见[第2章表2](init启动引导组件.md#table122681439144112)描述)并依次启动各关键系统服务进程,在启动系统服务进程的同时设置其对应权限。 - -- appspawn应用孵化组件 - - 负责接收**用户程序框架**的命令孵化应用进程,设置新进程的权限,并调用应用程序框架的入口函数。 - -- bootstrap服务启动组件 - - 提供了各服务和功能的启动入口标识。在SAMGR启动时,会调用boostrap标识的入口函数,并启动系统服务。 - -- syspara系统属性组件 - - 系统属性组件,根据OpenHarmony产品兼容性规范提供获取设备信息的接口,如:产品名、品牌名、厂家名等,同时提供设置/读取系统属性的接口。 - - -## 约束与限制 - -启动恢复子系统源代码目录和适配平台: - -**表 1** 启动恢复子系统源代码目录和适配平台 - - - - - - - - - - - - - - - - - - - -

名称

-

适配平台

-

base/startup/appspawn_lite

-

小型系统设备(参考内存≥1MB),如Hi3516DV300 、Hi3518EV300

-

base/startup/bootstrap_lite

-

轻量系统设备(参考内存≥128KB),如Hi3861V100

-

base/startup/init_lite

-

小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300

-

base/startup/syspara_lite

-
  • 轻量系统设备(参考内存≥128KB),如Hi3861V100
  • 小型系统设备(参考内存≥1MB),如Hi3516DV300、Hi3518EV300
-
- -- init启动引导组件: - - 配置文件init.cfg烧写到单板之后变成只读模式,修改时必须重新打包和烧写rootfs镜像。 - - 配置文件init.cfg仅支持json格式。 - -- bootstrap服务启动组件:需要在链接脚本中配置zInit代码段。 -- syspara系统属性组件:SetParameter/GetParameter仅支持uid大于1000的应用调用。 - diff --git "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index c8f592b80cfa7aa2254c26bfbe1fcda8a14da699..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\224\244\351\206\222\350\257\215\350\257\206\345\210\253SDK\347\232\204\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,81 +0,0 @@ -# 唤醒词识别SDK的开发示例 - -1. 在//foundation/ai/engine /interfaces/kits目录中添加唤醒词识别SDK的API接口定义,该接口可用三方应用的调用。如下代码片段即为唤醒词识别定义的API接口示例,其相关代码参考路径为://foundation/ai/engine /interfaces/kits/asr/keyword\_spotting。 - - ``` - class KWSSdk { - public: - KWSSdk(); - virtual ~KWSSdk(); - - // 定义了创建唤醒词检测工具包的方法 - int32_t Create(); - - // 定义了同步执行唤醒词检测任务的方法 - int32_t SyncExecute(const Array &audioInput); - - // 定义了设置唤醒词检测回调器的方法 - int32_t SetCallback(const std::shared_ptr &callback); - - // 定义了销毁唤醒词工具包的方法,释放与插件的会话信息。 - int32_t Destroy(); - }; - ``` - -2. 在//foundation/ai/engine/services/client/algorithm\_sdk的目录中增加SDK中API接口的具体实现,调用client端提供的接口,实现算法插件能力的使用。如下代码片段即为唤醒词识别的API接口中create方法的具体实现示例,更多详细代码可参考://foundation/ai/engine/services/client/algorithm\_sdk/asr/keyword\_spotting。 - - ``` - int32_t KWSSdk::KWSSdkImpl::Create() - { - if (kwsHandle_ != INVALID_KWS_HANDLE) { - HILOGE("[KWSSdkImpl]The SDK has been created"); - return KWS_RETCODE_FAILURE; - } - if (InitComponents() != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]Fail to init sdk components"); - return KWS_RETCODE_FAILURE; - } - // 调用client端提供的接口AieClientInit,实现初始化引擎服务,激活跨进程调用 - int32_t retCode = AieClientInit(configInfo_, clientInfo_, algorithmInfo_, nullptr); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]AieClientInit failed. Error code[%d]", retCode); - return KWS_RETCODE_FAILURE; - } - if (clientInfo_.clientId == INVALID_CLIENT_ID) { - HILOGE("[KWSSdkImpl]Fail to allocate client id"); - return KWS_RETCODE_FAILURE; - } - DataInfo inputInfo = { - .data = nullptr, - .length = 0, - }; - DataInfo outputInfo = { - .data = nullptr, - .length = 0, - }; - // 调用client端提供的接口AieClientPrepare,实现加载算法插件 - retCode = AieClientPrepare(clientInfo_, algorithmInfo_, inputInfo, outputInfo, nullptr); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]AieclientPrepare failed. Error code[%d]", retCode); - return KWS_RETCODE_FAILURE; - } - if (outputInfo.data == nullptr || outputInfo.length <= 0) { - HILOGE("[KWSSdkImpl]The data or length of output info is invalid"); - return KWS_RETCODE_FAILURE; - } - MallocPointerGuard pointerGuard(outputInfo.data); - retCode = PluginHelper::UnSerializeHandle(outputInfo, kwsHandle_); - if (retCode != RETCODE_SUCCESS) { - HILOGE("[KWSSdkImpl]Get handle from inputInfo failed"); - return KWS_RETCODE_FAILURE; - } - return KWS_RETCODE_SUCCESS; - } - ``` - - 上述代码为API接口的具体实现,从上述示例的代码中,SDK中create接口的具体实现即为下述示例代码中create方法,该方法调用了AI引擎框架client端开放接口AieClientInit,AieClientPrepare,从而实现与server端建立连接及加载算法模型的能力。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >SDK调用AI引擎client端接口顺序应遵循AieClientInit-\>AieClientPrepare-\>AieClientSyncProcess/AieClientAsyncProcess-\>AieClientRelease-\>AieClientDestroy,否则调用接口会返回错误码。 - - diff --git "a/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" "b/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" deleted file mode 100755 index 08422282d6c645d6451f0f930689f79fc73c4ad9..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\233\276\345\275\242\345\233\276\345\203\217.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 图形图像 - -- **[图形图像概述](图形图像概述.md)** - -- **[容器类组件开发指导](容器类组件开发指导.md)** - -- **[布局容器类组件开发指导](布局容器类组件开发指导.md)** - -- **[普通组件开发指导](普通组件开发指导.md)** - -- **[动画开发指导](动画开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" "b/zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" deleted file mode 100755 index c76c3a1f71afffffd608dd2db0ed33072b8bff54..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\252\222\344\275\223.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 媒体 - -- **[相机](相机.md)** - -- **[音视频](音视频.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" "b/zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" deleted file mode 100755 index 88ce479aa01d95df97297fd45bd3ac17d0d16ff1..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\256\211\345\205\250.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 安全 - -- **[概述](概述-7.md)** - -- **[应用验签开发指导](应用验签开发指导.md)** - -- **[应用权限管理开发指导](应用权限管理开发指导.md)** - -- **[IPC通信鉴权开发指导](IPC通信鉴权开发指导.md)** - -- **[可信设备群组管理开发指导](可信设备群组管理开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 507ad3b1186829744ad660c5cd49f52eee5b9415..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,244 +0,0 @@ -# 容器类组件开发指导 - -- [UIViewGroup](#section145471898812) -- [使用场景](#section0916112362216) -- [接口说明](#section12641756192212) -- [开发步骤](#section5412161692311) -- [UIScrollView](#section174961523161315) -- [使用场景](#section8937101902413) -- [接口说明](#section14789133142420) -- [开发步骤](#section1769754422417) - -容器类组件,指能包含其它UI组件的组件,容器类组件继承于UIViewGroup(带Add方法),基于实际组件的使用场景,将需要增加其他子组件的组件,放置到容器类继承结构下。如UIAnalogClock内,通常会Add需要的计步信息,时分秒图标等。 - -**图 1** 普通容器类组件结构 -![](figures/普通容器类组件结构.png "普通容器类组件结构") - -RootView、UIAbstractScroll、UIPicker组件从UIViewGroup继承,UIList、UIScrollView、UISwipeView组件从UIAbstractScroll继承。 - -## UIViewGroup - -## 使用场景 - -UIViewGroup是容器类组件基类,实现增加、删除、插入等操作,通过增加方法可以添加子组件。普通容器类组件子组件需要设置位置信息,位置信息为相对父组件的相对坐标。组件树结构如下图: - -**图 2** 组件树结构示意图 -![](figures/组件树结构示意图.png "组件树结构示意图") - -往根节点rootView里添加ViewGroup1容器组件和View1组件,往ViewGroup1容器组件里再添加View2组件和ViewGroup2容器组件,在View1之后添加View3组件。 - -- 关于渲染:容器类组件在渲染时会遍历所有子组件OnDraw方法,以达到刷新所有组件的目的。 -- 关于坐标:子组件位置信息为相对父组件的相对坐标,系统在渲染时计算绝对坐标并显示。 -- 关于树结构遍历:UIViewGroup提供如下方法实现遍历、查找、管理组件树。 - -## 接口说明 - -**表 1** ViewGroup接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

virtual void Add(UIView* view)

-

添加子组件

-

virtual void Insert(UIView* prevView, UIView* insertView)

-

插入子组件

-

virtual void Remove(UIView* view)

-

删除子组件

-

virtual void RemoveAll()

-

删除所有子组件

-

virtual void GetTargetView(const Point& point, UIView** last)

-

获取目标视图

-

virtual void MoveChildByOffset(int16_t x, int16_t y)

-

偏移子组件

-

UIView* GetChildrenHead() const

-

获取视图头节点

-

UIView* GetChildrenTail() const

-

获取视图最后那个节点

-

virtual UIView* GetChildById(const char* id) const override

-

通过id获取子视图

-
- -## 开发步骤 - -1. 构造button实例并设置坐标信息。 - - ``` - UILabelButton* btn1 = new UILabelButton(); - btn1->SetPosition(0, 0, 100, 50); - btn1->SetText("btn1"); - - UILabelButton* btn2 = new UILabelButton(); - btn2->SetPosition(50, 50, 100, 50); - btn2->SetText("btn2"); - - UILabelButton* btn3 = new UILabelButton(); - btn3->SetPosition(100, 100, 100, 50); - btn3->SetText("btn3"); - ``` - -2. 构造UIViewGroup实例,并设置坐标信息。 - - ``` - UIViewGroup* group = new UIViewGroup(); - group->SetPosition(0, 0, 300, 300); - ``` - -3. 使用Add方法添加Button实例到UIViewGroup。 - - ``` - group->Add(btn1); - group->Add(btn2); - group->Add(btn3); - ``` - -4. 检查ViewGroup效果如下图所示。 - - **图 3** ViewGroup添加view实例效果图 - ![](figures/ViewGroup添加view实例效果图.png "ViewGroup添加view实例效果图") - - -## UIScrollView - -## 使用场景 - -UIScrollView提供可滑动的容器类组件,子组件可在触摸事件驱动下上下、左右滑动,并提供水平和垂直方向的游标显示功能。 - -## 接口说明 - -**表 2** ScrollView接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void ScrollBy(int16_t xDistance, int16_t yDistance)

-

移动视图

-

void SetScrollbarWidth(uint8_t width)

-

设置滑动条宽度

-

void SetHorizontalScrollState(bool state)

-

设置水平滑动状态

-

bool GetHorizontalScrollState() const

-

获取水平是否可滑动状态

-

void SetVerticalScrollState(bool state)

-

设置垂直滑动状态

-

bool GetVerticalScrollState() const

-

获取垂直是否可滑动状态

-

void SetXScrollBarVisible(bool state)

-

设置X轴滑动条是否可见

-

void SetYScrollBarVisible(bool state)

-

设置Y轴滑动条是否可见

-

void RegisterScrollListener(OnScrollListener* scrollListener)

-

注册滑动事件回调类

-

void RefreshScrollBar()

-

刷新滑动条

-

virtual void OnScrollStart() {}

-

滚动开始回调函数

-

virtual void OnScrollEnd() {}

-

滚动结束回调函数

-

uint8_t GetScrollState() const

-

获取滚动状态

-

void SetScrollState(uint8_t state)

-

设置滚动状态

-
- -## 开发步骤 - -添加两个button子组件,并显示水平、垂直方向游标。 - -``` -scrollView* scroll = new UIScrollView(); -scroll->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full); -scroll->SetPosition(0,0, 200, 200); -scroll->SetXScrollBarVisible(true); -scroll->SetYScrollBarVisible(true); -UILabelButton* button1 = new UILabelButton(); -button1->SetText("button1"); -button1->SetPosition(0, 0, 300, 300); -UILabelButton* button2 = new UILabelButton(); -button2->SetText("button2"); -button2->SetPosition(0, 300, 300, 300); -scroll->Add(button1); -scroll->Add(button2); -``` - -**图 4** 水平、垂直方向可滑动效果图 -![](figures/水平-垂直方向可滑动效果图.gif "水平-垂直方向可滑动效果图") - diff --git "a/zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 4f8653aad5a60dd337d7ff873ee22d005474cad3..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\270\203\345\261\200\345\256\271\345\231\250\347\261\273\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,216 +0,0 @@ -# 布局容器类组件开发指导 - -- [UISwipeView](#section13631719181717) -- [使用场景](#section11299120102617) -- [接口说明](#section767434119261) -- [开发步骤(水平滑动,不可循环)](#section111911175287) -- [开发步骤(水平滑动,可循环)](#section1976914915282) -- [GridLayout](#section46819199173) -- [使用场景](#section831618247294) -- [接口说明](#section597214622912) -- [开发步骤](#section1418253410306) - -布局类容器组件由视图基础类组成,通过直接设置视图位置,可以达到嵌套和重叠布局的目的;通过设置布局类型和边距达到规格化布局子组件的目的;通过调用相关接口可实现根据父组件及兄弟节点布局视图的目的。 - -## UISwipeView - -## 使用场景 - -UISwipeView继承UIViewGroup,除提供容器类组件Add、Remove、Insert等方法外还提供按页面滑动功能,滑动结束后当前页面居中对齐显示。该组件分为水平方向和垂直方向,通过Add方法添加的子组件会根据Add的顺序和UISwipeView方向自动水平对齐或则垂直对齐。 - -## 接口说明 - -**表 1** SwipeView接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetCurrentPage(uint16_t index);

-

设置当前页

-

uint16_t GetCurrentPage()

-

获取当前页

-

UIView* GetCurrentView() const

-

获取当前页组件

-

void SetOnSwipeListener(OnSwipeListener& onSwipeListener)

-

设置滑动回调类

-

void SetAnimatorTime(uint16_t time);

-

设置动画事件

-

void SetLoopState(bool loop)

-

设置是否循环

-

UIView* GetViewByIndex(uint16_t index);

-

通过index获取view

-
- -## 开发步骤(水平滑动,不可循环) - -1. 创建一个水平滑动的UISwipeView。 - - ``` - UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); - ``` - -2. 向UISwipeView中添加子组件。 - - ``` - UILabelButton* button1 = new UILabelButton(); - button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button1->SetText("button1"); - swipe->Add(button1); - UILabelButton* button2 = new UILabelButton(); - button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button2->SetText("button2"); - swipe->Add(button2); - UILabelButton* button3 = new UILabelButton(); - button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button3->SetText("button3"); - swipe->Add(button3); - ``` - -3. 检查实现效果,水平滑动,不可循环。 - - **图 1** UISwipeView水平滑动效果图 - - - ![](figures/zh-cn_image_0000001053247975.gif) - - -## 开发步骤(水平滑动,可循环) - -1. 创建一个水平滑动的UISwipeView并添加子组件。 - - ``` - UISwipeView* swipe = new UISwipeView(UISwipeView::HORIZONTAL); - UILabelButton* button1 = new UILabelButton(); - button1->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button1->SetText("button1"); - swipe->Add(button1); - UILabelButton* button2 = new UILabelButton(); - button2->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button2->SetText("button2"); - swipe->Add(button2); - UILabelButton* button3 = new UILabelButton(); - button3->SetPosition(0, 0, g_ButtonW, g_ButtonH); - button3->SetText("button3"); - swipe->Add(button3); - ``` - -2. 设置UISwipeView循环滑动。 - - ``` - swipe->SetLoopState(true); - ``` - -3. 检查实现效果,水平循环滑动。 - - **图 2** UISwipeView水平滑动循环效果图 - - - ![](figures/zh-cn_image_0000001053207924.gif) - - -## GridLayout - -## 使用场景 - -提供基础布局能力,可设置网格行数和列数,通过Add方法添加的子组件在调用LayoutChildren\(\)方法后自动进行排列布局。 - -## 接口说明 - -**表 2** GridLayout接口说明 - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetRows(const uint16_t& rows)

-

设置行数

-

void SetCols(const uint16_t& cols)

-

设置列数

-

void LayoutChildren(bool needInvalidate = false)

-

布局子组件

-
- -## 开发步骤 - -1. 构造GridLayout并设置位置、大小信息。 - - ``` - GridLayout* layout_ = new GridLayout(); - layout_->SetPosition(0, g_y, HROIZONTAL_RESOLUTION, 200); - layout_->SetLayoutDirection(LAYOUT_HOR); - layout_->SetRows(2); - layout_->SetCols(2); - ``` - -2. 构造子组件button。 - - ``` - UILabelButton* bt1 = new UILabelButton(); - bt1->SetPosition(0,0,100,50); - bt1->SetText("bt1"); - UILabelButton* bt2 = new UILabelButton(); - bt2->SetPosition(0, 0, 100, 50); - bt2->SetText("bt2"); - UILabelButton* bt3 = new UILabelButton(); - bt3->SetPosition(0, 0, 100, 50); - bt3->SetText("bt3"); - UILabelButton* bt4 = new UILabelButton(); - bt4->SetPosition(0, 0, 100, 50); - bt4->SetText("bt4"); - ``` - -3. 添加子组件并调用LayoutChildren\(\)。 - - ``` - layout_->Add(bt1); - layout_->Add(bt2); - layout_->Add(bt3); - layout_->Add(bt4); - layout_->LayoutChildren(); - ``` - -4. 检查button组件布局效果如下图所示。 - - **图 3** 设置2\*2网格并添加4个button组件进行布局 - ![](figures/设置2-2网格并添加4个button组件进行布局.png "设置2-2网格并添加4个button组件进行布局") - - diff --git "a/zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100755 index c81824514aa2b6660e73433a089e82faca04fa13..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,56 +0,0 @@ -# 常见问题 - -- [系统启动过程中打印“parse failed!”错误后停止启动](#section2041345718513) -- [系统启动过程未结束就自动重启,如此反复持续](#section57381816168) -- [参数正确的情况下调用SetParameter/GetParameter返回失败](#section129991227141512) - -## 系统启动过程中打印“parse failed!”错误后停止启动 - -**现象描述** - -系统启动过程中,打印“\[Init\] InitReadCfg, parse failed! please check file /etc/init.cfg format.”错误,启动过程停止,如下图所示: - -![](figures/zh-cn_image_0000001063839940.png) - -**可能原因** - -修改init.cfg文件时,漏掉或多加了逗号或括号等,导致init.cfg文件的json格式被破坏。 - -**解决办法** - -仔细检查init.cfg文件,确保其格式符合json格式要求。 - -## 系统启动过程未结束就自动重启,如此反复持续 - -**现象描述** - -镜像烧写完成后系统启动,启动过程未完成即自动重新启动,如此反复持续。 - -**可能原因** - -被init启动的服务都有一个叫做“importance”的属性(详见[第2章表3](init启动引导组件.md#table14737791471)描述)。 - -- 当该属性为0时,表示若当前服务进程退出,init不需要重启单板。 -- 当该属性为1时,表示若当前服务进程退出,init需要重启单板。 - -因此出现上述现象的可能原因:有“importance”属性为1的服务在每次启动的过程中都会退出(可能是进程崩溃或出错自动退出),导致init进程自动重启单板。 - -**解决办法** - -1. 需要通过日志确认崩溃或报错退出的服务,并解决其崩溃/报错的问题,然后重新烧写镜像即可。 -2. 也可以将崩溃/报错退出的服务的“importance”属性改为0,然后重新烧写镜像,这样即使其退出,init也不会重启单板。 - -## 参数正确的情况下调用SetParameter/GetParameter返回失败 - -**现象描述** - -在各参数正确的情况下调用SetParameter/GetParameter返回失败。 - -**可能原因** - -程序对SetParameter/GetParameter这两个接口做了权限校验,在各参数正确的情况下调用SetParameter/GetParameter返回操作失败,很有可能是调用者的uid大于1000,没有调用权限。 - -**解决办法** - -无需处理 - diff --git "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 127a7f175667a950f8cd2f4e43e3bc738d825519..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\346\235\203\351\231\220\347\256\241\347\220\206\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,228 +0,0 @@ -# 应用权限管理开发指导 - -- [运作机制](#section193961322175011) -- [场景介绍](#section18502174174019) -- [接口说明](#section1633115419401) -- [开发步骤](#section022611498210) - -## 运作机制 - -由于OpenHarmony允许安装三方应用,所以需要对三方应用的敏感权限调用进行管控,具体实现是应用在开发阶段就需要在profile.json中指明此应用在运行过程中可能会调用哪些敏感权限,这些权限包括静态权限和动态权限,静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示获取用户的敏感信息,所以需要在运行时让用户确认才可以调用,授权方式包括系统设置应用手动授权等。除了运行时对应用调用敏感权限进行管控外,还需要利用应用签名管控手段确保应用安装包已经被设备厂商进行了确认。 - -**表 1** OpenHarmony权限列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

OpenHarmony权限

-

授权方式

-

权限说明

-

ohos.permission.LISTEN_BUNDLE_CHANGE

-

system_grant(静态权限)

-

允许该应用获取应用变化消息。

-

ohos.permission.GET_BUNDLE_INFO

-

system_grant(静态权限)

-

允许该应用获取应用信息。

-

ohos.permission.INSTALL_BUNDLE

-

system_grant(静态权限)

-

允许该应用安装应用。

-

ohos.permission.CAMERA

-

user_grant(动态权限)

-

此应用可随时使用相机拍摄照片和录制视频。

-

ohos.permission.MODIFY_AUDIO_SETTINGS

-

system_grant(静态权限)

-

允许该应用修改全局音频设置,例如音量和用于输出的扬声器。

-

ohos.permission.READ_MEDIA

-

user_grant(动态权限)

-

允许该应用读取您的视频收藏。

-

ohos.permission.MICROPHONE

-

user_grant(动态权限)

-

此应用可随时使用麦克风进行录音。

-

ohos.permission.WRITE_MEDIA

-

user_grant(动态权限)

-

允许该应用写入您的音乐收藏。

-

ohos.permission.DISTRIBUTED_DATASYNC

-

user_grant(动态权限)

-

管控分布式数据传输能力。

-

ohos.permission.DISTRIBUTED_VIRTUALDEVICE

-

user_grant(动态权限)

-

允许应用使用分布式虚拟能力

-
- ->![](public_sys-resources/icon-note.gif) **说明:** ->静态权限:应用安装时由系统授予的权限,对应于权限敏感级别的system\_grant ->动态权限:应用在运行过程中需要用户授权的权限,对应于权限敏感级别的user\_grant - -## 场景介绍 - -应用权限是软件用来访问系统资源和使用系统能力的一种通行方式。在涉及用户隐私相关功能和数据的场景,例如:访问个人设备的硬件特性,如摄像头、麦克风,以及读写媒体文件等,OpenHarmony通过应用权限管理组件来保护这些数据以及能力。 - -在系统应用开发过程中,如果应用要使用敏感权限,开发者可以调用应用权限管理组件接口检查待访问权限是否被授权,如果未授权,操作不允许。 - -## 接口说明 - -应用权限管理提供的API接口,当前仅供系统应用和系统服务调用,具体API接口如下。 - -**表 2** 应用权限管理API接口功能介绍 - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int CheckPermission(int uid, const char *permissionName)

-

检查指定UID的应用进程是否具有访问系统服务API的权限

-

int CheckSelfPermission(const char *permissionName)

-

检查调用者是否具有访问系统服务API的权限

-

int QueryPermission(const char *identifier, PermissionSaved **permissions, int *permNum)

-

查询应用申请的所有权限,并检查权限是否被授予

-

int GrantPermission(const char *identifier, const char *permName)

-

将指定权限授予应用程序

-

int RevokePermission(const char *identifier, const char *permName)

-

收回应用程序的指定权限

-

int GrantRuntimePermission(int uid, const char *permissionName)

-

应用运行时动态授予指定权限

-

int RevokeRuntimePermission(int uid, const char *permissionName)

-

应用运行时动态撤销指定权限

-
- -## 开发步骤 - -本部分以包管理器的应用权限开发为例进行讲解。开发过程中,首先需要明确涉及的敏感权限,并在config.json中声明该权限,在安装应用程序时,包管理器会调用应用权限管理组件的接口检查该权限是否被授予,若授予,安装流程正常进行,否则安装失败。 - -1. 在开发过程中,包管理器明确需要安装应用的权限(ohos.permission.INSTALL\_BUNDLE),并在config.json中声明该权限; - - ``` - { - ... - "module": { - "package": "com.huawei.kitframework", - "deviceType": [ - "phone", "tv","tablet", "pc","car","smartWatch","sportsWatch","smartCamera", "smartVision" - ], - "reqPermissions": [{ - // 声明需要的权限:安装应用程序的权限名 - "name": "ohos.permission.INSTALL_BUNDLE", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - }, - { - "name": "ohos.permission.LISTEN_BUNDLE_CHANGE", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - }, - { - "name": "ohos.permission.GET_BUNDLE_INFO", - "reason": "install bundle", - "usedScene": { - "ability": [ - "KitFramework" - ], - "when": "always" - } - } - ], - ... - } - ``` - -2. 当包管理器开发应用安装功能接口时,会调用权限管理相关接口检查自身是否具有安装应用程序的权限,例如:以安装应用的权限名"ohos.permission.INSTALL\_BUNDLE"作为入参,调用CheckPermission接口检查包管理器是否具有安装应用的权限,如果有权限,安装流程继续执行,否则返回安装失败; - - ``` - constexpr static char PERMISSION_INSTALL_BUNDLE[] = "ohos.permission.INSTALL_BUNDLE"; - - bool Install(const char *hapPath, const InstallParam *installParam, InstallerCallback installerCallback) - { - if ((hapPath == nullptr) || (installerCallback == nullptr) || (installParam == nullptr)) { - HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to nullptr parameters"); - return false; - } - // 检查ohos.permission.INSTALL_BUNDLE权限是否被授予 - if (CheckPermission(0, static_cast(PERMISSION_INSTALL_BUNDLE)) != GRANTED) { - HILOG_ERROR(HILOG_MODULE_APP, "BundleManager install failed due to permission denied"); - return false; // 返回安装失败 - } - // 安装流程 - ... - } - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 8c5e78070f8c6b457d28fa149bcc528bad8a910b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\272\224\347\224\250\351\252\214\347\255\276\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,272 +0,0 @@ -# 应用验签开发指导 - -- [场景介绍](#section18502174174019) -- [验签流程](#section554632717226) -- [接口说明](#section1633115419401) -- [开发步骤(场景一)](#section4207112818418) - - [验签指导](#section11470123816297) - - [生成OpenHarmony自签名应用](#section167151429133312) - - [开发示例](#section174318361353) - -- [开发步骤(场景二)](#section81272563427) - - [验签指导](#section07028210442) - - [开发示例](#section1930711345445) - -- [调测验证](#section427316292411) - -## 场景介绍 - -当需要验证调试应用、发布应用,OpenHarmony自签名应用的完整性是否被破坏时,可以调用验签组件的接口进行验证。如有需要还可通过验签接口获取部分描述文件信息,如appid。对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 - -## 验签流程 - -未经签名的Hap包的压缩方式是ZIP格式,简单分为文件块,中心目录(Central directory)块,中心目录结尾(EOCD,End of central directory record)块。 - -经过签名的Hap包,在文件块,和中心目录块之间,插入了签名块。签名块由文件签名数据块(data sign block)、描述文件签名数据块(profile sign block)和签名头(sign head)组成,如下图所示。 - -**图 1** 经过签名的Hap包结构 - - -![](figures/安全子系统.png) - -整个验签流程,主要分为三部分:整包验签、描述文件签名块验签,以及描述文件内容校验。 - -**整包验签** - -用设备的预置根证书,通过证书链来证明叶子证书本身是可信的,然后用叶子证书的公钥解密出的摘要证明整包是未篡改的。 - -具体操作步骤如下: - -1. 对文件签名数据块中的证书链进行校验,确定其叶子证书是可信的。 -2. 用叶子证书中的公钥对文件签名块进行验签,证明其未被篡改。 -3. 计算并合并文件块,中心目录块和中心目录结尾块的摘要。然后将计算结果,再与签名块中的描述文件签名块的摘要合并,将最终合并的摘要与文件签名块中包含的摘要对比,如果两者相等,则整包验签通过。 - -**描述文件签名块验签** - -首先判断文件签名的签发单位,如果是应用市场签发的发布应用,则无需对描述文件进行验签,直接信任,否则要对其验签。先取出整个描述文件签名块,然后验证证书链,最后用叶子证书对描述文件数据块验签,证明其未被篡改。 - -**描述文件内容校验** - -取出描述文件,并对其内容进行合法性检查。其中若hap包为调试应用,则会比对本机UDID与描述文件中包含的UDID列表,如果本机UDID在描述文件的UDID列表中包含,则验证通过。比较描述文件中包含的证书(如果是应用市场发布应用或OpenHarmony自签名则无需比较),和整包校验时使用的叶子证书,如果相同,认为整个验签流程完成。 - -## 接口说明 - -验签组件当前提供innerkits接口,仅供系统应用调用,相关接口及功能描述如下: - -**表 1** 验签组件API接口功能介绍 - - - - - - - - - - - - - - - - -

接口名

-

描述

-

int APPVERI_AppVerify(const char *filePath, VerifyResult *verifyRst)

-

主入口函数,输入文件路径,进行验签,并将从描述文件中获取的数据通过verifyRst返回给调用者

-

int APPVERI_SetDebugMode(bool mode)

-

设置测试模式,设置mode为true,则支持基于测试根密钥的证书链校验,设置mode为false,则关闭基于测试根密钥的证书链校验。

-

注:当前没有基于现有测试根密钥的证书,开发者可根据自身需要,替换测试根密钥并进行相关验证。

-

void APPVERI_FreeVerifyRst(VerifyResult *verifyRst)

-

释放verifyRst中申请的内存

-
- -## 开发步骤(场景一) - -### 验签指导 - -对应用市场发布应用、基于应用市场调试证书签发的调试应用、OpenHarmony自签名应用的校验。 - -1. 定义出参结构体变量VerifyResult; - - ``` - VerifyResult verifyResult = {0}; - ``` - -2. 以文件路径及VerifyResult为入参,调用APPVERI\_AppVerify进行文件校验; - - ``` - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - ``` - -3. 判断返回结果,如果校验通过的话,获取VerifyResult中的数据,进行业务处理; - - ``` - signatureInfo.appId = verifyResult.profile.appid; - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - ``` - -4. 调用APPVERI\_FreeVerifyRst,释放VerifyResult中申请的内存。 - - ``` - APPVERI_FreeVerifyRst(&verifyResult); - ``` - - -### 生成OpenHarmony自签名应用 - -如果是OpenHarmony自签名应用的校验,开发者可通过以下方式生成OpenHarmony自签名应用。 - -1. 材料备齐。 - - 生成自签名应用需要的材料有:签名工具、系统应用hap包、系统应用profile文件\(\*.p7b\)、签名证书\(\*.cer\)、签名公私钥对\(\*.jks\)。 - -2. 将所有材料放在同一个目录下,打开shell。 -3. 根据应用、描述文件的实际名称修改指令,并在shell中输入,完成签名。 - - ``` - java -jar hapsigntoolv2.jar sign -mode localjks -privatekey "OpenHarmony Software Signature" -inputFile camera.hap -outputFile signed_camera.hap -signAlg SHA256withECDSA -keystore OpenHarmony.jks -keystorepasswd 123456 -keyaliaspasswd 123456 -profile camera_release.p7b -certpath OpenHarmony.cer -profileSigned 1 - ``` - - 关键字段说明: - - -jar:签名工具,[hapsigntool](https://repo.huaweicloud.com/harmonyos/develop_tools/hapsigntoolv2.jar) - - -mode:本地签名标记位,固定为localjks - - -privatekey:密钥对别名,签名公私钥对的别名为OpenHarmony Software Signature - - -inputFile:待签名应用,通过编译产生 - - -outputFile:签名后应用,最终输出 - - -signAlg:签名算法,当前固定为SHA256withECDSA - - -keystore:公私钥对,使用签名公私钥对,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.jks](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.jks)。默认密码为123456 ,用户可采用工具\(例如keytool\)更改默认密码 - - -keystorepasswd:公私钥对密码,默认签名公私钥对密码为123456 - - -keyaliaspasswd:公私钥对别名密码,默认签名公私钥对别名密码为123456 - - -profile:描述文件,应用的描述文件位于对应源代码目录中 - - -certpath:使用签名证书,位于开源库security\_services\_app\_verify仓中OpenHarmonyCer目录下,[OpenHarmony.cer](https://gitee.com/openharmony/security_appverify/blob/master/interfaces/innerkits/appverify_lite/OpenHarmonyCer/OpenHarmony.cer) - - -profileSigned:签名块中是否包含描述文件\(profile\)。固定为1(包含) - - -### 开发示例 - -以应用管理框架组件在应用安装时进行验签的实际调用为例: - -``` -uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) -{ - bool mode = ManagerService::GetInstance().IsDebugMode(); - HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); - // 定义结果结构体 - VerifyResult verifyResult = {0}; - // 输入待验签文件路径进行验签 - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - uint8_t errorCode = SwitchErrorCode(ret); - if (errorCode != ERR_OK) { - return errorCode; - } - // 从结果结构体中获取appid - signatureInfo.appId = verifyResult.profile.appid; - // 从结果结构体中获取描述文件中书写的应用名 - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - int32_t restricNum = verifyResult.profile.permission.restricNum; - for (int32_t i = 0; i < restricNum; i++) { - signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); - } - // 释放结果结构体中申请的内存 - APPVERI_FreeVerifyRst(&verifyResult); - return ERR_OK; -} -``` - -## 开发步骤(场景二) - -### 验签指导 - -对采用基于测试根密钥证书签名的应用的校验。 - -1. 调用APPVERI\_SetDebugMode\(true\)开启测试模式; - - ``` - ManagerService::SetDebugMode(true); - ... - uint8_t ManagerService::SetDebugMode(bool enable) - { - int32_t ret = APPVERI_SetDebugMode(enable); - if (ret < 0) { - HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); - return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; - } - isDebugMode_ = enable; - HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); - return ERR_OK; - } - ``` - -2. 同场景一中步骤一至四,定义结构体,校验、释放结构体; -3. 调用APPVERI\_SetDebugMode\(false\)关闭测试模式。 - - ``` - ManagerService::SetDebugMode(false); - ``` - - -### 开发示例 - -完整开发示例如下(在场景一代码示例的基础上进行补充): - -``` -uint8_t ManagerService::SetDebugMode(bool enable) -{ - int32_t ret = APPVERI_SetDebugMode(enable); - if (ret < 0) { - HILOG_ERROR(HILOG_MODULE_APP, "set signature debug mode failed"); - return ERR_APPEXECFWK_SET_DEBUG_MODE_ERROR; - } - isDebugMode_ = enable; - HILOG_INFO(HILOG_MODULE_APP, "current sign debug mode is %d", isDebugMode_); - return ERR_OK; -} -uint8_t HapSignVerify::VerifySignature(const std::string &hapFilepath, SignatureInfo &signatureInfo) -{ - // 开启支持测试服务器签名应用验证 - ManagerService::SetDebugMode(true); - bool mode = ManagerService::GetInstance().IsDebugMode(); - HILOG_INFO(HILOG_MODULE_APP, "current mode is %d!", mode); - // 定义结果结构体 - VerifyResult verifyResult = {0}; - // 输入待验签文件路径进行验签 - int32_t ret = APPVERI_AppVerify(hapFilepath.c_str(), &verifyResult); - uint8_t errorCode = SwitchErrorCode(ret); - if (errorCode != ERR_OK) { - return errorCode; - } - // 从结果结构体中获取appid - signatureInfo.appId = verifyResult.profile.appid; - // 从结果结构体中获取描述文件中书写的应用名 - signatureInfo.provisionBundleName = verifyResult.profile.bundleInfo.bundleName; - int32_t restricNum = verifyResult.profile.permission.restricNum; - for (int32_t i = 0; i < restricNum; i++) { - signatureInfo.restrictedPermissions.emplace_back((verifyResult.profile.permission.restricPermission)[i]); - } - // 释放结果结构体中申请的内存 - APPVERI_FreeVerifyRst(&verifyResult); - // 关闭支持测试服务器签名应用验证 - ManagerService::SetDebugMode(false); - return ERR_OK; -} -``` - -## 调测验证 - -1. 选取一个在OpenHarmony上能够正常安装的应用A。 -2. 根据开发指导开发。 -3. 对应用A,采用自开发程序进行验签,验签通过,能获取到appid。即为开发成功。 - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" deleted file mode 100755 index 39c2377cd403b1b3aaed2c97947c6cea63b4e6dc..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\345\256\236\344\276\213-6.md" +++ /dev/null @@ -1,112 +0,0 @@ -# 开发实例 - -- [去电开发实例](#section286643718507) -- [来电开发实例](#section3205350105014) - -## 去电开发实例 - -去电的调用流程示例如下图所示: - -**图 1** 去电调用流程图 - - -![](figures/去电.png) - -当应用触发去电动作时,RIL Adapter会接收到拨打电话的请求,OnRequest\(\)会根据拨打电话请求ID调用拨打电话的接口。在该接口里会把电话服务传过来的数据封装为对应的AT指令发送到Modem,Modem执行完拨号命令后通过OnRequestResponse\(\)接口把响应结果上报给RIL Adapter。 - -``` -#include -#include -#include -#include -#include "atchannel.h" -#include "at_tok.h" -#include "hdf_log.h" -#include "ril.h" - -static void OnRequest(int request, void *data, size_t datalen, RIL_Token token) -{ - HDF_LOGI("OnRequest request = %{public}d start \n", request); - switch (request) { - case HREQ_CALL_DIAL: - SendDialRequest(data, datalen, token); - break; - …… - default: - break; - } -} - -// 将去电ID和参数转换成对应的AT命令,通过send_at_request发送给Modem -static void SendDialRequest(void *data, size_t datalen __unused, RIL_Token token) -{ - char *atCmd; - const char *clir; - int ret; - DialInfo *pDial; - pDial = (DialInfo *) data; - - if (!strncmp(pDial->address, "*31#", 4)) { - HDF_LOGI("clir suppression"); - clir = "i"; - num = (char *)&(pDial->address[4]); - } else if (!strncmp(pDial->address, "#31#", 4)) { - HDF_LOGI("clir invocation"); - clir = "I"; - num = (char *)&(pDial->address[4]); - } else { - HDF_LOGI("set clir state to default"); - clir = ""; - num = (char *)pDial->number; - } - - asprintf(&atCmd, "ATD%s%s;", pDial->address, clir); - ret = send_at_request(atCmd, NULL); - free(atCmd); - // 命令执行完成后调用该接口,将Modem执行的结果反馈给RIL Adapter - OnRequestResponse(t, RIL_RESULT_SUCCESS, NULL, 0); -} -``` - -## 来电开发实例 - -来电的调用流程示例如下图所示: - -**图 2** 来电调用流程图 - - -![](figures/来电.png) - -Modem设备节点读取线程s\_tid\_read会循环读取Modem上报的消息,当Modem接收到来电时会主动上报来电相关的信息; - -当该线程通过调用OnNotificationResponse\(\)解析到Modem上报的数据是以"+CRING"、"RING"等字符开头时,表示有来电事件,然后通过OnRadioEventNotify\(HNOTI\_CALL\_STATUS, NULL, 0\)上报给RIL Adapter完成来电事件上报。 - -``` -#include -#include "atchannel.h" -#include "at_tok.h" -#include "hdf_log.h" -#include "ril.h" - -bool IsCallStatusUpdated(const char *s) -{ - return (StrBeginWith(s, "+CRING:") - || StrBeginWith(s, "RING") - || StrBeginWith(s, "NO CARRIER") - || StrBeginWith(s, "+CCWA")); -} - -// 将Modem上报数据解析为对应的Modem事件 -static void OnNotificationResponse(const char *s, const char *sms_pdu) -{ - char *line = NULL, *p; - HDF_LOGI("OnNotificationResponse = %{public}s sState = %{public}d", s, sState); - // 解析到以"+CRING:"等字符开头的数据时,转换为来电事件 - if (IsCallStatusUpdated(s)) { - // 通知RIL Adapter有来电事件 - OnRadioEventNotify(HNOTI_CALL_STATUS, NULL, 0); - } - …… -} -``` - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" deleted file mode 100644 index 6a68dfe23f9f81c975fab1807c63bc9fbe6a15f4..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274-3.md" +++ /dev/null @@ -1,711 +0,0 @@ -# 开发指导 - -- [场景介绍](#section93012287133) -- [接口说明](#section11821047161319) -- [开发步骤](#section10514141679) - - [创建Service类型的Ability](#section19921154214315) - - [包管理接口使用指导](#section1724016743217) - - [Hap包打包](#section171771212328) - - -## 场景介绍 - -- 带界面的Ability的应用,比如:新闻类的应用、视频类的应用、导航类的应用、支付类的应用等等,目前我们看到的大部分应用都是带有界面的用于人机交互的应用。 - -- 不带界面的Ability应用,比如:音乐播放器能在后台播放音乐、后台提供计算服务、导航服务的各类应用等。 - -- 不管是带界面的Ability应用还是不带界面的Ability应用,都要打包成Hap包,最终发布到应用市场,用户通过应用市场下载安装相应的应用。 - -## 接口说明 - -**表 1** Ability子系统的对外接口 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

接口名称

-

接口描述

-

Want *WantParseUri(const char *uri)

-

反序列化接口,由字符串生成Want对象。

-

const char *WantToUri(Want want)

-

序列化,把Want对象生成字符串。

-

void SetWantElement(Want *want, ElementName element);

-

设置ElementName对象。

-

void SetWantData(Want *want, const void *data, uint16_t dataLength)

-

设置数据。

-

bool SetWantSvcIdentity(Want *want, SvcIdentity sid)

-

设置SvcIdentity。

-

void ClearWant(Want *want)

-

清除Want的内部内存数据。

-

void SetMainRoute(const std::string &entry)

-

设置AbilitySlice主路由。

-

void SetUIContent(RootView *rootView)

-

设置布局资源。

-

void OnStart(const Want& intent)

-

Ability生命周期状态回调,Ability启动时被回调。

-

void OnStop()

-

Ability生命周期状态回调,Ability销毁时被回调。

-

void OnActive(const Want& intent)

-

Ability生命周期状态回调,Ability显示时被回调。

-

void OnInactive()

-

Ability生命周期状态回调,Ability隐藏时被回调。

-

void OnBackground()

-

Ability生命周期状态回调,Ability退到后台时被回调。

-

const SvcIdentity *OnConnect(const Want &want)

-

Service类型Ability第一次连接时被回调。

-

void OnDisconnect(const Want &want);

-

Service类型Ability断开连接被回调。

-

void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply);

-

Service类型Ability接收消息处理。

-

void Dump(const std::string &extra)

-

dump Ability信息。

-

void Present(AbilitySlice *abilitySlice, const Want &want)

-

发起AbilitySlice跳转。

-

void Terminate()

-

退出当前AbilitySlice。

-

void SetUIContent(RootView *rootView)

-

设置当前AbilitySlice所在Ability的布局资源。

-

void OnStart(const Want& want)

-

AbilitySlice生命周期状态回调,AbilitySlice启动时被回调。

-

void OnStop()

-

AbilitySlice生命周期状态回调,AbilitySlice销毁时被回调。

-

void OnActive(const Want& want)

-

AbilitySlice生命周期状态回调,AbilitySlice显示时被回调。

-

void OnInactive()

-

AbilitySlice生命周期状态回调,AbilitySlice隐藏时被回调。

-

void OnBackground()

-

AbilitySlice生命周期状态回调,AbilitySlice退到后台时被回调。

-

int StartAbility(const Want &want)

-

启动Ability。

-

int StopAbility(const Want &want)

-

停止Service类型的Ability。

-

int TerminateAbility()

-

销毁当前的Ability。

-

int ConnectAbility(const Want &want, const IAbilityConnection &conn, void *data);

-

绑定Service类型的Ability。

-

int DisconnectAbility(const IAbilityConnection &conn)

-

解绑Service类型的Ability。

-

const char *GetBundleName()

-

获取当前ability的对应应用的包名。

-

const char *GetSrcPath()

-

获取当前ability的对应应用的安装路径。

-

const char *GetDataPath()

-

获取当前ability的对应应用的数据路径。

-

int StartAbility(const Want *want)

-

启动Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

int ConnectAbility(const Want *want, const IAbilityConnection *conn, void *data);

-

绑定Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

int DisconnectAbility(const IAbilityConnection *conn);

-

解绑Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

int StopAbility(const Want *want)

-

停止Service类型的Ability,该接口可以不需要在基于Ability开发的应用中使用。

-

void (*OnAbilityConnectDone)(ElementName *elementName, SvcIdentity *serviceSid, int resultCode, void *data)

-

绑定Service Ability的回调。

-

void (*OnAbilityDisconnectDone)(ElementName *elementName, int resultCode, void *data)

-

解绑Service Ability的回调。

-

void PostTask(const Task& task)

-

投递任务到异步线程进行处理。

-

void PostQuit()

-

退出当前线程的消息循环。

-

static AbilityEventHandler* GetCurrentHandler()

-

获取当前线程的事件处理器。

-

void Run()

-

执行当前线程的消息循环。

-

#define REGISTER_AA(className)

-

注册开发者的Ability到框架中。

-

#define REGISTER_AS(className)

-

注册开发者的AbilitySlice到框架中。

-
- -## 开发步骤 - -### 创建Service类型的Ability - -1. 在my\_service\_ability.h中创建Ability的子类MyServiceAbility。 - - ``` - class MyServiceAbility: public Ability { - protected: - void OnStart(const Want& want); - const SvcIdentity *OnConnect(const Want &want) override; - void MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) override; - }; - ``` - -2. 调用REGISTER\_AA宏将ServiceAbility注册到应用框架中,以便应用框架实例化开发者的MyServiceAbility。 - - ``` - #include "my_service_ability.h" - - REGISTER_AA(ServiceAbility) - - void MyServiceAbility::OnStart(const Want& want) - { - printf("ServiceAbility::OnStart\n"); - Ability::OnStart(want); - } - - const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) - { - printf("ServiceAbility::OnConnect\n"); - return Ability::OnConnect(want); - } - - void MyServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) - { - printf("ServiceAbility::MsgHandle, funcId is %u\n", funcId); - int result = 0; - if (funcId == 0) { - result = IpcIoPopInt32(request) + IpcIoPopInt32(request); - } - // push data - IpcIoPushInt32(reply, result); - } - ``` - -3. 实现Service相关的生命周期方法。Service也是一种Ability,Ability为服务提供了以下生命周期方法,用户可以重写这些方法来添加自己的处理。用户在重写的方法里,需要调用父类对应的方法。 - - OnStart\(\) - - 该方法在创建Service的时候调用,用于做一些Service初始化且耗时较短的工作,在Service的整个生命周期只会调用一次。 - - ``` - void MyServiceAbility::OnStart(const Want& want) - { - printf("ServiceAbility::OnStart\n"); - Ability::OnStart(want); - } - ``` - - - OnConnect​\(\) - - 在组件和服务连接时调用,该方法返回SvcIdentity,组件可以通过它,与服务交互。 - - ``` - const SvcIdentity *MyServiceAbility::OnConnect(const Want &want) - { - printf("ServiceAbility::OnConnect\n"); - return Ability::OnConnect(want); - } - ``` - - - OnDisconnect​\(\) - - 在组件与绑定的Service断开连接时调用。 - - - OnStop\(\) - - 在Service销毁时调用。Service应通过实现此方法来清理任何资源,如关闭线程、注册的侦听器等。 - - -4. 重写消息处理方法。 - - MsgHandle是Service用来处理客户端消息的方法。其中funcId是客户端传过来的消息类型,request是客户端传过来的序列化请求参数。如果用户在处理完成之后想要把结果传回去,需要把结果序列化后写入reply中。 - - ``` - void ServiceAbility::MsgHandle(uint32_t funcId, IpcIo *request, IpcIo *reply) - { - printf("ServiceAbility::MsgHandle, funcId is %d\n", funcId); - int result = 0; - if (funcId == PLUS) { - result = IpcIoPopInt32(request) + IpcIoPopInt32(request); - } - // push data - IpcIoPushInt32(reply, result); - } - ``` - -5. 注册Service。 - - Service也需要在应用清单文件config.json中进行注册,注册类型type需要设置为service。 - - ``` - "abilities": [{ - "name": "ServiceAbility", - "icon": "res/drawable/phone.png", - "label": "test app 2", - "launchType": "standard", - "type": "service", - "visible": true - } - ] - ``` - -6. 启动Service。 - - Ability为用户提供了StartAbility\(\)方法来启动另外一个Ability,因为Service也是Ability的一种,开发者同样可以通过将Want传递给该方法来启动Service。 - - 开发者可以通过Want的SetWantElement \(\)来设置目标服务信息。ElementName结构体的两个主要参数:第一个参数为包名称;第二个参数为目标Ability。 - - ``` - { - Want want = { nullptr }; - ElementName element = { nullptr }; - SetElementBundleName(&element, "com.company.appname"); - SetElementAbilityName(&element, "ServiceAbility"); - SetWantElement(&want, element); - StartAbility(want); - ClearElement(&element); - ClearWant(&want); - } - ``` - - StartAbility\(\) 方法会立即执行,如果Service尚未运行,则系统首先会调用OnStart\(\)。 - - - 停止Service。 - - Service一旦创建就会一直保持在后台运行,开发者可以通过调用StopAbility\(\)来停止Service。 - - -7. 连接Service。 - - 如果Service需要与Page Ability或其他应用组件中的Service进行交互,则应创建用于连接的Service。Service支持其他Ability通过ConnectAbility\(\)与其进行连接,ConnectAbility\(\)需要传入目标Service的Want,以及IAbilityConnection的实例来处理回调。IAbilityConnection提供了两个方法供用户实现,OnAbilityConnectDone\(\)用来处理连接的回调,OnAbilityDisconnectDone\(\)用来处理断开连接的回调。 - - ``` - { - // ability创建IAbilityConnection对象和定义IAbilityConnection的两个方法实现 - IAbilityConnection abilityConnection = new IAbilityConnection(); - abilityConnection->OnAbilityConnectDone = OnAbilityConnectDone; - abilityConnection->OnAbilityDisconnectDone = OnAbilityDisconnectDone; - - void OnAbilityConnectDone(ElementName *elementName, SvcIdentity *serviceSid, - int resultCode, void *data) - { - if (resultCode != 0) { - return; - } - // push data - IpcIo request; - char dataBuffer[IPC_IO_DATA_MAX]; - IpcIoInit(&request, dataBuffer, IPC_IO_DATA_MAX, 0); - IpcIoPushInt32(&request, 10); - IpcIoPushInt32(&request, 6); - - // send and getReply - IpcIo reply; - uintptr_t ptr = 0; - if (Transact(nullptr, *serviceSid, 0, &request, &reply, - LITEIPC_FLAG_DEFAULT, &ptr) != LITEIPC_OK) { - printf("transact error\n"); - return; - } - int result = IpcIoPopInt32(&reply); - printf("execute add method, result is %d\n", result); - if (ptr != 0) { - FreeBuffer(nullptr, reinterpret_cast(ptr)); - } - } - - void OnAbilityDisconnectDone(ElementName *elementName, - int resultCode, void *data) - { - printf("elementName is %s, %s\n", - elementName->bundleName, elementName->abilityName); - } - } - ``` - - - 发起connect和disconnect。 - - ``` - { - // ability发起connect - Want want = { nullptr }; - ElementName element = { nullptr }; - SetElementBundleName(&element, "com.company.appname"); - SetElementAbilityName(&element, "ServiceAbility"); - SetWantElement(&want, element); - ConnectAbility(want, *abilityConnection, this); - - // ability发起disconnect - DisconnectAbility(*abilityConnection); - } - ``` - - - -### 包管理接口使用指导 - -**安装应用** - -安装接口只能给内置的系统应用使用。根据应用的安装路径,可以在安装应用时进行选择: - -- 将应用安装到系统默认的文件目录/storage/app/。 -- 将应用安装到系统外挂的存储介质中,例如micro sdcard。 - -这两种选择可以在创建InstallParam实例的时候指定,当InstallParam的成员变量installLocation为 INSTALL\_LOCATION\_INTERNAL\_ONLY时,意味着应用将会被安装到/storage/app/目录下;当InstallParam的成员变量installLocation为INSTALL\_LOCATION\_PREFER\_EXTERNAL时,意味着应用将被安装到存储介质,其安装目录是/sdcard/app/。由于安装应用的过程是异步的,所以需要使用类似信号量的机制来确保安装的回调可以被执行。 - -安装应用的步骤如下(示例代码以安装到系统目录为例): - -1. 将经过安全签名的应用放置于指定的目录下。 -2. 创建InstallParam实例和信号量。 - - ``` - InstallParam installParam = { - .installLocation = INSTALL_LOCATION_INTERNAL_ONLY, // 安装到系统目录 - .keepData = false - }; - static sem_t g_sem; - ``` - -3. 定义回调函数。 - - ``` - static void InstallCallback(const uint8_t resultCode, const void *resultMessage) - { - std::string strMessage = reinterpret_cast(resultMessage); - if (!strMessage.empty()) { - printf("install resultMessage is %s, %d\n", strMessage.c_str(),resultCode); - } - sem_post(&g_sem); - } - ``` - -4. 调用Install接口。 - - ``` - const uint32_t WAIT_TIMEOUT = 30; - sem_init(&g_sem, 0, 0); - std::string installPath = “/storage/bundle/demo.hap”; // hap包的存储路径 - bool result = Install(installPath.c_str(), &installParam, InstallCallback); - struct timespec ts = {}; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += WAIT_TIMEOUT; // 超时即释放信号量 - sem_timedwait(&g_sem, &ts); - ``` - - -**卸载应用** - -卸载应用的时候可以选择是否保留应用的数据,开发者可以通过创建的InstallParam实例的成员变量keepData来确定。当keepData为true, 卸载应用之后将保留应用的数据,当keepData为false时,卸载应用之后将不会保留应用的数据。 - -1. 创建InstallParam实例和信号量。 - - ``` - static sem_t g_sem; - InstallParam installParam = { - .installLocation = 1, - .keepData = false // 不保留应用数据 - }; - ``` - -2. 定义回调函数。 - - ``` - static void UninstallCallback(const uint8_t resultCode, const void *resultMessage) - { - std::string strMessage = reinterpret_cast(resultMessage); - if (!strMessage.empty()) { - printf("uninstall resultMessage is %s\n", strMessage.c_str()); - g_resultMessage = strMessage; - } - g_resultCode = resultCode; - sem_post(&g_sem); - } - ``` - -3. 调用Uninstall接口。 - - ``` - sem_init(&g_sem, 0, 0); - const uint32_t WAIT_TIMEOUT = 30; - std::string BUNDLE_NAME = “com.huawei.demo”; // 卸载应用的包名 - Uninstall(BUNDLE_NAME.c_str(), &installParam, UninstallCallback); - struct timespec ts = {}; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += WAIT_TIMEOUT; - sem_timedwait(&g_sem, &ts); - ``` - - -**查询已安装应用的包信息** - -开发者可以利用BundleManager提供的接口GetBundleInfo来查询系统内已安装应用的包信息。 - -1. 创建以及初始化BundleInfo。 - - ``` - BundleInfo bundleInfo; - (void) memset_s(&bundleInfo, sizeof(BundleInfo), 0, sizeof(BundleInfo)); - ``` - -2. 调用GetBundleInfo接口,指定查询应用的包名,同时指定flag来确定获取的BundleInfo中是否含有元能力信息(实例代码以含有元能力信息为例)。 - - ``` - std::string BUNDLE_NAME = "com.huawei.demo"; - uint8_t ret = GetBundleInfo(BUNDLE_NAME.c_str(), 1, &bundleInfo); // flags = 1,获取包信息中含有元能力信息 - ``` - -3. 使用完获取的BundleInfo之后,要及时清理掉其内部所占用的内存空间避免内存泄漏。 - - ``` - ClearBundleInfo(&bundleInfo); - ``` - - -### Hap包打包 - -打包工具一般集成到开发工具或者ide中,开发者一般不涉及直接使用该工具,下面的介绍开发者可以作为了解。打包工具的jar包在开源代码中的位置:developtools/packing\_tool/jar。 - -- 打包命令行参数 - - **表 2** 打包所需要的资源文件描述 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

命令参数

-

对应的资源文件

-

说明

-

是否可缺省

-

--mode

-

-

-

为“hap”字段,打包生成hap

-

-

--json-path

-

清单文件config.json

-

-

-

-

--resources-path

-

资源文件resources

-

-

-

-

--assets-path

-

资源文件assets

-

-

-

-

--lib-path

-

依赖库文件

-

-

-

-

--shared-libs-path

-

共享库文件

-

针对系统应用的共享库,特殊情况下使用

-

-

--ability-so-path

-

主功能so文件

-

-

-

-

--index-path

-

资源索引

-

资源索引文件由资源生成工具生成,由资源流水线会集成该工具

-

-

--out-path

-

-

-

生成的hap包输出路径,默认为当前目录

-

-

--force

-

-

-

是否覆盖原有同名文件,默认为false

-

-
- -- 打包示例 - - 开发视图 - - ![](figures/zh-cn_image_0000001062942690.png) - - - 编译视图 - - ![](figures/zh-cn_image_0000001062334618.png) - - - 使用打包工具执行以下命令打包: - - ![](figures/zh-cn_image_0000001062476933.png) - - ``` - $ java -jar hmos_app_packing_tool.jar --mode hap --json-path ./config.json --assets-path ./assets/ --ability-so-path ./libentry.so --index-path ./resources.index --out-path out/entry.hap --force true - ``` - - - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 4ef866ea112a9d162a86e22d4a5badacfbfb1b0b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 开发指导 - -为实现AI 引擎框架的接入,开发者需开发上述[图1](AI引擎框架开发指南.md#fig143186187187)中的SDK模块和Plugin模块,通过调用sdk提供的接口,基于AI引擎框架实现调用plugin中算法的能力,从而实现AI能力的生命周期管理和按需部署功能。 - -- **[SDK开发过程](SDK开发过程.md)** - -- **[插件的开发过程](插件的开发过程.md)** - -- **[配置文件的开发过程](配置文件的开发过程.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" "b/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" deleted file mode 100755 index 346b8a084afbb9645ee0436d39b12456a2b28625..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\345\274\200\345\217\221\347\244\272\344\276\213.md" +++ /dev/null @@ -1,13 +0,0 @@ -# 开发示例 - -以开发唤醒词识别为例,开发者可在Hi3516DV300开发板上,基于AI引擎框架开发唤醒词识别的sdk以及唤醒词识别的plugin,通过编译命令编出新的版本镜像并将其烧入版本。同时,开发者开发唤醒词识别的应用,该应用能够接收外部音频,将listen到的音频传入SDK中的接口,若音频中带有关键词,唤醒词识别的应用会识别出相应的词语,并打印在命令行中。 - -本示例中唤醒词识别的场景中唤醒词是固定的,当开发者传入的音频包含”Hi,小问“,启动的应用就会打印"\[Hi, xiaowen\]",当不包含时,会打印'\[UNKNOWN\]"。 - -- **[唤醒词识别SDK的开发示例](唤醒词识别SDK的开发示例.md)** - -- **[唤醒词识别插件的开发示例](唤醒词识别插件的开发示例.md)** - -- **[唤醒词识别配置文件的开发示例](唤醒词识别配置文件的开发示例.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" "b/zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" deleted file mode 100755 index e2497a9e3850d12fc57e61924b8f6b0b2451d7d9..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\212\200\346\234\257\350\247\204\350\214\203.md" +++ /dev/null @@ -1,15 +0,0 @@ -# 技术规范 - -**用词约定:** - -**规则:**必须准守的约定 - -**建议:**需要加以考虑的约定 - -- **[代码管理规范](代码管理规范.md)** - -- **[命名规范](命名规范.md)** - -- **[接口开发规范](接口开发规范.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 2b37619913040891523cba68ded948d628a273f5..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\213\215\347\205\247\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,395 +0,0 @@ -# 拍照开发指导 - -- [使用场景](#section1963312376119) -- [接口说明](#section56549532016) -- [约束与限制](#section1165911177314) -- [开发步骤](#section138543918214) - -## 使用场景 - -使用Camera产生图片帧(拍照)。 - -## 接口说明 - -**表 1** API列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

类名

-

接口名

-

描述

-

CameraKit

-

int32_t GetCameraIds(std::list<string> cameraList)

-

获取cameraId列表

-

CameraKit

-

CameraAbility& GetCameraAbility(string cameraId)

-

获取指定camera的能力

-

CameraKit

-

void RegisterCameraDeviceCallback(CameraDeviceCallback* callback, EventHandler* handler)

-

注册camera设备状态回调

-

CameraKit

-

void UnregisterCameraDeviceCallback(CameraDeviceCallback* callback)

-

去注册camera设备状态回调

-

CameraKit

-

void CreateCamera(string cameraId, CameraStateCallback* callback, EventHandler* handler)

-

创建camera实例

-

Camera

-

string GetCameraId()

-

获取cameraID

-

Camera

-

CameraConfig& GetCameraConfig()

-

获取camera配置信息

-

Camera

-

FrameConfig& GetFrameConfig(int32_t type)

-

获取捕获帧类型

-

Camera

-

void Configure(CameraConfig& config)

-

配置camera

-

Camera

-

void Release()

-

释放camera

-

Camera

-

int TriggerLoopingCapture(FrameConfig& frameConfig)

-

开始循环帧捕获

-

Camera

-

void StopLoopingCapture()

-

停止循环帧捕获

-

Camera

-

int32_t TriggerSingleCapture(FrameConfig& frameConfig)

-

抓图

-

CameraConfig

-

void SetFrameStateCallback(FrameStateCallback* callback, EventHandler* handler);

-

设置帧状态回调

-

CameraConfig

-

static CameraConfig* CreateCameraConfig()

-

创建camera配置信息实例

-

CameraAbility

-

std::list<Size> GetSupportedSizes(int format)

-

根据类型获取支持输出图像尺寸大小

-

CameraAbility

-

std::list<T> GetParameterRange(uint32_t key)

-

获取支持的参数范围

-

CameraDevice

-

CameraDeviceCallback()

-

camera设备回调类构造函数

-

CameraDevice

-

void OnCameraStatus​(std::string cameraId, int32_t status)

-

camera设备状态变化时的回调

-

CameraStateCallback

-

CameraStateCallback​()

-

camera状态回调类构造函数

-

CameraStateCallback

-

void OnConfigured​(Camera& camera)

-

camera配置成功回调

-

CameraStateCallback

-

void OnConfigureFailed​(Camera& camera,int32_t errorCode)

-

camera配置失败回调

-

CameraStateCallback

-

void OnCreated​(Camera& camera)

-

camera创建成功回调

-

CameraStateCallback

-

void OnCreateFailed​(std::string cameraId,int32_t errorCode)

-

camera创建失败回调

-

CameraStateCallback

-

void OnReleased​(Camera& camera)

-

camera释放回调

-

FrameStateCallback

-

FrameStateCallback​()

-

帧状态回调类构造函数

-

FrameStateCallback

-

void OnFrameFinished(Camera& camera, FrameConfig& frameConfig, FrameResult& frameResult)

-

拍照帧完成回调

-

FrameStateCallback

-

void OnFrameError​(Camera& camera, FrameConfig& frameConfig, int32_t errorCode, FrameResult& frameResult)

-

拍照帧异常回调

-

FrameConfig

-

int32_t GetFrameConfigType()

-

获取帧配置类型

-

FrameConfig

-

std::list<OHOS::Surface> GetSurfaces()

-

获取帧配置的surface

-

FrameConfig

-

void AddSurface(OHOS::AGP::UISurface& surface);

-

添加surface

-

FrameConfig

-

void RemoveSurface(OHOS::AGP::UISurface& surface);

-

删除surface

-
- -## 约束与限制 - -无。 - -## 开发步骤 - -1. 实现设备状态回调的派生类,用户在设备状态发生变更(如新插入相机设备/相机掉线)时,自定义操作。 - - ``` - class SampleCameraDeviceCallback : public CameraDeviceCallback { - void OnCameraStatus(std::string cameraId, int32_t status) override - { - //do something when camera is available/unavailable - } - }; - ``` - -2. 实现帧事件回调的派生类,这里在拿到帧数据以后将其转存为文件。 - - ``` - static void SampleSaveCapture(const char *p, uint32_t size) - { - cout << "Start saving picture" << endl; - struct timeval tv; - gettimeofday(&tv, NULL); - struct tm *ltm = localtime(&tv.tv_sec); - if (ltm != nullptr) { - ostringstream ss("Capture_"); - ss << "Capture" << ltm->tm_hour << "-" << ltm->tm_min << "-" << ltm->tm_sec << ".jpg"; - - ofstream pic("/sdcard/" + ss.str(), ofstream::out | ofstream::trunc); - cout << "write " << size << " bytes" << endl; - pic.write(p, size); - cout << "Saving picture end" << endl; - } - } - - class TestFrameStateCallback : public FrameStateCallback { - void OnFrameFinished(Camera &camera, FrameConfig &fc, FrameResult &result) override - { - cout << "Receive frame complete inform." << endl; - if (fc.GetFrameConfigType() == FRAME_CONFIG_CAPTURE) { - cout << "Capture frame received." << endl; - list surfaceList = fc.GetSurfaces(); - for (Surface *surface : surfaceList) { - SurfaceBuffer *buffer = surface->AcquireBuffer(); - if (buffer != nullptr) { - char *virtAddr = static_cast(buffer->GetVirAddr()); - if (virtAddr != nullptr) { - SampleSaveCapture(virtAddr, buffer->GetSize()); - } - surface->ReleaseBuffer(buffer); - } - delete surface; - } - delete &fc; - } - } - }; - ``` - -3. 实现相机状态回调的派生类,当相机状态发生变化(配置成功/失败,创建成功/失败\)时,自定义操作。 - - ``` - class SampleCameraStateMng : public CameraStateCallback { - public: - SampleCameraStateMng() = delete; - SampleCameraStateMng(EventHandler &eventHdlr) : eventHdlr_(eventHdlr) {} - ~SampleCameraStateMng() - { - if (recordFd_ != -1) { - close(recordFd_); - } - } - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - void OnCreateFailed(const std::string cameraId, int32_t errorCode) override {} - void OnReleased(Camera &c) override {} - }; - ``` - -4. 创建CameraKit,用于创建和获取camera信息。 - - ``` - CameraKit *camKit = CameraKit::GetInstance(); - list camList = camKit->GetCameraIds(); - string camId; - for (auto &cam : camList) { - cout << "camera name:" << cam << endl; - const CameraAbility *ability = camKit->GetCameraAbility(cam); - /* find camera which fits user's ability */ - list sizeList = ability->GetSupportedSizes(0); - if (find(sizeList.begin(), sizeList.end(), CAM_PIC_1080P) != sizeList.end()) { - camId = cam; - break; - } - } - ``` - -5. 创建Camera实例。 - - ``` - EventHandler eventHdlr; // Create a thread to handle callback events - SampleCameraStateMng CamStateMng(eventHdlr); - - camKit->CreateCamera(camId, CamStateMng, eventHdlr); - ``` - -6. 根据[步骤1](#li378084192111)、[步骤2](#li8716104682913)、[步骤3](#li6671035102514)中的回调设计,camera实例创建成功后会进行配置操作,主流程中app需要设计同步机制。 - - ``` - void OnCreated(Camera &c) override - { - cout << "Sample recv OnCreate camera." << endl; - auto config = CameraConfig::CreateCameraConfig(); - config->SetFrameStateCallback(&fsCb_, &eventHdlr_); - c.Configure(*config); - cam_ = &c; - } - - void Capture() - { - if (cam_ == nullptr) { - cout << "Camera is not ready." << endl; - return; - } - FrameConfig *fc = new FrameConfig(FRAME_CONFIG_CAPTURE); - Surface *surface = Surface::CreateSurface(); - if (surface == nullptr) { - delete fc; - } - surface->SetWidthAndHeight(1920, 1080); /* 1920:width,1080:height */ - fc->AddSurface(*surface); - cam_->TriggerSingleCapture(*fc); - } - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" "b/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" deleted file mode 100755 index 272f0279421d4978f9630781b67300a5888ef970..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203-2.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 搭建环境 - -- 开发板:Hi3516DV300 - -- [下载源码](../get-code/源码获取.md) -- [编译用户程序框架](https://gitee.com/openharmony/docs/blob/master/zh-cn/readme/%E7%94%A8%E6%88%B7%E7%A8%8B%E5%BA%8F%E6%A1%86%E6%9E%B6%E5%AD%90%E7%B3%BB%E7%BB%9F.md) - diff --git "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" "b/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" deleted file mode 100755 index 47fefd53336be6b712b10a85c4ba32aec3e63d6f..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\220\255\345\273\272\347\216\257\345\242\203.md" +++ /dev/null @@ -1,5 +0,0 @@ -# 搭建环境 - -1. 准备开发板:Hi3516DV300,Hi3518EV300 -2. [下载源码](https://device.harmonyos.com/cn/docs/start/get-code/oem_sourcecode_guide-0000001050769927#ZH-CN_TOPIC_0000001050769927__section1186691118430) - diff --git "a/zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" deleted file mode 100755 index 2c417f20a485aa9f6e6bbb303048baacbc30809b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\231\256\351\200\232\347\273\204\344\273\266\345\274\200\345\217\221\346\214\207\345\257\274.md" +++ /dev/null @@ -1,555 +0,0 @@ -# 普通组件开发指导 - -- [UIButton](#section145353310214) -- [使用场景](#section1169616141577) -- [接口说明](#section341211538315) -- [开发步骤](#section22501726193214) -- [UIImageView](#section19523161611259) -- [使用场景](#section1274484210400) -- [接口说明](#section74981992411) -- [开发步骤(自适应)](#section144341333134114) -- [开发步骤(平铺模式)](#section97178160421) -- [UILabel](#section16588132012911) -- [使用场景](#section6870195634218) -- [接口说明](#section2012714510433) -- [开发步骤(默认模式)](#section83221538114410) -- [开发步骤(背景色和透明度)](#section933360204510) -- [开发步骤(字符间距)](#section19447826124518) -- [开发步骤(大小自适应)](#section101711842154617) -- [开发步骤(省略号模式)](#section1249519410471) -- [开发步骤(滚动模式)](#section15643122618478) - -普通组件均继承于基类UIView,不可以添加子组件,常用的普通组件有button、image、label等。 - -**图 1** 普通组件树结构 -![](figures/普通组件树结构.png "普通组件树结构") - -UIView为基础类,UIAbstractProgress、UIArcLabel(旋转字体)、UIButton(按键)、UICanvas(画布)、UILabel(字体)、UIImageView(图片)从UIView继承。UIBoxProgress、UICircleProgress从UIAbstractProgress继承,UILabelButton和UIRepeatButton从UIButton继承,UIImageAnimatorView和UITextureMapper从UIImageView继承。 - -## UIButton - -## 使用场景 - -UIButton组件,提供可点击功能,同时可设置不同状态下样式。 - -## 接口说明 - -**表 1** button接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetImageSrc (const char *defaultImgSrc, const char *triggeredImgSrc)

-

设置button图片

-

void SetImagePosition (const int16_t x, const int16_t y)

-

设置button图片位置

-

int16_t GetImageX () const

-

获取图片X坐标

-

int16_t GetImageY () const

-

获取图片Y坐标

-

const ImageInfo* GetCurImageSrc() const

-

获取当前状态图片

-

Style& GetStyleForState (ButtonState state)

-

设置button当前状态的style

-

voidSetStyleForState (const Style &style, ButtonState state)

-

设置button指定状态的style

-

void Disable ()

-

去使能button

-

void Enable ()

-

使能button

-
- -## 开发步骤 - -1. 实现点击事件。 - - ``` - class TestBtnOnClickListener : public OHOS::UIView::OnClickListener { - bool OnClick(UIView& view, const ClickEvent& event) override - { - int16_t width = view.GetWidth() + 10; - int16_t height = view.GetHeight() + 10; - view.Resize(width, height); - view.Invalidate(); - return true; - } - }; - ``` - -2. 创建一个UIButton。 - - ``` - UIButton* button = new UIButton(); - button->SetPosition(50, 50); - button->SetWidth(100); - button->SetHeight(50); - ``` - -3. 给UIButton注册点击事件回调。 - - ``` - button->SetOnClickListener(new TestBtnOnClickListener()); - ``` - -4. 检查Button点击效果如下图所示,Button逐渐变大。 - - **图 2** UIButton点击效果 - ![](figures/UIButton点击效果.gif "UIButton点击效果") - - -## UIImageView - -## 使用场景 - -图片组件,提供图片显示,透明度设置,图片旋转、缩放功能。支持的图片格式为RGB565、RGB888、RGBA8888、PNG、JPG。 - -## 接口说明 - -**表 2** image接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetSrc (const char *src)

-

设置二进制图片路径

-

void SetSrc (const ImageInfo *src)

-

设置图片指针

-

void SetAutoEnable (bool enable)

-

设置组件大小跟随image大小变化

-

const void* GetSrcType () const

-

获取图片类型

-

bool GetAutoEnable () const

-

获取组件大小是否跟随image大小变化

-

void SetBlurLevel(BlurLevel level)

-

设置模糊等级

-

BlurLevel GetBlurLevel() const

-

获取模糊等级

-

void SetTransformAlgorithm(TransformAlgorithm algorithm)

-

设置旋转算法

-

TransformAlgorithm GetTransformAlgorithm() const

-

获取旋转算法

-
- -## 开发步骤(自适应) - -1. 创建一个UIImageView。 - - ``` - UIImageView* imageView = new UIImageView(); - imageView->SetPosition(0, 30); - ``` - -2. 设置二进制格式的图片。 - - ``` - imageView->SetSrc("..\\config\\images\\A021_001.bin"); - ``` - -3. 检查UIImageView控件大小与图片相同。 - - **图 3** 自适应模式图片效果图 - ![](figures/自适应模式图片效果图.png "自适应模式图片效果图") - - -## 开发步骤(平铺模式) - -1. 创建一个UIImageView。 - - ``` - UIImageView* imageView = new UIImageView(); - imageView->SetPosition(0, 30); - ``` - -2. 设置图片。 - - ``` - imageView->SetSrc("..\\config\\images\\A021_001.bin"); - ``` - -3. 取消图片自适应,设置图片大小,平铺显示效果。 - - ``` - imageView->SetAutoEnable(false); - imageView->Resize(454, 150); - ``` - -4. 检查UIImageView控件显示为平铺效果。 - - **图 4** 平铺模式图片效果图 - ![](figures/平铺模式图片效果图.png "平铺模式图片效果图") - - -## UILabel - -## 使用场景 - -标签(label)是在一块区域上显示文本字符串的组件,可设置区域背景色、文字的显示样式和长文本的显示效果等。 - -## 接口说明 - -**表 3** label接口说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

方法

-

功能

-

void SetText(const char* text);

-

设置文字

-

const char* GetText() const;

-

获取text

-

void SetLineBreakMode(const uint8_t lineBreakMode);

-

设置label模式,例如截断,自动扩展等。

-

uint8_t GetLineBreakMode() const

-

获取label模式

-

void SetTextColor(ColorType color)

-

设置文本颜色

-

ColorType GetTextColor() const

-

获取文本颜色

-

void SetAlign(UITextLanguageAlignment horizontalAlign,

-

UITextLanguageAlignment verticalAlign = TEXT_ALIGNMENT_TOP);

-

设置文本对齐方式

-

UITextLanguageAlignment GetHorAlign() const

-

获取文本水平对齐方式

-

UITextLanguageAlignment GetVerAlign() const

-

获取文本竖直对齐方式

-

void SetDirect(UITextLanguageDirect direct)

-

设置文本显示方向

-

UITextLanguageDirect GetDirect() const

-

获取文本显示方向

-

void SetFontId(uint8_t fontId);

-

设置动态字体id

-

uint8_t GetFontId() const

-

获取动态字体id

-

void SetFont(const char *name, uint8_t size);

-

设置字的名字和大小

-

void SetAnimatorSpeed(uint16_t animSpeed);

-

设置字体旋转的速度

-

uint16_t GetTextWidth();

-

获取字体的宽

-

uint16_t GetTextHeight();

-

获取字体的高

-

void SetRollStartPos(int16_t pos)

-

设置旋转的位置

-

int16_t GetRollStartPos() const

-

获取旋转的位置

-

void SetTextRotation(LabelRotateDegree angle)

-

设置文本旋转角度枚举值

-

LabelRotateDegree GetTextRotation() const

-

获取文本旋转角度枚举值

-

uint16_t GetTextRotateDegree() const

-

获取文本旋转角度数值

-
- -## 开发步骤(默认模式) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置文本数据。 - - ``` - label->SetText("label"); - ``` - -4. 检查label大小和显示效果正常,如下图所示。 - - ![](figures/zh-cn_image_0000001051782526.png) - - -## 开发步骤(背景色和透明度) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置背景颜色及透明度效果。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_BACKGROUND_OPA, 127); - label->SetText("Label"); - ``` - -4. 检查label背景色为Gray,如下图所示。 - - ![](figures/zh-cn_image_0000001052582522.png) - - -## 开发步骤(字符间距) - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置字体颜色和字间距效果。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_LETTER_SPACE, 5); - label->SetText("Label"); - ``` - -4. 检查label字符间距为5,如下图所示。 - - ![](figures/zh-cn_image_0000001052942531.png) - - -## 开发步骤(大小自适应) - -当文本过长时,可根据文本信息自动调整label组件大小,也可以设置文本截断或者文本滚动效果。 - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置字体颜色为Gray,组件大小自适应文本内容。 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT); - label->SetText("123\n567890"); - ``` - -4. 检查label大小自适应文本内容,如下图所示。 - - ![](figures/zh-cn_image_0000001052782555.png) - - -## 开发步骤(省略号模式) - -省略号模式指文本内容显示不下时,在末尾显示省略号。 - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置换行模式为DOT模式 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS); - label->SetText("123567890"); - ``` - -4. 检查label DOT模式效果,如下图所示,末尾显示省略号。 - - ![](figures/zh-cn_image_0000001052662559.png) - - -## 开发步骤(滚动模式) - -文本滚动显示。 - -1. 创建label,设置大小和位置信息。 - - ``` - UILabel* label = new UILabel(); - label->SetPosition(x, y); - label->Resize(width, height); - ``` - -2. 设置字形信息。 - - ``` - label->SetFont("SourceHanSansSC-Regular.otf", 30); - ``` - -3. 设置换行模式为滚动模式 - - ``` - label->SetStyle(STYLE_BACKGROUND_COLOR, Color::Gray().full); - label->SetStyle(STYLE_BACKGROUND_OPA, 127); - label->SetLineBreakMode(UILabel::LINE_BREAK_MARQUEE); - label->SetText("123567890"); - ``` - -4. 检查label滚动模式效果,如下图所示。 - - ![](figures/20200721-223604(eSpace).gif) - - diff --git "a/zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" deleted file mode 100644 index 6c6cf033328d93b995af036b0607bb9c31bb37ef..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\240\207\345\207\206\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 标准系统编译构建指导 - -- **[编译构建概述](编译构建概述-0.md)** - -- **[编译构建使用指导](编译构建使用指导-1.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" "b/zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" deleted file mode 100644 index 45d0d3267613ee990ad09557a99fb18a311c5efe..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260-7.md" +++ /dev/null @@ -1,76 +0,0 @@ -# 概述 - -- [基本概念](#section175012297491) -- [约束与限制](#section2029921310472) - -OpenHarmony安全子系统目前提供给开发者的安全能力主要包含应用可信、权限管理、设备可信。涉及以下几个模块: - -- 应用验签 - - 为了确保应用内容的完整性,系统通过应用签名和Profile对应用的来源进行管控,同时对于调试应用,还可通过验签接口验证应用和设备的UDID是否匹配,确保应用安装在了正确的设备上。 - -- 应用权限管理 - - 应用权限是管理应用访问系统资源和使用系统能力的一种通用方式,应用在开发阶段需要在profile.json中指明此应用在运行过程中可能会调用哪些权限,其中静态权限表示只需要在安装阶段注册就可以,而动态权限一般表示涉及到敏感信息,所以需要用户进行动态授权。 - -- IPC通信鉴权 - - 系统服务通过IPC暴露接口给其他进程访问,这些接口需要配置相应的访问策略,当其他进程访问这些接口时,将会触发IPC通信鉴权机制校验访问进程是否拥有权限访问该接口,若无权限,则拒绝访问该接口。 - -- 可信设备群组管理 - - 提供基于群组概念的同华为账号群组、点对点群组(如二维码、碰一碰等)的设备安全可信关系的创建和查询,分布式应用可基于该能力进行设备间的可信认证,然后向分布式软总线请求设备间安全会话。 - - -## 基本概念 - -在进行依赖验签组件的应用开发前,开发者应了解以下基本概念: - -- Samgr - - Samgr\(System Ability M2anager\)系统能力管理,在OpenHarmony上作为一个管理系统能力的模块,详见系统服务框架子系统。 - - -- BMS - - BMS\(Bundle Manager Service\)包管理管理,在OpenHarmony上主要负责应用的安装、卸载和数据管理。 - - -- 描述文件 - - 本文中的描述文件,指HarmonyAppProvision,简称profile。HarmonyAppProvision采用json文件格式进行描述。 - - -- 叶子证书 - - 最终用于为整包或profile签名的证书称为叶子证书,位于数字证书链的最末端。 - - -- 调试应用 - - 指开发者从应用市场申请调试证书与调试描述文件,并以此签名的hap包。 - - -- 待上架应用 - - 指开发者从应用市场申请发布证书与发布描述文件,以此签名,未通过应用市场正式发布的hap包。 - - -- 发布应用 - - 指开发者从应用市场申请发布证书与发布描述文件,以此签名的hap包,上传至应用市场,并由应用市场正式发布的hap包。 - - -- OpenHarmony自签名应用 - - 当开发者自行编译OpenHarmony系统应用后,采用原应用描述文件,以及公开的OpenHarmony公私钥对和证书进行自签名产生的hap包。 - - -## 约束与限制 - -- 仅支持以下三类应用的验签:应用市场调试应用、应用市场发布应用、OpenHarmony自签名应用的验签。 -- 若对应用市场调试应用验签,则本机UDID需要在描述文件包含的UDID列表中。 -- 待上架应用无法验签通过。 -- 验签组件提供的接口都位于security\_interfaces\_innerkits\_app\_verify仓[app\_verify\_pub.h](https://gitee.com/fork_ohos_wj/security_interfaces_innerkits_app_verify/blob/master/app_verify_pub.h)中,仅支持系统应用开发者调用。 -- 可信设备群组管理接口,目前只对系统签名权限才可以使用。 - diff --git "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" deleted file mode 100755 index 63ee16f94ce7de540c47dae8ab52a5aef504889b..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\246\202\350\277\260.md" +++ /dev/null @@ -1,141 +0,0 @@ -# 概述 - -- [基本概念](#section72601941194812) -- [Ability子系统](#section14633111813374) -- [包管理子系统](#section1341146154412) -- [运作机制](#section94302021112717) -- [约束与限制](#section89534912527) - -用户程序框架是OpenHarmony为开发者提供开发OpenHarmony应用的开发框架,包含两个模块:Ability子系统和包管理子系统。 - -## 基本概念 - -开发者在开发前需要先了解以下基本概念,方便开发者更好的理解OpenHarmony用户程序框架。 - -## Ability子系统 - -Ability子系统是管理OpenHarmony应用运行状态的开发框架。 - -**图 1** Ability子系统框架图 -![](figures/Ability子系统框架图.png "Ability子系统框架图") - -- **Ability**:系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。Ability分为两种类型:Page类型的Ability和Service类型的Ability。 - - **Page类型的Ability**:带有界面,为用户提供人机交互的能力。 - - - **Service类型的Ability**:不带界面,为用户提供后台任务机制。 - - - -- **AbilitySlice**:单个页面及其控制逻辑的总和,是Page类型Ability特有的组件,一个Page类型的Ability可以包含多个AbilitySlice,此时,这些页面提供的业务能力应当是高度相关的。 - - **图 2** Ability与AbilitySlice的关系图 - ![](figures/Ability与AbilitySlice的关系图.png "Ability与AbilitySlice的关系图") - -- **生命周期**:Ability被调度到启动、激活、隐藏和退出等各个状态的统称。 - - **图 3** Ability生命周期流转 - - - ![](figures/图片1.png) - - - **OnStart\(\)** - - 系统首次创建Page实例时触发该回调。对于一个Page实例,该回调在其生命周期过程中仅触发一次,Page在该逻辑后进入INACTIVE状态。开发者必须重写该方法,并在此配置默认展示的AbilitySlice。 - - - **OnActive\(\)** - - Page会在进入INACTIVE状态后来到前台,然后系统调用此回调。Page在此之后进入ACTIVE状态,该状态是应用与用户交互的状态。Page将保持在此状态,除非某类事件发生导致Page失去焦点,比如用户点击返回键或导航到其他Page。 - - 当此类事件发生时,会触发Page回到INACTIVE状态,系统将调用OnInactive\(\)回调。此后,Page可能重新回到ACTIVE状态,系统将再次调用OnActive\(\)回调。因此,开发者通常需要成对实现OnActive\(\)和OnInactive\(\),并在OnActive\(\)中获取在OnInactive\(\)中被释放的资源。 - - - **OnInactive\(\)** - - 当Page失去焦点时,系统将调用此回调,此后Page进入INACTIVE状态。开发者可以在此回调中实现Page失去焦点时应表现的恰当行为。 - - - **OnBackground\(\)** - - 如果Page不再对用户可见,系统将可能根据资源状况调用此回调,此后Page进入BACKGROUND状态。开发者应该在此回调中释放Page不可见时无用的资源,或在此回调中执行较为耗时的状态保存操作。 - - - **OnForeground\(\)** - - 处于BACKGROUND状态的Page仍然驻留在内存中,当重新回到前台时(比如用户重新导航到此Page),系统将先调用OnForeground\(\)回调使Page回到INACTIVE状态,然后调用OnActive\(\)回调使Page回到ACTIVE状态。开发者应当在此回调中重新申请在OnBackground\(\)中释放的资源。轻量化设备目前不支持该接口。 - - - **OnStop\(\)** - - 此回调表示系统正在销毁Page。销毁Page的可能原因包括: - - - 用户通过系统管理能力显式关闭Page,例如使用任务管理器关闭Page。 - - 用户行为触发Page的TerminateAbility\(\)方法调用,例如使用应用的退出功能。 - - 配置变更导致系统暂时销毁Page并重建。 - - 系统出于资源管理目的,自动触发对处于BACKGROUND状态Page的销毁。 - - -- **AbilityKit**:Ability框架提供给开发者的开发包,开发者基于该开发包可以开发出基于Ability组件的应用。基于Ability组件开发的应用有两种类型:基于Javascript语言开发的Ability(JS Ability)和基于C/C++语言开发的Ability(Native Ability)。JS应用开发框架是开发者开发JS Ability所用到框架,是在AbilityKit基础封装的包含js UI组件的一套方便开发者能够迅速开发Ability应用的框架。 -- **AbilityLoader**:负责注册和加载开发者Ability的模块。开发者开发的Ability先要调用AbilityLoader的注册接口注册到框架中,接着Ability启动时会被实例化。 - -- **AbilityManager**:负责AbilityKit和Ability管理服务进行IPC的通信。 - -- **EventHandler**:AbilityKit提供给开发者的用于在Ability中实现线程间通信的一个模块。 - -- **AbilityManagerService**:元能力运行管理服务。该服务用于协调各Ability运行关系、及生命周期进行调度的系统服务。其中,服务启动模块负责Ability管理服务的启动、注册等。服务接口管理模块负责Ability管理服务对外能力的管理。进程管理模块负责Ability应用所在进程的启动和销毁、及其进程信息维护等功能。Ability栈管理模块负责维护各个Ability之间跳转的先后关系。生命周期调度模块是Ability管理服务根据系统当前的操作调度Ability进入相应的状态的模块。连接管理模块是Ability管理服务对Service类型Ability连接管理的模块 - -- **AppSpawn**:负责创建Ability应用所在进程的系统服务,该服务有较高的权限,为Ability应用设置相应的权限,并预加载一些通用的模块,加速应用的启动。 - - -## 包管理子系统 - -包管理子系统是OpenHarmony为开发者提供的安装包管理框架。 - -**图 4** 包管理子系统框架图 -![](figures/包管理子系统框架图.png "包管理子系统框架图") - -- **BundleKit**:是包管理服务对外提供的接口,有安装/卸载接口、包信息查询接口、包状态变化listen接口。 -- **包扫描器**:用来解析本地预制或者安装的安装包,提取里面的各种信息,供管理子模块进行管理,持久化。 -- **包安装子模块**:安装,卸载,升级一个包;包安装服务是一个单独进程和包管理服务通过IPC进行通信,该服务用于创建、删除安装目录和数据目录等,具有较高的权限。 - -- **包管理子模块**:管理安装包相关的信息,存储持久化包信息。 - -- **包安全管理子模块**:签名检查、权限授予、权限管理。 - - -## 运作机制 - -Ability子系统的核心模块是Ability管理服务、包管理子系统的核心模块是包管理服务,这两个服务是系统级服务,借助系统服务框架Samgr实现服务的注册与发现,并对其他进程提供Ability管理服务和包管理服务。Ability管理服务和包管理服务通过AbilityKit和BundleKit以接口的形式向外提供服务。 - -**图 5** Ability管理服务和包管理服务启动 -![](figures/Ability管理服务和包管理服务启动.png "Ability管理服务和包管理服务启动") - -Ability管理服务和包管理服务启动后,就可以安装OpenHarmony应用和启动运行OpenHarmony应用。 - -**图 6** 应用启动流程 -![](figures/应用启动流程.png "应用启动流程") - -桌面为Ability管理服务启动的第一个OpenHarmony应用。桌面启动后,用户可以在桌面上点击安装的OpenHarmony应用并启动该应用。上图6为从桌面启动一个已安装应用的交互流程。 - -从图中可知,Ability管理服务负责协调Ability之间的显示隐藏,包管理服务负责Ability信息的存储查询。 - -## 约束与限制 - -- 语言版本 - - - C++11版本或以上 - - -- 框架针对不同的芯片平台和底层OS能力,规格有所区别 - - - Cortex-M RAM/ROM: - - - RAM:建议大于20K - - - ROM: \> 300K (包含JS应用开发框架,UIKit及引擎等强相关子系统) - - - - Cortex-A RAM/ROM: - - - RAM:建议大于2M - - - ROM:\> 2M (包含JS应用开发框架,UIKit及引擎等强相关子系统) - - - - diff --git "a/zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" "b/zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" deleted file mode 100755 index ee62074e9be367efea0a74fa180c801d6381ef42..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\346\265\213\350\257\225.md" +++ /dev/null @@ -1,989 +0,0 @@ -# 测试 - -- [概述](#section12403172115920) - - [基本概念](#section53632272090) - - [运作机制](#section2394431106) - -- [约束与限制](#section2029921310472) -- [搭建环境](#section175012297491) - - [环境要求](#section935055691014) - - [安装环境](#section6511193210111) - - [检验环境是否搭建成功](#section1899144517117) - -- [开发指导](#section16741101301210) - - [场景介绍](#section93782214124) - - [接口说明](#section54131732101218) - - [开发步骤](#section53541946111218) - -- [开发实例](#section7477121918136) -- [测试平台使用](#section76401945124810) -- [包结构说明](#section1875515364133) - -## 概述 - -### 基本概念 - -测试子系统提供基于python开发的一键式的开发者自测试平台,支持跨平台使用以及三方测试框架拓展,主要包括测试用例编译、测试用例管理、测试用例调度分发、测试用例执行、测试结果收集、测试报告生成、测试用例模板、测试环境管理等模块。 - -在测试子系统开发前,开发者应先了解以下概念: - -- 测试用例编译 - - 支持将测试用例源代码编译成可在被测设备侧执行的二进制文件。 - -- 测试用例调度分发 - - 支持将测试用例通过网口通道或者串口通道分发到不同的被测设备上,并且为每一个测试用例分配特定的测试用例执行器。 - -- 测试用例执行器 - - 负责测试用例的预处理,用例执行,结果记录等执行逻辑。 - -- 测试用例模板 - - 定义了测试用例以及用例编译配置GN文件的统一格式。 - -- 测试平台kit - - 测试平台运行过程中公共方法,如提供测试用例目录向被测设备挂载文件系统,测试用例推送到被测设备,或者从被测设备获取测试结果等操作。 - -- 测试报告生成 - - 定义开发者自测试报告模板,生成web测试报告。 - -- 测试环境管理 - - 支持通过USB、串口等方式管理被测设备,功能包括设备发现,设备状态查询等。 - - -### 运作机制 - -- 测试平台架构图如下: - -**图 1** 测试平台架构 -![](figures/测试平台架构.png "测试平台架构") - -- 测试平台运行时序图如下: - -**图 2** 测试平台运行时序 -![](figures/测试平台运行时序.png "测试平台运行时序") - -- 测试平台运行原理 - -测试平台通过shell脚本启动,以命令行方式支持一系列的测试指令执行,通过命令行输出测试结果。 - -## 约束与限制 - -- 功能使用范围:开发自测试平台仅支持代码级的测试用例开发和验证,如单元测试,模块测试。 -- 规格限制:当前测试框架的适用范围仅支持白盒测试。 -- 操作限制:一台测试设备上仅支持启动单个测试平台。 - -## 搭建环境 - -### 环境要求 - -**表 1** **环境要求** - - - - - - - - - - - - - - - - -

项目

-

测试设备

-

被测设备

-

硬件

-
  • 内存:8G及以上
  • 硬盘:100G及以上
  • 硬件架构:X86或ARM64
-
  • Hi3516 DV300开发板
  • Hi3518 EV300开发板
-

软件

-
  • 操作系统:Windows 10 64位 或 Ubuntu 18.04

    系统组件(Linux): libreadline-dev

    -
  • Python:3.7.5及以上
  • Python插件:pyserial3.3及以上、paramiko2.7.1及以上、setuptools40.8.0及以上,rsa4.0及以上
  • NFS Server:haneWIN NFS Server1.2.50及以上或者 NFSv4及以上
-
  • 系统软件:版本不低于OpenHarmony 1.0
  • 内核类型:LiteOS-A或者Linux
-
- -### 安装环境 - -1. 如测试环境为Linux,需要安装系统组件readline,命令如下: - - ``` - sudo apt-get install libreadline-dev - ``` - - 安装成功提示如下: - - ``` - Reading package lists... Done - Building dependency tree - Reading state information... Done - libreadline-dev is already the newest version (7.0-3). - 0 upgraded, 0 newly installed, 0 to remove and 11 not upgraded. - ``` - -2. 安装Python扩展组件setuptools、(rsa、paramiko、以及pyserial,设备仅支持串口时安装),命令如下: - - 1、安装setuptools,安装命令如下: - - ``` - pip install setuptools - ``` - - 安装成功提示如下: - - ``` - Requirement already satisfied: setuptools in d:\programs\python37\lib\site-packages (41.2.0) - ``` - - 2、安装rsa,安装命令如下: - - ``` - pip install rsa - ``` - - 安装成功提示如下: - - ``` - Installing collected packages: pyasn1, rsa - Successfully installed pyasn1-0.4.8 rsa-4.7 - ``` - - 3、安装Paramiko,安装命令如下: - - ``` - pip install paramiko - ``` - - 安装成功提示如下: - - ``` - Installing collected packages: pycparser, cffi, pynacl, bcrypt, cryptography, paramiko - Successfully installed bcrypt-3.2.0 cffi-1.14.4 cryptography-3.3.1 paramiko-2.7.2 pycparser-2.20 pynacl-1.4.0 - ``` - - 4、安装pyserial(被测设备仅支持串口时安装),安装命令如下: - - ``` - pip install pyserial - ``` - - 安装成功提示如下: - - ``` - Requirement already satisfied: pyserial in d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg (3.4) - ``` - -3. 安装NFS server(被测设备仅支持串口时安装)。 - - **Windows环境安装** - - 下载并安装haneWIN NFS Server1.2.50,地址:https://www.hanewin.net/nfs-e.htm - - **Linux环境下安装** - - ``` - sudo apt install nfs-kernel-server - ``` - - 所有环境配置安装完成,即可在IDE中进行测试平台代码开发调试,推荐的IDE为 DevEco Studio。 - - -### 检验环境是否搭建成功 - -**表 2** **检验环境** - - - - - - - - - - - - - - - - - - - - -

检查项

-

操作

-

满足条件

-

检查python安装与否,版本是否满足要求。

-

命令行窗口执行命令:python --version。

-

版本不小于3.7.5即可。

-

检查python扩展插件安装与否。

-

打开test/xdevice目录,执行run.bat或run.sh。

-

可进入提示符“>>>”界面即可。

-

检查NFS Server启动状态(被测设备仅支持串口时检测)。

-

通过串口登录开发板,执行mount命令挂载NFS。

-

可正常挂载文件目录即可。

-
- -## 开发指导 - -### 场景介绍 - -针对对开发的业务代码进行白盒测试验证。 - -### 接口说明 - -测试框架集成了开源的单元测试框架,并对测试用例的宏定义做了扩展,具体框架说明详见开源官方文档。 - -**表 3** 测试框架扩展宏定义说明 - - - - - - - - - - - - - - - - -

宏定义

-

描述

-

HWTEST

-

测试用例执行不依赖Setup&Teardown。HWTEST对TEST增加了“用例级别”参数“TestSize.Level1”,例如HWTEST(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

-

HWTEST_F

-

测试用例(不带参数)执行依赖Setup&Teardown。HWTEST_F对TEST_F增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_F(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

-

HWTEST_P

-

测试用例(带参数)执行依赖Setup&Teardown。HWTEST_P对TEST_P增加了“用例级别”参数“ TestSize.Level1”,例如HWTEST_P(CalculatorAddTest, TestPoint_001, TestSize.Level1)。

-
- -### 开发步骤 - -1. 按照开发者测试用例目录规划定义测试套文件,需要继承testing::Test类,命名以被测特性+Test命名,示例代码路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp - - ``` - /* - * Copyright (c) 2020 OpenHarmony. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - #include - - using namespace std; - using namespace testing::ext; - - class CalcSubtractionTest : public testing::Test { - public: - static void SetUpTestCase(void); - static void TearDownTestCase(void); - void SetUp(); - void TearDown(); - }; - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >测试用例规范 - >- 命名规范 - > 测试用例源文件名称和测试套内容保持一致,测试套与用例之间关系1:N,测试套与测试源文件之间关系1:1,每个源文件全局唯一,格式:\[特性\]\_\[功能\]\_\[子功能1\]\_\[子功能1.1\],子功能支持向下细分。 - > 文件命名采用全小写+下划线方式命名,以test结尾,如demo用例:developertest/examples/lite/cxx\_demo - >- 测试用例编码规范 - > 开发者测试用例原则上与特性代码编码规范保持一致,另外需要添加必要的用例描述信息,详见[•自测试用例模板](#li2069415903917)。 - >- 测试用例编译配置规范 - > 测试用例采用GN方式编译,配置遵循本开源项目的[编译指导](../quick-start/概述.md)。 - >- 测试用例模板 - > 详见测试demo用例:developertest/examples/lite/cxx\_demo/test/unittest/common/calc\_subtraction\_test.cpp - -2. 实现测试套执行过程需要的预处理操作和后处理操作,即实现SetUp和TearDown方法。 - - ``` - void CalcSubtractionTest::SetUpTestCase(void) - { - // step 1: input testsuite setup step - } - - void CalcSubtractionTest::TearDownTestCase(void) - { - // step 2: input testsuite teardown step - } - - void CalcSubtractionTest::SetUp(void) - { - // step 3: input testcase setup step - } - - void CalcSubtractionTest::TearDown(void) - { - // step 4: input testcase teardown step - } - ``` - -3. 针对被测对象的特性编写测试用例,以使用HWTEST\_F为例说明。 - - ``` - /** - * @tc.name: integer_sub_001 - * @tc.desc: Test Calculator - * @tc.type: FUNC - * @tc.require: AR00000000 SR00000000 - */ - HWTEST_F(CalcSubtractionTest, integer_sub_001, TestSize.Level1) - { - EXPECT_EQ(0, Subtraction(1, 0)); - } - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >- @tc.name:用例名称,对测试目的简要描述。 - >- @tc.desc:描述用例详细描述,包括测试目的、测试步骤、期望结果等。 - >- @tc.type:测试属性分类(FUNC、PERF、SECU、RELI)。 - >- @tc.require:需求编号或者issue编号,用来将修改与用例关联。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

序号

-

测试类型名称

-

缩写

-

测试类型描述

-

1

-

功能测试(functionality)

-

FUNC

-

验证软件各个功能满足功能设计与规格。

-

2

-

性能测试(performance)

-

PERF

-

验证软件是否满足性能设计指标。包含负载测试容量测试,压力测试等。

-

3

-

安全性测试(security)

-

SECU

-

验证软件在生命周期内符合安全需求定义和相关法规。

-

4

-

可靠性测试(reliability)

-

RELI

-

在规定的条件下,在规定的时间内,软件不引起系统失效的概率,这里也包含稳定性。

-
- -4. 编写用例编译GN文件,其中包括定义用例编译目标,添加编译配置依赖,源文件等,举例说明: - - 示例文件路径:test/developertest/examples/lite/cxx\_demo/test/unittest/common/BUILD.gn)。 - - ``` - import("//build/lite/config/test.gni") - - unittest("CalcSubTest") { - output_extension = "bin" - sources = [ - "calc_subtraction_test.cpp" - ] - include_dirs = [] - deps = [] - } - ``` - -5. 将用例编译目标添加到子系统编译配置中,保证用例随版本一起编译,举例说明: - 1. 支持hdc连接的设备,编译配置示例路径:test/developertest/examples/ohos.build。 - - ``` - { - "subsystem": "subsystem_examples", - "parts": { - "subsystem_examples": { - "module_list": [ - "//test/developertest/examples/detector:detector", - ... ... - ], - "test_list": [ - "//test/developertest/examples/detector/test:unittest", - ... ... - ] - }, - ... ... - } - ``` - - 2. 仅支持串口的设备,编译配置示例路径:test/developertest/examples/lite/BUILD.gn。 - - ``` - import("//build/lite/config/test.gni") - - subsystem_test("test") { - test_components = [] - if(ohos_kernel_type == "liteos_riscv") { - features += [ - ] - }else if(ohos_kernel_type == "liteos_a") { - test_components += [ - "//test/developertest/examples/lite/cxx_demo/test/unittest/common:CalcSubTest" - ] - } - } - ``` - - -6. 编写测试用例资源配置,当测试用例需要使用静态测试资源文件时使用该配置。 - 1. 在部件或者模块的test目录下创建resource目录。 - 2. 在resource目录下创建形态目录,如phone。 - 3. 在设备形态目录下创建一个以模块名命名的文件夹,如testmodule。 - 4. 在模块目录下创建一个ohos\_test.xml文件,文件内容格式如下: - - ``` - - - - - - - - ``` - - 5. 在测试用例的编译配置文件中定义resource\_config\_file,用来指定对应的资源文件ohos\_test.xml。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >如上资源文件功能:将resource目录下的test.txt文件通过hdc push命令推送到被测设备的/data/test/resource目录下。 - - -7. 以上步骤完成即完成测试用例编写,即可执行测试用例。 - - >![](public_sys-resources/icon-note.gif) **说明:** - >- 支持hdc连接的设备,测试用例支持单独编译。 - >- 仅支持串口连接的设备,在代码根路径下执行编译debug版本的命令,即可编译测试用例。 - > 测试用例用例的执行详见[测试平台使用](#section76401945124810)。 - - -## 开发实例 - -测试子系统代码仓提供了完整demo用例,demo用例路径:test/developertest/examples/。以一个减法运算方法编写测试用例举例说明: - -- 被测代码如下: - - ``` - static int Subtraction(int a, int b) - { - return a - b; - } - ``` - -- 测试用例代码如下: - - ``` - /** - * @tc.name: integer_sub_002 - * @tc.desc: Verify the Subtraction function. - * @tc.type: FUNC - * @tc.require: AR00000000 SR00000000 - */ - HWTEST_F(CalcSubtractionTest, integer_sub_002, TestSize.Level1) - { - EXPECT_EQ(1, Subtraction(2, 1)); - } - ``` - - -## 测试平台使用 - -1. (可选)安装xdevice组件。安装xdevice后,xdevice组件可以作为python的扩展包使用。 - - 打开xdevice安装目录:test/xdevice,执行如下命令: - - ``` - python setup.py install - ``` - - 安装成功提示如下: - - ``` - ... ... - Installed d:\programs\python37\lib\site-packages\xdevice-0.0.0-py3.7.egg - Processing dependencies for xdevice==0.0.0 - Searching for pyserial==3.4 - Best match: pyserial 3.4 - Processing pyserial-3.4-py3.7.egg - pyserial 3.4 is already the active version in easy-install.pth - Installing miniterm.py script to D:\Programs\Python37\Scripts - - Using d:\programs\python37\lib\site-packages\pyserial-3.4-py3.7.egg - Finished processing dependencies for xdevice==0.0.0 - ``` - -2. 修改developertest/config/user\_config.xml 文件配置developertest组件。 - 1. 测试框架通用配置。 - - \[build\] \# 配置测试用例的编译参数,例如: - - ``` - - false - false - true - ... ... - - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >测试用例的编译参数说明如下: - >example:是否编译测试用例示例,默认false。 - >version:是否编译测试版本,默认false。 - >testcase:是否编译测试用例,默认true。 - - 2. 支持hdc连接的被测设备。 - - \[device\] \# 配置标签为usb-hdc的环境信息,测试设备的IP地址和hdc映射的端口号,例如: - - ``` - - 192.168.1.1 - 9111 - - - ``` - - 3. 仅支持串口的被测设备。 - - \[board\_info\] \# 开发板配置信息,例如: - - ``` - - hispark - taurus - ipcamera - hb build - - ``` - - >![](public_sys-resources/icon-note.gif) **说明:** - >开发板配置信息如下: - >board\_series:开发板系列,默认hispark。 - >board\_type:开发板类型,默认taurus。 - >board\_product:目标产品,默认ipcamera。 - >build\_command:测试版本和用例的编译命令,默认hb build。 - - \[device\] \# 配置标签为ipcamera的串口信息,COM口和波特率,例如: - - ``` - - - COM1 - cmd - 115200 - 8 - 1 - 1 - - - ``` - - -3. (可选)修改developertest组件配置。如果测试用例已完成编译,可以直接指定测试用例的编译输出路径,测试平台执行用例时即不会重新编译测试用例。 - - 配置文件:config/user\_config.xml - - 1. \[test\_cases\] \# 指定测试用例的输出路径,编译输出目录,例如: - - ``` - - /home/opencode/out/release/tests - - ``` - - 2. \[NFS\] \# 被测设备仅支持串口时配置,指定NFS的映射路径,host\_dir为PC侧的NFS目录,board\_dir为板侧创建的目录,例如: - - ``` - - D:\nfs - user - - ``` - - -4. (可选)测试环境准备。当被测设备仅支持串口时,需要检查。 - - 系统镜像与文件系统已烧录进开发板,开发板上系统正常运行,在系统模式下,如使用shell登录时,设备提示符是“OHOS\#”。 - - 开发主机和开发板串口连接正常,网口连接正常。 - - 开发主机IP与开发板IP处在同一小网网段,相互可以ping通。 - - 开发主机侧创建空目录用于开发板通过NFS挂载测试用例,并且NFS服务启动正常。 - -5. (必选)启动测试平台,执行测试用例。 - - 启动测试框架,打开test/developertest目录,执行启动脚本。 - 1. Windows环境启动测试框架,执行如下脚本: - - ``` - start.bat - ``` - - 2. Linux环境启动测试框架。 - - ``` - ./start.sh - ``` - - - - 设备形态选择。 - - 根据实际的开发板选择,设备形态配置:developertest/config/framework\_config.xml。 - - - 执行测试指令。 - 1. 查询测试用例支持的子系统,模块,产品形态以及测试类型,使用show命令,示例如下: - - ``` - usage: - show productlist Querying Supported Product Forms - show typelist Querying the Supported Test Type - show subsystemlist Querying Supported Subsystems - show modulelist Querying Supported Modules - ``` - - 2. 执行测试指令,其中-t为必选,-ss和-tm为可选字段,示例如下: - - ``` - run -t ut -ss subsystem_examples -tm calculator - ``` - - 3. 参数说明:指定参数可以执行特定特性、模块对应的测试套。 - - ``` - usage: run [-h] [-p PRODUCTFORM] [-t [TESTTYPE [TESTTYPE ...]]] - [-ss SUBSYSTEM] [-tm TESTMODULE] [-ts TESTSUIT] - [-tc TESTCASE] [-tl TESTLEVEL] - - optional arguments: - -h, --help show this help message and exit - -p PRODUCTFORM, --productform PRODUCTFORM Specified product form - -t [TESTTYPE [TESTTYPE ...]], --testtype [TESTTYPE [TESTTYPE ...]] - Specify test type(UT,MST,ST,PERF,ALL) - -ss SUBSYSTEM, --subsystem SUBSYSTEM Specify test subsystem - -tm TESTMODULE, --testmodule TESTMODULE Specified test module - -ts TESTSUIT, --testsuite TESTSUIT Specify test suite - -tc TESTCASE, --testcase TESTCASE Specify test case - -tl TESTLEVEL, --testlevel TESTLEVEL Specify test level - ``` - - - - 测试框架帮助。 - - 帮助指令,用于查询测试平台支持哪些测试指令,如下: - - ``` - help - ``` - - - 退出自测试平台。 - - 退出自测试平台,使用如下命令退出测试平台,如下: - - ``` - quit - ``` - - -6. (必选)查看测试结果与日志,通过在测试平台中执行测试指令,即可在developertest/reports目录下生成测试日志和测试报告。 - - 测试用例的结果会直接显示在控制台上,执行一次的测试结果根路径如下: - - ``` - reports/xxxx-xx-xx-xx-xx-xx - ``` - - - 测试用例格式化结果目录如下: - - ``` - result/ - ``` - - - 测试用例日志目录如下: - - ``` - log/plan_log_xxxx-xx-xx-xx-xx-xx.log - ``` - - - 测试报告汇总: - - ``` - summary_report.html - ``` - - - 测试报告详情: - - ``` - details_report.html - ``` - - - - 测试平台日志目录如下: - - ``` - reports/platform_log_xxxx-xx-xx-xx-xx-xx.log - ``` - - - -## 包结构说明 - -开发者测试平台xdevice组件包结构说明,代码目录test/xdevice,详见下表所示: - -**表 4** xdevice组件包结构说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

功能描述

-

xdevice

-

测试平台基础组件。

-

xdevice/src/xdevice

-

基础测试框架源码。

-

xdevice/config

-

基础测试框架配置文件定义。

-

xdevice/src/xdevice/__main__.py

-

基础测试框架内部入口。

-

xdevice/src/xdevice/__init__.py

-

包依赖定义,插件依赖。

-

xdevice/src/xdevice/variables.py

-

全局变量定义。

-

xdevice/src/xdevice/_core/command

-

用例输入的命令行处理。

-

xdevice/src/xdevice/_core/config

-

基础测试框架的配置管理。

-

xdevice/src/xdevice/_core/environment

-

基础测试框架的环境管理,包括设备管理。

-

xdevice/src/xdevice/_core/executor

-

基础测试框架用例调度和分发。

-

xdevice/src/xdevice/_core/driver

-

基础测试框架测试执行器。

-

xdevice/src/xdevice/_core/resource

-

基础测试框架资源文件以及测试报告模板。

-

xdevice/src/xdevice/_core/testkit

-

基础测试框架公共操作,包括NFS文件系统挂载等。

-

xdevice/src/xdevice/_core/logger.py

-

基础测试框架日志管理。

-

xdevice/src/xdevice/_core/plugin.py

-

基础测试框架插件管理。

-

xdevice/src/xdevice/_core/interface.py

-

基础测试框架插件接口定义。

-

xdevice/setup.py

-

基础测试框架的安装脚本。

-

xdevice/run.bat

-

基础测试框架启动脚本(Windows)。

-

xdevice/run.sh

-

基础测试框架启动脚本(Linux)。

-
- -开发者测试平台developertest组件包结构说明,代码目录test/developertest,详见下表所示: - -**表 5** developertest组件包结构说明 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

名称

-

描述

-

developertest

-

开发测试框架。

-

developertest/src

-

测试框架源码。

-

developertest/src/core

-

测试执行器。

-

developertest/src/core/build

-

测试用例编译。

-

developertest/src/core/command

-

对用户输入的命令行处理。

-

developertest/src/core/config

-

测试框架配置管理。

-

developertest/src/core/driver

-

测试框架驱动执行器。

-

developertest/src/core/resource

-

测试框架配置文件。

-

developertest/src/core/testcase

-

测试用例管理。

-

developertest/src/core/common.py

-

测试框架公共操作。

-

developertest/src/core/constants.py

-

测试框架全局常量。

-

developertest/src/core/exception.py

-

测试框架异常定义。

-

developertest/src/core/utils.py

-

测试框架工具方法。

-

developertest/src/main

-

测试框架平台。

-

developertest/src/main/__main__.py

-

测试框架内部入口。

-

developertest/examples

-

测试框架demo用例。

-

developertest/third_party

-

测试框架依赖第三方组件适配。

-

developertest/BUILD.gn

-

测试子系统编译配置。

-

developertest/start.bat

-

开发者测试入口(Windows)。

-

developertest/start.sh

-

开发者测试入口(Linux)。

-
- diff --git "a/zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" "b/zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" deleted file mode 100755 index 14552d89af7b37c90cd9edbbc22f1d2d6c2b0bcb..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\224\250\346\210\267\347\250\213\345\272\217\346\241\206\346\236\266.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 用户程序框架 - -- **[概述](概述.md)** - -- **[搭建环境](搭建环境-2.md)** - -- **[开发指导](开发指导-3.md)** - -- **[开发实例](开发实例.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" "b/zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" deleted file mode 100755 index 3b86f53b9bc45e06e5cd20e684af73db06c88e77..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272.md" +++ /dev/null @@ -1,11 +0,0 @@ -# 相机 - -- **[相机开发概述](相机开发概述.md)** - -- **[拍照开发指导](拍照开发指导.md)** - -- **[录像开发指导](录像开发指导.md)** - -- **[预览开发指导](预览开发指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" deleted file mode 100755 index 65801b39bcc9ab160e7ad0d0133f46f330a67145..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\233\270\346\234\272\345\274\200\345\217\221\346\246\202\350\277\260.md" +++ /dev/null @@ -1,116 +0,0 @@ -# 相机开发概述 - -- [基本概念](#section175012297491) -- [运作机制](#section193961322175011) - -## 基本概念 - -相机是OpenHarmony多媒体进程提供的服务之一,提供了相机的录像、预览、拍照功能,支持多用户并发取流。 - -在进行应用的开发前,开发者应了解以下基本概念: - -- 视频帧 - - 视频流指的是将一系列图片数据按照固定时间间隔排列形成的数据流,每一张图片数据成为一帧,这样的一帧称为视频帧。 - -- 帧速率\(FPS: Frames Per Second\) - - 视频播放每秒钟刷新图片的速度,或是视频每秒的帧数,帧速率越高,视频的观感越流畅。 - -- 分辨率 - - 每一帧的图片信息都是由像素点组成的,分辨率描述了一张图片中像素点的个数。例如1920\*1080\(1080P\),是指图片宽1920像素,高1080像素。 - - -## 运作机制 - -- 多媒体服务进程 - - 多媒体服务作为系统服务,在系统启动时由Init进程拉起,并初始化和分配媒体硬件资源(内存/显示硬件/图像传感器/编解码器等)。初始化过程解析配置文件,确定了多媒体各个服务的能力和资源上限,通常由OEM厂商通过配置文件进行配置。相机服务在多媒体进程初始化时有以下配置项: - - - 内存池:所有媒体服务依赖于内存池中的内存轮转运行 - - 图像传感器:包括了传感器类型、分辨率、ISP等 - - 图像处理器:分辨率、码率、图像翻转等 - - 图像编码器:编码格式、码率、分辨率等 - - -- 关键类的解释 - - 应用通过持有下面4个类,配置和使用Camera的功能,包括了Camera类和它的三个异步回调类,三类回调分别对应了不同类型的异步处理场景,详见[表1](#table486418149411)。 - - **表 1** 关键类的解释 - - - - - - - - - - - - - - - - - - - - - - - - -

对象

-

用途

-

举例

-

Camera

-

对相机进行静态配置(通过配置类),触发相机基本功能

-

拍照/录像/预览

-

CameraDeviceCallback

-

处理相机硬件状态变化

-

可用/不可用

-

CameraStateCallback

-

处理camera自身状态变化

-

创建/释放

-

FrameStateCallback

-

处理帧状态的变化

-

拍照开始和结束/帧率发生变化

-
- -- 流的传递 - - Surface是多媒体传递音视频的基本数据结构,Camera一般作为Surface中数据的生产者,在不同的场景下有特定的消费者。 - - 相机的预览和录像输出均为视频流,拍照输出为图像帧,二者均通过Surface类进行传递。Surface类可以屏蔽进程内/跨进程的场景,进行多媒体信息流的传递。 - - 以录像为例,用户首先创建Recorder实例,并从Recorder中获取对应Surface,再将此Surface传递给Camera实例,此时Camera将作为生产者向Surface注入视频流,而Recorder作为消费者从Surface中取出视频流进行保存,用户的行为类似桥接,把二者通过Surface连接起来。 - - 类似的,用户也可以自行创建Surface传递给Camera实例,并实现消费者逻辑(例如通过网络传输视频流,或是将拍照的帧数据保存成图片文件)。 - - 图形图像模块也通过Surface从Camera获取流资源,具体步骤详见[图形图像开发指导](图形图像概述.md)。 - -- 相机运行流程 - 1. Camera创建流程 - - 本进程通过CameraManager创建Camera实例,并从服务端绑定camera设备,创建成功后异步通知developer。类之间的时序图如下: - - **图 1** Camera创建时序图 - - - ![](figures/zh-cn_image_0000001054101094.png) - - - 1. Camera录像/预览流程 - - 开发者首先通过CameraKit创建Camera,然后FrameConfig类对录像或者预览帧属性进行配置。录像/预览时序如下: - - **图 2** Camera录像/预览时序图 - - - ![](figures/zh-cn_image_0000001054421113.png) - - - diff --git "a/zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" "b/zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" deleted file mode 100644 index 5c490a8cfbdc0458b160ce6b284ecd2582f2faad..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\240\224\345\217\221\345\267\245\345\205\267\351\223\276.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 研发工具链 - -- **[bytrace使用指导](bytrace使用指导.md)** - -- **[hdc\_std 使用指导](hdc_std-使用指导.md)** - -- **[hdc\_std常见问题](hdc_std常见问题.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" deleted file mode 100755 index b59e4b2a18f9ef3c093e85b47b97126043b59744..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272.md" +++ /dev/null @@ -1,7 +0,0 @@ -# 编译构建 - -- **[轻量和小型系统编译构建指导](轻量和小型系统编译构建指导.md)** - -- **[标准系统编译构建指导](标准系统编译构建指导.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" deleted file mode 100755 index 661ff10cf6bdcb8d16510560214c53e124813a6d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274-1.md" +++ /dev/null @@ -1,176 +0,0 @@ -# 编译构建使用指导 - -- [目录结构](#section56731811102915) -- [编译](#section1069873833818) - - [编译命令](#section2740182614395) - -- [开发步骤](#section4207112818418) - -## 目录结构 - -``` -/build # 编译构建主目录 -├── config # 编译相关的配置项 -├── core -│ └── gn # 编译入口BUILD.gn配置 -├── loader # 各个组件配置加载、模板生成 -├── ohos # OpenHarmony编译打包流程配置 -│ ├── kits # kits编译打包模板和处理流程 -│ ├── ndk # ndk模板和处理流程 -│ ├── notice # notice模板和处理流程 -│ ├── packages # 版本打包模板和处理流程 -│ ├── sa_profile # sa模板和处理流程 -│ ├── sdk # sdk模板和处理流程,包括sdk中包含的模块配置 -│ └── testfwk # 测试相关的处理 -├── scripts # 编译相关的python脚本 -├── templates # c/c++编译模板定义 -└── toolchain # 编译工具链配置 -``` - -## 编译 - -### 编译命令 - -- 代码根目录下执行全量版本的编译命令: - - ``` - ./build.sh --product-name {product_name} - ``` - - \{product\_name\}为当前版本支持的平台。比如:Hi3516DV300等。 - - 编译完成后,结果镜像保存在 out/ohos-arm-release/packages/phone/images/ 目录下。 - -- 编译命令支持选项: - - ``` - --product-name # 必须 编译的产品名称,如:Hi3516DV300 - --build-target # 可选 指定编译目标,可以指定多个 - --gn-args # 可选 gn参数,支持指定多个 - --ccache # 可选 编译使用ccache,需要本地安装ccache - ``` - - -## 开发步骤 - -1. 添加组件。 - - 本节以添加一个自定义的组件为例,描述如何编译组件,编译库、编译可执行文件等。 - - 示例组件partA由feature1、feature2和feature3组成,feature1的编译目标为一个动态库,feature2的目标为一个可执行程序,feature3的目标为一个etc配置文件。 - - 示例组件partA的配置需要添加到一个子系统中,本次示例将添加到subsystem\_examples子系统中(subsystem\_examples子系统定义在test/examples/目录)。 - - 示例组件partA的完整目录结构如下: - - ``` - test/examples/partA - ├── feature1 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld1.h - │ └── src - │ └── helloworld1.cpp - ├── feature2 - │ ├── BUILD.gn - │ ├── include - │ │ └── helloworld2.h - │ └── src - │ └── helloworld2.cpp - └── feature3 - ├── BUILD.gn - └── src - └── config.conf - ``` - - 示例1:编写动态库gn脚本test/examples/partA/feature1/BUILD.gn,示例如下: - - ``` - config("helloworld_lib_config") { - include_dirs = [ "include" ] - } - - ohos_shared_library("helloworld_lib") { - sources = [ - "include/helloworld1.h", - "src/helloworld1.cpp", - ] - public_configs = [ ":helloworld_lib_config" ] - part_name = "partA" - } - ``` - - 示例2:编写可执行文件gn脚本test/examples/partA/feature2/BUILD.gn,示例如下: - - ``` - ohos_executable("helloworld_bin") { - sources = [ - "src/helloworld2.cpp" - ] - include_dirs = [ "include" ] - deps = [ # 依赖组件内模块 - "../feature1:helloworld_lib" - ] - external_deps = [ "partB:module1" ] # (可选)如果有跨组件的依赖,格式为“组件名:模块名” - install_enable = true # 可执行程序缺省不安装,需要安装时需要指定 - part_name = "partA" - } - ``` - - 示例3:编写etc模块gn脚本test/examples/partA/feature3/BUILD.gn,示例如下: - - ``` - ohos_prebuilt_etc("feature3_etc") { - source = "src/config.conf" - relative_install_dir = "init" #可选,模块安装相对路径,相对于默认安装路径;默认在/system/etc目录 - part_name = "partA" - } - ``` - - 示例4:在子系统的ohos.build中添加组件配置:test/examples/ohos.build。每个子系统有一个ohos.build配置文件,在子系统的根目录下。示例如下: - - ``` - "partA": { - "module_list": [ - "//test/examples/partA/feature1:helloworld_lib", - "//test/examples/partA/feature2:helloworld_bin", - "//test/examples/partA/feature3:feature3_etc", - ], - "inner_kits": [ - - ], - "system_kits": [ - - ], - "test_list": [ - - ] - } - ``` - - 一个组件包含module\_list、inner\_kits、system\_kits、test\_list四个部分的声明,其中: - - - module\_list:组件所包含的模块列表; - - inner\_kits:组件提供给其它组件调用的接口,其他组件的模块可以在external\_deps中添加依赖的模块; - - system\_kits:组件提供给开发者开发应用的接口; - - test\_list:组件中对应模块的测试用例; - -2. 将组件添加到产品配置中。 - - 在产品的配置中添加组件,产品对应的配置文件:productdefine/common/products/\{product-name\}.json。 - - 在产品配置文件中添加 "subsystem\_examples:partA",表示该产品中会编译并打包partA到版本中。 - -3. 编译。 - - 以编译Hi3516DV300为例,编译命令如下: - - ``` - ./build.sh --product-name Hi3516DV300 --ccache - ``` - -4. 编译输出。 - - 编译所生成的文件都归档在out/ohos-arm-release/目录下,结果镜像输出在 out/ohos-arm-release/packages/phone/images/ 目录下。 - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" deleted file mode 100755 index 8d5f276817760d9b28e9bee264507fc2e6c6b533..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\344\275\277\347\224\250\346\214\207\345\257\274.md" +++ /dev/null @@ -1,431 +0,0 @@ -# 编译构建使用指导 - -- [前提条件](#section13333171022312) -- [hb命令行工具使用](#section477242204612) -- [新增组件](#section4207112818418) -- [新增芯片解决方案](#section2737141421917) -- [新增产品解决方案](#section720881917199) - -## 前提条件 - -开发环境需安装gn、ninja构建工具、python 3.7.4及以上和hb。安装方法请见[搭建系统基础环境](../quick-start/搭建系统环境.md)。 - -## hb命令行工具使用 - -hb是OpenHarmony的命令行工具,用来执行编译命令。以下对hb的常用命令进行说明。 - -1. **hb set** - - ``` - hb set -h - usage: hb set [-h] [-root [ROOT_PATH]] [-p] - - optional arguments: - -h, --help show this help message and exit - -root [ROOT_PATH], --root_path [ROOT_PATH] - Set OHOS root path - -p, --product Set OHOS board and kernel - ``` - - - hb set 后无参数,进入默认设置流程 - - hb set -root dir可直接设置代码根目录 - - hb set -p设置要编译的产品 - -2. **hb env** - - 查看当前设置信息 - - ``` - hb env - [OHOS INFO] root path: xxx - [OHOS INFO] board: hispark_taurus - [OHOS INFO] kernel: liteos - [OHOS INFO] product: ipcamera - [OHOS INFO] product path: xxx/vendor/hisilicon/ipcamera - [OHOS INFO] device path: xxx/device/hisilicon/hispark_taurus/sdk_linux_4.19 - ``` - -3. **hb build** - - ``` - hb build -h - usage: hb build [-h] [-b BUILD_TYPE] [-c COMPILER] [-t [TEST [TEST ...]]] - [--dmverity] [-p PRODUCT] [-f] [-n] - [component [component ...]] - - positional arguments: - component name of the component - - optional arguments: - -h, --help show this help message and exit - -b BUILD_TYPE, --build_type BUILD_TYPE - release or debug version - -t [TEST [TEST ...]], --test [TEST [TEST ...]] - compile test suit - --dmverity Enable dmverity - -p PRODUCT, --product PRODUCT - build a specified product with - {product_name}@{company}, eg: ipcamera@hisilcon - -f, --full full code compilation - -T [TARGET [TARGET ...]], --target [TARGET [TARGET ...]] - Compile single target - ``` - - - hb build后无参数,会按照设置好的代码路径、产品进行编译,编译选项使用与之前保持一致。-f 选项将删除当前产品所有编译产品,等同于hb clean + hb build. - - hb build \{component\_name\}:基于设置好的产品对应的单板、内核,单独编译组件(e.g.:hb build kv\_store\)。 - - hb build -p ipcamera@hisilicon:免set编译产品,该命令可以跳过set步骤,直接编译产品。 - - 在device/device\_company/board下单独执行hb build会进入内核选择界面,选择完成后会根据当前路径的单板、选择的内核编译出仅包含内核、驱动的镜像。 - -4. **hb clean** - - 清除out目录对应产品的编译产物,仅保留args.gn、build.log。清除指定路径可输入路径参数:hb clean out/board/product,默认将清除当前hb set的产品对应out路径。 - - ``` - hb clean - usage: hb clean [-h] [out_path] - - positional arguments: - out_path clean a specified path. - - optional arguments: - -h, --help show this help message and exit - ``` - - -## 新增组件 - -本小节介绍如何新增一个组件,首先确定组件归属的子系统和组件名称,然后按如下步骤新增: - -1. 源码开发完成后,添加组件编译脚本。 - - 以编译组件hello\_world可执行文件为例,applications/sample/hello\_world/BUILD.gn可以写为: - - ``` - executable("hello_world") { - include_dirs = [ - "include", - ] - sources = [ - "src/hello_world.c" - ] - } - ``` - - 如上编译脚本,可编译出一个可在OpenHarmony上运行的名为hello\_world的可执行文件。 - - 单独编译该组件,hb set任意选择一款产品,然后使用-T选项单独编译组件: - - ``` - hb build -f -T //applications/sample/hello_world - ``` - - 组件在开发板上功能验证完成后,可按步骤2\~5将组件配置到产品中。 - -2. 添加组件描述。 - - 组件描述位于build/lite/components下,新增的组件需加入对应子系统的json文件中。一个组件描述必选的字段有: - - - component:组件名称。 - - description:组件的一句话功能描述。 - - optional:组件是否为系统可选。 - - dirs:组件源码路径。 - - targets:组件编译入口。 - - 以将hello\_world组件加入应用子系统为例,在applications.json中添加hello\_world对象: - - ``` - { - "components": [ - { - "component": "hello_world", - "description": "Hello world.", - "optional": "true", - "dirs": [ - "applications/sample/hello_world" - ], - "targets": [ - "//applications/sample/hello_world" - ] - }, - ... - ] - } - ``` - -3. 将组件配置到产品。 - - 产品的配置文件config.json位于位于vendor/company/product/下,产品配置文件需包含产品名称、OpenHarmony版本号、device厂商、开发板、内核类型、内核版本号,以及配置的子系统和组件。以将hello\_world组件加入产品配置文件my\_product.json中为例,加入hello\_wolrd对象: - - ``` - { - "product_name": "hello_world_test", - "ohos_version": "OpenHarmony 1.0", - "device_company": "hisilicon", - "board": "hispark_taurus", - "kernel_type": "liteos_a", - "kernel_version": "1.0.0", - "subsystems": [ - { - "subsystem": "applications", - "components": [ - { "component": "hello_world", "features":[] } - ] - }, - ... - ] - } - ``` - -4. 编译产品。 - - 1. 代码根目录输入hb set选择对应产品。 - - 2. 执行hb build。 - - -## 新增芯片解决方案 - -编译构建支持添加新的芯片解决方案厂商,具体步骤如下: - -1. 创建芯片解决方案目录。 - - 按照[芯片解决方案配置规则](编译构建概述.md#section1625463413327)创建目录,以芯片厂商realtek的“rtl8720“开发板为例, 在代码根目录执行: - - ``` - mkdir -p device/realtek/rtl8720 - ``` - -2. 创建内核适配目录,并编写开发板编译配置config.gni文件。 - - 以realtek的“rtl8720“开发板的liteos\_m适配为例,device/realtek/rtl8720/liteos\_a/config.gni的内容如下: - - ``` - # Kernel type, e.g. "linux", "liteos_a", "liteos_m". - kernel_type = "liteos_a" - - # Kernel version. - kernel_version = "3.0.0" - - # Board CPU type, e.g. "cortex-a7", "riscv32". - board_cpu = "real-m300" - - # Board arch, e.g. "armv7-a", "rv32imac". - board_arch = "" - - # Toolchain name used for system compiling. - # E.g. gcc-arm-none-eabi, arm-linux-harmonyeabi-gcc, ohos-clang, riscv32-unknown-elf. - # Note: The default toolchain is "ohos-clang". It's not mandatory if you use the default toochain. - board_toolchain = "gcc-arm-none-eabi" - - # The toolchain path instatlled, it's not mandatory if you have added toolchian path to your ~/.bashrc. - board_toolchain_path = - rebase_path("//prebuilts/gcc/linux-x86/arm/gcc-arm-none-eabi/bin", - root_build_dir) - - # Compiler prefix. - board_toolchain_prefix = "gcc-arm-none-eabi-" - - # Compiler type, "gcc" or "clang". - board_toolchain_type = "gcc" - - # Board related common compile flags. - board_cflags = [] - board_cxx_flags = [] - board_ld_flags = [] - ``` - -3. 编写编译脚本。 - - 在开发板目录下创建BUILD.gn,target名称应与开发板名称一致。以realtek的rtl8720开发板为例,device/realtek/rtl8720/BUILD.gn内容可以是: - - ``` - group("rtl8720") { # target类型也可以shared_library, static_library, executable - # 具体内容 - ...... - } - ``` - -4. 编译芯片解决方案。 - - 在开发板目录下执行hb build,即可启动芯片解决方案的编译。 - - -## 新增产品解决方案 - -编译构建支持芯片解决方案和组件的灵活拼装,形成定制化的产品解决方案。具体步骤如下: - -1. 创建产品目录 - - 按照[产品解决方案配置规则](编译构建概述.md#section1625463413327)创建产品目录,以基于“rtl8720“开发板的wifiiot模组为例,在代码根目录执行: - - ``` - mkdir -p vendor/my_company/wifiiot - ``` - -2. 拼装产品 - - 在新建的产品目录下新建config.json文件,以步骤1中的wifiiot为例,vendor/my\_company/wifiiot/config.json可以是: - - ``` - { - "product_name": "wifiiot", # 产品名称 - "ohos_version": "OpenHarmony 1.0", # 使用的OS版本 - "device_company": "realtek", # 芯片解决方案厂商名称 - "board": "rtl8720", # 开发板名称 - "kernel_type": "liteos_m", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "kernel", # 选择的子系统 - "components": [ - { "component": "liteos_m", "features":[] } # 选择的组件和组件特性 - ] - }, - ... - { - 更多子系统和组件 - } - ] - } - ``` - - 注意:编译构建系统编译前会对device\_company,board,kernel\_type,kernel\_version、subsystem、component字段进行有效性检查,其中device\_company,board,kernel\_type,kernel\_version应与已知的芯片解决方案匹配,subsystem、component应与build/lite/components下的组件描述匹配。 - -3. 适配OS接口 - - 在产品目录下创建hals目录,并将产品解决方案对OS适配的源码和编译脚本放入该目录下。 - -4. 配置系统服务 - - 在产品目录下创建init\_configs目录,并在init\_configs目录下创建init.cfg文件,按需配置要启动的系统服务。 - -5. 配置init进程(仅linux内核需要) - - 在init\_configs目录下创建etc目录,然后在etc下创建init.d文件夹和fstab文件。最后按产品需求在init.d文件下创建并编辑rcS文件和Sxxx文件。 - -6. 配置文件系统镜像(可选,仅支持文件系统的开发板需要) - - 在产品目录下创建fs.yml文件。fs.yml需按产品实际情况配置,一个典型的fs.yml文件如下: - - ``` - - - fs_dir_name: rootfs # 镜像的名称 - fs_dirs: - - - # 将编译生成的out/my_board/my_product/bin目录下的文件拷贝到rootfs/bin中,并忽略测试bin - source_dir: bin - target_dir: bin - ignore_files: - - Test.bin - - TestSuite.bin - - - # 将编译生成的out/my_board/my_product/libs目录下的文件拷贝到rootfs/lib中,忽略所有.a文件,并设置文件和文件夹的权限为644和755 - source_dir: libs - target_dir: lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: usr/lib - target_dir: usr/lib - ignore_files: - - .a - dir_mode: 755 - file_mode: 644 - - - source_dir: config - target_dir: etc - - - source_dir: system - target_dir: system - - - source_dir: sbin - target_dir: sbin - - - source_dir: usr/bin - target_dir: usr/bin - - - source_dir: usr/sbin - target_dir: usr/sbin - - - # 创建一个proc空目录 - target_dir: proc - - - target_dir: mnt - - - target_dir: opt - - - target_dir: tmp - - - target_dir: var - - - target_dir: sys - - - source_dir: etc - target_dir: etc - - - source_dir: vendor - target_dir: vendor - - - target_dir: storage - - fs_filemode: - - - file_dir: lib/ld-uClibc-0.9.33.2.so - file_mode: 555 - - - file_dir: lib/ld-2.24.so - file_mode: 555 - - - file_dir: etc/init.cfg - file_mode: 400 - fs_symlink: - - - # 在rootfs/lib下创建软连接ld-musl-arm.so.1 -> libc.so - source: libc.so - link_name: ${fs_dir}/lib/ld-musl-arm.so.1 - - - source: mksh - link_name: ${fs_dir}/bin/sh - - - source: mksh - link_name: ${fs_dir}/bin/shell - fs_make_cmd: - # 使用脚本将rootfs制作为ext4格式的image - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - - fs_dir_name: userfs - fs_dirs: - - - source_dir: storage/etc - target_dir: etc - - - source_dir: data - target_dir: data - fs_make_cmd: - - ${root_path}/build/lite/make_rootfs/rootfsimg_linux.sh ${fs_dir} ext4 - - ``` - -7. 编写编译脚本 - - 在产品目录下创建BUILD.gn文件,按产品实际情况编写脚本。以步骤1中的wifiiot为例,BUILD.gn示例如下: - - ``` - group("wifiiot") { # target名称与产品名一致 - deps = [] - # 拷贝init配置 - deps += [ "init_configs" ] - # 将hals加入编译 - deps += [ "hals" ] - # 其他 - ...... - } - ``` - -8. 编译产品。 - - 在代码根目录执行hb set按提示选择新增的产品,然后执行hb build即可启动编译。 - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" deleted file mode 100755 index ca00b2428542c6024ff6fa79649c5814646cfd28..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\345\270\270\350\247\201\351\227\256\351\242\230.md" +++ /dev/null @@ -1,121 +0,0 @@ -# 编译构建常见问题 - -- [由于ninja版本问题导致编译失败](#section1019152312222) -- [由于ncurses库缺失导致编译失败](#section21449422618) -- [由于未安装mcopy导致编译失败](#section12477184992615) -- [由于权限问题导致编译失败](#section178451337202716) -- [由于未安装Crypto导致编译失败](#section1241481172819) -- [由于编译环境为shell导致编译失败](#section3691222152919) - -## 由于ninja版本问题导致编译失败 - -- **现象描述:** - - 编译失败,提示“usr/sbin/ninja: invalid option -- w”。 - -- **可能原因:** - - 编译环境中ninja版本太低,不支持--w选项。 - -- **解决办法:** - - 卸载环境中ninja和gn,按照HarmonyOS官网[获取工具](../get-code/获取工具.md)。 - - -## 由于ncurses库缺失导致编译失败 - -- **现象描述:** - - 编译失败,提示“/usr/bin/ld: cannot find -lncurses”。 - -- **可能原因:** - - 编译环境ncurses库缺失。 - -- **解决办法:** - - ``` - sudo apt-get install lib32ncurses5-dev - ``` - - -## 由于未安装mcopy导致编译失败 - -- **现象描述:** - - ​编译失败,提示“line 77: mcopy: command not found”。 - -- **可能原因:** - - 编译环境未安装mcopy。 - -- **解决办法:** - - ``` - ​sudo apt-get install dosfstools mtools - ``` - - -## 由于权限问题导致编译失败 - -- **现象描述:** - - 编译失败,提示“riscv32-unknown-elf-gcc: error trying to exec 'cc1': execvp: No such file or directory”。 - -- ​**可能原因:** - - 当前用户对riscv编译器路径下的文件访问权限不够。 - -- ​**解决办法:** - 1. 查询gcc\_riscv32所在目录。 - - ``` - which riscv32-unknown-elf-gcc - ``` - - 2. 使用chmod命令修改目录权限为755。 - - -## 由于未安装Crypto导致编译失败 - -- **现象描述:** - - 编译失败,提示“No module named 'Crypto'”。 - -- **可能原因:** - - python3未安装Crypto。 - -- **解决办法:** - 1. 查询Python版本号。 - - ``` - python3 --version - ``` - - 2. 需使用python3.7以上版本,然后安装pycryptodome。 - - ``` - sudo pip3 install pycryptodome - ``` - - - -## 由于编译环境为shell导致编译失败 - -- **现象描述:** - - 编译失败:“xx.sh \[: xx unexpected operator”。 - -- **可能原因:** - - 编译环境shell不是bash。 - -- **解决办法:** - - ``` - sudo rm -rf /bin/sh - sudo ln -s /bin/bash /bin/sh - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" deleted file mode 100755 index 1bd7dd28d93785765d46a6c7585280e1fe6d390a..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260-0.md" +++ /dev/null @@ -1,58 +0,0 @@ -# 编译构建概述 - -- [基本概念](#section175012297491) -- [运作机制](#section193961322175011) -- [约束与限制](#section2029921310472) - -编译构建子系统提供了一个基于gn和ninja的编译构建框架。主要提供以下功能: - -- 构建不同芯片平台的产品。如:Hi3516DV300平台。 - -- 根据产品配置可以按照组件组装打包产品需要的能力。 - -## 基本概念 - -在了解编译构建子系统的能力前,应了解如下基本概念: - -- 平台 - - 开发板和内核的组合,不同平台支持的子系统和组件不同。 - -- 子系统 - - OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。子系统是一个逻辑概念,它具体由对应的组件构成。 - -- 组件 - - 对子系统的进一步拆分,可复用的软件单元,它包含源码、配置文件、资源文件和编译脚本;能独立构建,以二进制方式集成,具备独立验证能力的二进制单元。 - -- gn - - Generate ninja的缩写,用于产生ninja文件。 - -- ninja - - ninja是一个专注于速度的小型构建系统。 - - -## 运作机制 - -OpenHarmony侧的编译构建流程主要包括编译命令行解析,调用gn,执行ninja: - -- 命令行解析:解析待编译的产品名称,加载相关配置。 -- 调用gn: 根据命令行解析的产品名称和编译类型,配置编译工具链和全局的编译选项。 -- 执行ninja:启动编译并生成对应的产品版本。 - -## 约束与限制 - -- 需按照[源码获取](../get-code/源码获取.md)指导下载全量源码(采用方式三获取)。 -- 编译环境需要Ubuntu18.04及以上版本。 -- 安装编译所需的程序包。 - - 安装命令: - - ``` - sudo apt-get install binutils git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev ccache libgl1-mesa-dev libxml2-utils xsltproc unzip m4 - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" "b/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" deleted file mode 100755 index 83423cbe1c9b0d7f4bfd6bae3124b490c43cd6c8..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\347\274\226\350\257\221\346\236\204\345\273\272\346\246\202\350\277\260.md" +++ /dev/null @@ -1,381 +0,0 @@ -# 编译构建概述 - -- [基本概念](#section175012297491) -- [目录结构](#section3267040205617) -- [构建流程](#section193961322175011) -- [组件、芯片解决方案和产品解决方案配置规则](#section1625463413327) - -一个基于gn和ninja的构建系统,以支持OpenHarmony组件化开发为目标,提供以下基本功能: - -- 支持按组件拼装产品并编译。 - -- 独立构建芯片解决方案厂商源码。 -- 独立构建单个组件。 - -## 基本概念 - -在使用编译构建子系统前,应了解如下基本概念: - -- 子系统 - - 子系统是一个逻辑概念,它由一个或多个具体的组件组成。OpenHarmony整体遵从分层设计,从下向上依次为:内核层、系统服务层、框架层和应用层。系统功能按照“系统 \> 子系统 \> 组件”逐级展开,在多设备部署场景下,支持根据实际需求裁剪某些非必要的子系统或组件。 - - -- 组件 - - 系统最小的可复用、可配置、可裁剪的功能单元。组件具备目录独立可并行开发、可独立编译、可独立测试的特征。 - -- gn - - Generate ninja的缩写,用于产生ninja文件。 - -- ninja - - ninja是一个专注于速度的小型构建系统。 - -- hb - - OpenHarmony的命令行工具,用来执行编译命令。 - - -## 目录结构 - -``` -build/lite -├── components # 组件描述文件 -├── figures # readme中的图片 -├── hb # hb pip安装包源码 -├── make_rootfs # 文件系统镜像制作脚本 -├── config # 编译配置项 -│ ├── component # 组件相关的模板定义 -│ ├── kernel # 内核相关的编译配置 -│ └── subsystem # 子系统编译配置 -├── platform # ld脚本 -├── testfwk # 测试编译框架 -└── toolchain # 编译工具链配置,包括:编译器路径、编译选项、链接选项等 -``` - -## 构建流程 - -编译构建流程如[图1 ](#fig9744112715161)所示,主要分设置和编译两步: - -**图 1** 编译构建流程 -![](figures/编译构建流程.jpg "编译构建流程") - -1. hb set: 设置OpenHarmony源码目录和要编译的产品。 -2. hb build: 编译产品、开发板或者组件。编译主要过程如下: - - 读取编译配置:根据产品选择的开发板,读取开发板config.gni文件内容,主要包括编译工具链、编译链接命令和选项等。 - - 调用gn:调用gn gen命令,读取产品配置生成产品解决方案out目录和ninja文件。 - - 调用ninja:调用ninja -C out/board/product启动编译。 - - 系统镜像打包:将组件编译产物打包,设置文件属性和权限,制作文件系统镜像。 - - -## 组件、芯片解决方案和产品解决方案配置规则 - -为了实现芯片解决方案、产品解决方案与OpenHarmony是解耦的、可插拔的,组件、芯片解决方案和产品解决方案的路径、目录树和配置需遵循一定的规则,具体如下: - -- **组件** - -组件源码路径命名规则为:_\{领域\}/\{子系统\}/\{组件\}_,组件目录树规则如下: - -``` -component -├── interfaces -│ ├── innerkits # 系统内接口,组件间使用 -│ └── kits # 应用接口,应用开发者使用 -├── frameworks # framework实现 -├── services # service实现 -└── BUILD.gn # 组件编译脚本 -``` - -组件的名称、源码路径、功能简介、是否必选、编译目标、RAM、ROM、编译输出、已适配的内核、可配置的特性和依赖等属性定义在build/lite/components目录下对应子系统的json文件中,新增组件时需要在对应子系统json文件中添加相应的组件定义。产品所配置的组件必须在某个子系统中被定义过,否则会校验失败。 - -以泛sensor子系统的sensor服务组件为例,组件属性定义描述文件字段说明如下: - -``` -{ - "components": [ - { - "component": "sensor_lite", # 组件名称 - "description": "Sensor services", # 组件一句话功能描述 - "optional": "true", # 组件是否为最小系统必选 - "dirs": [ # 组件源码路径 - "base/sensors/sensor_lite" - ], - "targets": [ # 组件编译入口 - "//base/sensors/sensor_lite/services:sensor_service" - ], - "rom": "92KB", # 组件ROM值 - "ram": "~200KB", # 组件RAM估值 - "output": [ "libsensor_frameworks.so" ], # 组件编译输出 - "adapted_kernel": [ "liteos_a" ], # 组件已适配的内核 - "features": [], # 组件可配置的特性 - "deps": { - "components": [ # 组件依赖的其他组件 - "samgr_lite", - "ipc_lite" - - ], - "third_party": [ # 组件依赖的三方开源软件 - "bounds_checking_function" - ] - } - } - ] -} -``` - -组件的编译脚本语言为gn,gn的基本用法请见[gn快速入门](https://gn.googlesource.com/gn/+/master/docs/quick_start.md)。组件即为gn定义的编译目标,可以为静态库、动态库、可执行文件或group。组件BUILD.gn的编写建议如下: - -1)编译目标名称与组件一致。 - -2)组件对外可配置的特性变量需声明在该组件BUILD.gn中,特性变量命名规则:ohos\_\{subsystem\}\_\{component\}\_\{feature\}。特性在组件描述中也需要同步定义,在产品配置文件config.json中按需配置。 - -3)宏定义规则:OHOS\_\{SUBSYSTEM\}\_\{COMPONENT\}\_\{FEATURE\} - -以图形的UI组件为例,foundation/graphic/ui/BUILD.gn文件如下: - -``` - # 声明组件可配置的特性 - declare_args() { - enable_ohos_graphic_ui_animator = false # 动效特性开关 - ohos_ohos_graphic_ui_font = "vector" # 可配置的字体类型,vector或者bitmap - } - - # 组件基础功能 - shared_library("base") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - } - - # 仅在animator开启时编译 - if(enable_ohos_graphic_ui_animator ) { - shared_library("animator") { - sources = [ - ...... - ] - include_dirs = [ - ...... - ] - deps = [ :base ] - } - } - ...... - # target名称建议与组件名称一致, 组件target类型可以是executable(bin文件),shared_library(动态库.so),static_library(静态库.a),group等等 - executable("ui") { - deps = [ - ":base" - ] - - # animator特性由产品配置 - if(enable_ohos_graphic_ui_animator ) { - deps += [ - "animator" - ] - } - } -``` - -- **芯片解决方案** - -芯片解决方案是指基于某款开发板的完整解决方案,包含驱动、设备侧接口适配、开发板sdk等。芯片解决方案是一个特殊的组件,源码路径规则为:_device/\{芯片解决方案厂商\}/\{开发板\}_。芯片解决方案组件会随产品选择的开发板默认编译。芯片解决方案目录树规则如下: - -``` -device -└── company # 芯片解决方案厂商 - └── board # 开发板名称 - ├── BUILD.gn # 编译脚本 - ├── hals # OS南向接口适配 - ├── linux # 可选,linux内核版本 - │ └── config.gni # linux版本编译配置 - └── liteos_a # 可选,liteos内核版本 - └── config.gni # liteos_a版本编译配置 -``` - -config.gni为开发板编译相关的配置。编译时会采用该配置文件中的参数选择编译相应的OS组件,编译阶段系统全局可见。关键字段介绍如下: - -``` -kernel_type: 开发板使用的内核类型,例如:“liteos_a”, “liteos_m”, “linux”。 -kernel_version: 开发使用的内核版本,例如:“4.19”。 -board_cpu: 开发板CPU类型,例如:“cortex-a7”, “riscv32”。 -board_arch: 开发芯片arch, 例如: “armv7-a”, “rv32imac”。 -board_toolchain: 开发板自定义的编译工具链名称,例如:“gcc-arm-none-eabi”。若为空,则使用默认为ohos-clang。 -board_toolchain_prefix:编译工具链前缀,例如:“gcc-arm-none-eabi”。 -board_toolchain_type: 编译工具链类型,目前支持gcc和clang。例如:“gcc” ,“clang”。 -board_cflags: 开发板配置的c文件编译选项。 -board_cxx_flags: 开发板配置的cpp文件编译选项。 -board_ld_flags: 开发板配置的链接选项。 -``` - -- **产品解决方案** - -产品解决方案为基于开发板的完整产品,主要包含产品对OS的适配、组件拼装配置、启动配置和文件系统配置等。源码路径规则为:_vendor/\{产品解决方案厂商\}/\{产品名称\}。_产品解决方案也是一个特殊的组件,目录树规则如下: - -``` -vendor -└── company # 产品解决方案厂商 - ├── product # 产品名称 - │ ├── init_configs - │ │ ├── etc # init进程启动配置(可选,仅linux内核需要) - │ │ └── init.cfg # 系统服务启动配置 - │ ├── hals # 产品解决方案OS适配 - │ ├── BUILD.gn # 产品编译脚本 - │ └── config.json # 产品配置文件 - │ └── fs.yml # 文件系统打包配置 - └── ...... -``` - -新增产品须按如上的规则创建目录和文件,编译构建系统将按该规则扫描已配置的产品。关键的目录和文件详细介绍如下: - -1. vendor/company/product/init\_configs/etc - - 该文件夹中包含rcS脚本,Sxxx脚本和fstab脚本,init进程在启动系统服务之前执行这些脚本。执行的流程为“rcS-\>fstab-\>S00-xxx“,Sxxx脚本中的内容与开发板和产品需要有关,主要包括设备节点的创建、创建目录、扫描设备节点、修改文件权限等等。这些文件在产品编译的BUILD.gn中按需拷贝到产品out目录中,最终打包到rootfs镜像中。 - -2. vendor/company/product/init\_configs/init.cfg - - init进程启动服务的配置文件,当前支持解析的命令有: - - 1\) start: 启动某个服务 - - 2\) mkdir: 创建文件夹 - - 3)chmod: 修改指定路径/文件的权限 - - 4\) chown: 修改指定路径/文件的属组 - - 5\) mount: 挂载命令 - - 该文件中的各个字段的解释如下: - - ``` - { - "jobs" : [{ # job数组,一个job对应一个命令集合。job的执行顺序:pre-init -> init -> post-init。 - "name" : "pre-init", - "cmds" : [ - "mkdir /storage/data", # 创建目录 - "chmod 0755 /storage/data", # 修改权限,权限值的格式为0xxx, 如0755 - "mkdir /storage/data/log", - "chmod 0755 /storage/data/log", - "chown 4 4 /storage/data/log", # 修改属组,第一个数字为uid, 第二个数字为gid - ...... - "mount vfat /dev/mmcblock0 /sdcard rw,umask=000" # 挂载,格式为: mount [文件系统类型] [source] [target] [flags] [data] - # 其中flags仅支持:nodev、noexec、nosuid和rdonly - ] - }, { - "name" : "init", - "cmds" : [ # 按cmds数组顺序启动启动服务 - "start shell", # 注意:start与服务名称之间有且只有一个空格 - ...... - "start service1" - ] - }, { - "name" : "post-init", # 最后别执行的job, init进程启动完成后的处理(如驱动初始化后再mount设备) - "cmds" : [] - } - ], - "services" : [{ # service数组,一个service对应一个进程 - "name" : "shell", # 服务名称 - "path" : ["/sbin/getty", "-n", "-l", "/bin/sh", "-L", "115200", "ttyS000", "vt100"], # 可执行文件全路径,path必须为第一个元素 - "uid" : 0, # 进程的uid,须与二进制文件的uid保持一致 - "gid" : 0, # 进程的gid,须与二进制文件的gid保持一致 - "once" : 0, # 是否为一次性进程,1:进程退出后,init不在重新拉起。0:常驻进程,进程若退出,init将重新拉起 - "importance" : 0, # 是否为关键进程,1:是关键进程,若进程退出,init将会重启单板。0:非关键进程,若进程退出,init不会重启单板 - "caps" : [4294967295] - }, - ...... - ] - } - ``` - -3. vendor/company/product/init\_configs/hals - - 解决方案厂商对OS的适配,需要实现的接口请见各个组件的readme说明文档。 - -4. vendor/company/product/config.json - - config.json为编译构建的主入口,包含了开发板、OS组件和内核等配置信息。以基于hispark\_taurus开发板的ipcamera产品为例,配置文件如下: - - ``` - { - "product_name": "ipcamera", # 产品名称 - "ohos_version": "OpenHarmony 1.0", # 选择的OS版本 - "device_company": "hisilicon", # 芯片厂商 - "board": "hispark_taurus", # 开发板名称 - "kernel_type": "liteos_a", # 选择的内核类型 - "kernel_version": "3.0.0", # 选择的内核版本 - "subsystems": [ - { - "subsystem": "aafwk", # 选择的子系统 - "components": [ - { "component": "ability", "features":[ "enable_ohos_appexecfwk_feature_ability = true" ] } # 选择的组件和组件特性配置 - ] - }, - { - ...... - } - ...... - 更多子系统和组件 - } - } - ``` - -5. vendor/company/product/fs.yml - - 该文件用于配置文件系统镜像制作过程,将编译产物打包成文件系统镜像,比如用户态根文件系统rootfs.img和可读写的userfs.img。它由多个列表组成,每个列表对应一个文件系统。字段说明如下: - - ``` - fs_dir_name: 必填,声明文件系统文件名, 如rootfs、userfs - fs_dirs: 选填,配置out下文件目录与文件系统文件目录的映射关系,每个文件目录对应一个列表 - source_dir: 选填,out下目标文件目录,若缺失则将根据target_dir在文件系统下创建空目录 - target_dir: 必填,文件系统下对应文件目录 - ignore_files:选填,声明拷贝忽略文件 - dir_mode: 选填,文件目录权限,默认755 - file_mode: 选填,该文件目录下所有文件的权限,默认555 - fs_filemode: 选填,配置需要特殊声明权限的文件,每个文件对应一个列表 - file_dir: 必填,文件系统下具体文件路径 - file_mode: 必填,文件权限声明 - fs_symlink: 选填,配置文件系统软连接 - fs_make_cmd: 必填,配置需要制作文件系统脚本,OS提供的脚本在build/lite/make_rootfs下, 支持linux,liteos内核和ext4、jffs2、vfat格式。也支持芯片解决方案厂商自定义。 - fs_attr: 选填,根据配置项动态调整文件系统 - ``` - - 其中fs\_symlink、fs\_make\_cmd字段支持以下变量: - - - $\{root\_path\} - - 代码根目录,对应gn的$\{ohos\_root\_path\} - - - $\{out\_path\} - - 产品out目录,对应gn的$\{root\_out\_dir\} - - - $\{fs\_dir\} - - 文件系统目录,由以下变量拼接而成 - - - $\{root\_path\} - - $\{fs\_dir\_name\} - - - >![](public_sys-resources/icon-note.gif) **说明:** - >fs.yml是可选的,对于没有文件系统的设备可不配置。 - -6. vendor/company/product/BUILD.gn - - 产品编译的入口,主要用于编译解决方案厂商源码和拷贝启动配置文件。如果某个产品被选择为要编译的产品,那么对应产品目录下的BUILD.gn会默认编译。一个典型的产品编译BUILD.gn应该如下: - - ``` - group("product") { # target名称需与product名称即三级目录名称一致 - deps = [] - # 拷贝init配置 - deps += [ "init_configs" ] - # 其他 - ...... - } - ``` - - diff --git "a/zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" "b/zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" deleted file mode 100755 index e85c33895c2a4348209433745b10487457589a5d..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\350\275\273\351\207\217\345\222\214\345\260\217\345\236\213\347\263\273\347\273\237\347\274\226\350\257\221\346\236\204\345\273\272\346\214\207\345\257\274.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 轻量和小型系统编译构建指导 - -- **[编译构建概述](编译构建概述.md)** - -- **[编译构建使用指导](编译构建使用指导.md)** - -- **[编译构建常见问题](编译构建常见问题.md)** - - diff --git "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" "b/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" deleted file mode 100755 index 5f32b5fe5013f986e38b1363270abfa4d02668d2..0000000000000000000000000000000000000000 --- "a/zh-cn/device-dev/subsystems/\351\237\263\350\247\206\351\242\221.md" +++ /dev/null @@ -1,9 +0,0 @@ -# 音视频 - -- **[音视频开发概述](音视频开发概述.md)** - -- **[音视频播放开发指导](音视频播放开发指导.md)** - -- **[音视频录制开发指导](音视频录制开发指导.md)** - - diff --git "a/zh-cn/device-dev/\345\257\274\350\257\273.md" "b/zh-cn/device-dev/\345\257\274\350\257\273.md" index c49e621b918d86e3a96969515fed4605ed142761..44b738359b4d15194b84a525e6a69a7e152ad25c 100644 --- "a/zh-cn/device-dev/\345\257\274\350\257\273.md" +++ "b/zh-cn/device-dev/\345\257\274\350\257\273.md" @@ -48,49 +48,49 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按

整体认知OpenHarmony

- +

获取开发资源

准备开发前相关资源

- +

快速入门

快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行。

-

轻量和小型系统入门

+

轻量和小型系统快速入门

基础能力使用

使用OpenHarmony提供的基础能力

- +

进阶开发

结合系统能力开发智能设备

- +

移植适配

  • 针对特定芯片做移植适配
  • 对三方库进行移植适配
- +

贡献组件

OpenHarmony贡献功能组件

- +

参考

@@ -118,49 +118,49 @@ OpenHarmony也提供了一系列可选的系统组件,方便设备开发者按

整体认知OpenHarmony

- +

获取开发资源

准备开发前相关资源

- +

快速入门

快速熟悉OpenHarmony环境搭建、编译、烧录、调测、运行。

-

标准系统入门

+

标准系统快速入门

基础能力使用

使用OpenHarmony提供的基础能力

- +

进阶开发

结合系统能力开发智能设备

- +

移植适配

对三方库进行移植适配

-

三方库移植指导

+

三方库移植指导

贡献组件

OpenHarmony贡献功能组件

- +

参考

diff --git a/zh-cn/readme.md b/zh-cn/readme.md index 5d67c93e32fc44a704de73113f055beb4f0fa03f..15528919ed017e7a40459397dc85c2484201d1ed 100644 --- a/zh-cn/readme.md +++ b/zh-cn/readme.md @@ -4,54 +4,55 @@ ## 文档目录结构 -- [Openharmony概述](OpenHarmony-Overview_zh.md) -- 轻量和小型系统开发指导(参考内存<128MB) +- [Openharmony概述](OpenHarmony-Overview_zh.md) +- 轻量和小型系统开发指导(参考内存<128MB) - 设备开发 - overview:[设备开发导读](device-dev/导读.md) - quick-start:[快速入门](device-dev/quick-start/Readme-CN.md)(搭建环境、获取源码、编译、烧录等) - - 开发基础能力 - - Kernel:[轻量和小型系统内核](device-dev/kernel/轻量和小型系统内核.md) + - Basic Capability:开发基础能力 + - Kernel:[轻量和小型系统内核](device-dev/kernel/kernel-lite.md) - Drivers:[驱动](device-dev/driver/Readme-CN.md) - Subsystems:[子系统](device-dev/subsystems/Readme-CN.md)(编译构建、图形图像、DFX、XTS等子系统) - Security:[隐私与安全](device-dev/security/Readme-CN.md) - - guide:[开发示例](device-dev/guide/Readme-CN.md) - - [WLAN连接类产品](device-dev/guide/WLAN连接类产品.md)(LED外设控制、集成三方SDK) - - [无屏摄像头类产品](device-dev/guide/无屏摄像头类产品.md)(摄像头控制) - - [带屏摄像头类产品](device-dev/guide/带屏摄像头类产品.md)(屏幕和摄像头控制、视觉应用开发) + - guide:开发示例 + - [WLAN连接类产品](device-dev/guide/device-wifi.md)(LED外设控制、集成三方SDK) + - [无屏摄像头类产品](device-dev/guide/device-iotcamera-control.md)(摄像头控制) + - [带屏摄像头类产品](device-dev/guide/device-camera.md)(屏幕和摄像头控制、视觉应用开发) - - porting:[移植适配](device-dev/porting/Readme-CN.md) - - [三方芯片移植指导](device-dev/porting/三方芯片移植指导.md) - - [三方库移植指导](device-dev/porting/三方库移植指导.md) + - porting:移植适配 + - [三方库移植指导](device-dev/porting/transplant-thirdparty.md) + - [轻量系统芯片移植指导](device-dev/porting/transplant-minichip.md) + - [小型系统芯片移植指导](device-dev/porting/transplant-smallchip.md) - - bundles:[组件开发](device-dev/bundles/Readme-CN.md) - - [组件开发规范](device-dev/bundles/组件开发规范.md) - - [组件开发指南](device-dev/bundles/组件开发指南.md) - - [组件开发示例](device-dev/bundles/组件开发示例.md) + - bundles:组件开发 + - [组件开发规范](device-dev/bundles/bundles-standard-rules.md) + - [组件开发指南](device-dev/bundles/bundles-guide.md) + - [组件开发示例](device-dev/bundles/bundles-demo.md) -- 标准系统开发指导(参考内存≥128MB) +- 标准系统开发指导(参考内存≥128MB) - 设备开发 - overview:[设备开发导读](device-dev/导读.md) - - quick-start:[快速入门](device-dev/quick-start/Readme-CN.md)(搭建环境、获取源码、编译、烧录等) - - 开发基础能力 - - Kernel:[标准系统内核](device-dev/kernel/标准系统内核.md) + - quick-start:[快速入门](device-dev/quick-start/quickstart-standard.md)(搭建环境、获取源码、编译、烧录等) + - Basic Capability:开发基础能力 + - Kernel:[标准系统内核](device-dev/kernel/kernel-standard.md) - Drivers:[驱动](device-dev/driver/Readme-CN.md) - Subsystems:[子系统](device-dev/subsystems/Readme-CN.md)(编译构建、图形图像、DFX、XTS等子系统) - Security:[隐私与安全](device-dev/security/Readme-CN.md) - - guide:[开发示例](device-dev/guide/Readme-CN.md) - - [时钟应用](device-dev/guide/时钟应用开发示例.md) - - [平台驱动](device-dev/guide/平台驱动开发示例.md) - - [外设驱动](device-dev/guide/外设驱动开发示例.md) + - guide:开发示例 + - [时钟应用](device-dev/guide/device-clock-guide.md) + - [平台驱动](device-dev/guide/device-drive-demo.md) + - [外设驱动](device-dev/guide/device-outerdrive-demo.md) - - porting:[移植适配](device-dev/porting/Readme-CN.md) + - porting:移植适配 - [三方库移植指导](device-dev/porting/三方库移植指导.md) + [三方库移植指导](device-dev/porting/transplant-thirdparty.md) - - bundles:[组件开发](device-dev/bundles/Readme-CN.md) - - [组件开发规范](device-dev/bundles/组件开发规范.md) - - [组件开发指南](device-dev/bundles/组件开发指南.md) - - [组件开发示例](device-dev/bundles/组件开发示例.md) + - bundles:组件开发 + - [组件开发规范](device-dev/bundles/bundles-standard-rules.md) + - [组件开发指南](device-dev/bundles/bundles-guide.md) + - [组件开发示例](device-dev/bundles/bundles-demo.md) - 应用开发 @@ -61,7 +62,8 @@ - media:[媒体](application-dev/media/Readme-CN.md) - connectivity:[网络与连接](application-dev/connectivity/Readme-CN.md) - js-reference:[JS参考规范](application-dev/js-reference/Readme-CN.md) -- glossary:[术语](device-dev/glossary/术语.md) +- 许可证及版权信息检查工具:[开源合规审查工具](https://gitee.com/openharmony-sig/tools_oat) +- glossary:[术语](device-dev/glossary/glossary.md) ## 版本更新