Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
OpenHarmony
Docs
提交
47fdba0d
D
Docs
项目概览
OpenHarmony
/
Docs
大约 2 年 前同步成功
通知
161
Star
293
Fork
28
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
D
Docs
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
47fdba0d
编写于
8月 11, 2023
作者:
X
xsz233
提交者:
Gitee
8月 11, 2023
浏览文件
操作
浏览文件
下载
差异文件
Merge branch 'master' of gitee.com:openharmony/docs into master
Signed-off-by:
N
xsz233
<
xushizhe@huawei.com
>
上级
b899ec58
0e54313c
变更
8
展开全部
隐藏空白更改
内联
并排
Showing
8 changed file
with
780 addition
and
311 deletion
+780
-311
zh-cn/application-dev/quick-start/arkts-appstorage.md
zh-cn/application-dev/quick-start/arkts-appstorage.md
+87
-19
zh-cn/application-dev/reference/apis/js-apis-installer.md
zh-cn/application-dev/reference/apis/js-apis-installer.md
+10
-8
zh-cn/device-dev/porting/porting-smallchip-driver-oom.md
zh-cn/device-dev/porting/porting-smallchip-driver-oom.md
+42
-31
zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md
zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md
+33
-16
zh-cn/device-dev/porting/porting-smallchip-prepare-building.md
.../device-dev/porting/porting-smallchip-prepare-building.md
+10
-6
zh-cn/device-dev/porting/standard-system-porting-guide.md
zh-cn/device-dev/porting/standard-system-porting-guide.md
+222
-231
zh-cn/release-notes/changelogs/OpenHarmony_4.0.10.1/changelog-ArkUI.md
...-notes/changelogs/OpenHarmony_4.0.10.1/changelog-ArkUI.md
+375
-0
zh-cn/release-notes/changelogs/OpenHarmony_4.0.9.5/changelogs-arkui.md
...-notes/changelogs/OpenHarmony_4.0.9.5/changelogs-arkui.md
+1
-0
未找到文件。
zh-cn/application-dev/quick-start/arkts-appstorage.md
浏览文件 @
47fdba0d
...
...
@@ -192,9 +192,85 @@ struct CompA {
}
```
###
以持久化方式订阅某个事件并接收事件回调
###
不建议借助@StorageLink的双向同步机制实现事件通知
推荐使用持久化方式订阅某个事件并接收事件回调,可以减少开销,增强代码的可读性。
不建议开发者使用@StorageLink和AppStorage的双向同步的机制来实现事件通知,AppStorage是和UI相关的数据存储,改变会带来UI的刷新,相对于一般的事件通知,UI刷新的成本较大。
TapImage中的点击事件,会触发AppStorage中tapIndex对应属性的改变。因为@StorageLink是双向同步,修改会同步会AppStorage中,所以,所有绑定AppStorage的tapIndex可见自定义组件都会被通知UI刷新。UI刷新带来的成本是巨大的,因此不建议开发者使用此方式来实现基本的事件通知功能。
```
ts
// xxx.ets
class
ViewData
{
title
:
string
;
uri
:
Resource
;
color
:
Color
=
Color
.
Black
;
constructor
(
title
:
string
,
uri
:
Resource
)
{
this
.
title
=
title
;
this
.
uri
=
uri
}
}
@
Entry
@
Component
struct
Gallery2
{
dataList
:
Array
<
ViewData
>
=
[
new
ViewData
(
'
flower
'
,
$r
(
'
app.media.icon
'
)),
new
ViewData
(
'
OMG
'
,
$r
(
'
app.media.icon
'
)),
new
ViewData
(
'
OMG
'
,
$r
(
'
app.media.icon
'
))]
scroller
:
Scroller
=
new
Scroller
()
build
()
{
Column
()
{
Grid
(
this
.
scroller
)
{
ForEach
(
this
.
dataList
,
(
item
:
ViewData
,
index
?:
number
)
=>
{
GridItem
()
{
TapImage
({
uri
:
item
.
uri
,
index
:
index
})
}.
aspectRatio
(
1
)
},
(
item
:
ViewData
,
index
?:
number
)
=>
{
return
JSON
.
stringify
(
item
)
+
index
;
})
}.
columnsTemplate
(
'
1fr 1fr
'
)
}
}
}
@
Component
export
struct
TapImage
{
@
StorageLink
(
'
tapIndex
'
)
@
Watch
(
'
onTapIndexChange
'
)
tapIndex
:
number
=
-
1
;
@
State
tapColor
:
Color
=
Color
.
Black
;
private
index
:
number
;
private
uri
:
Resource
;
// 判断是否被选中
onTapIndexChange
()
{
if
(
this
.
tapIndex
>=
0
&&
this
.
index
===
this
.
tapIndex
)
{
console
.
info
(
`tapindex:
${
this
.
tapIndex
}
, index:
${
this
.
index
}
, red`
)
this
.
tapColor
=
Color
.
Red
;
}
else
{
console
.
info
(
`tapindex:
${
this
.
tapIndex
}
, index:
${
this
.
index
}
, black`
)
this
.
tapColor
=
Color
.
Black
;
}
}
build
()
{
Column
()
{
Image
(
this
.
uri
)
.
objectFit
(
ImageFit
.
Cover
)
.
onClick
(()
=>
{
this
.
tapIndex
=
this
.
index
;
})
.
border
({
width
:
5
,
style
:
BorderStyle
.
Dotted
,
color
:
this
.
tapColor
})
}
}
}
```
开发者可以使用emit订阅某个事件并接收事件回调,可以减少开销,增强代码的可读性。
```
ts
...
...
@@ -293,10 +369,9 @@ export struct TapImage {
}
```
以下示例为消息机制方式订阅事件,会导致回调监听的节点数较多,非常耗时,不推荐以此来实现应用代码。
以上通知事件逻辑简单,也可以简化成三元表达式。
```
ts
```
// xxx.ets
class ViewData {
title: string;
...
...
@@ -337,22 +412,11 @@ struct Gallery2 {
@Component
export struct TapImage {
@
StorageLink
(
'
tapIndex
'
)
@
Watch
(
'
onTapIndexChange
'
)
tapIndex
:
number
=
-
1
;
@StorageLink('tapIndex') tapIndex: number = -1;
@State tapColor: Color = Color.Black;
private index: number;
private uri: Resource;
// 判断是否被选中
onTapIndexChange
()
{
if
(
this
.
tapIndex
>=
0
&&
this
.
index
===
this
.
tapIndex
)
{
console
.
info
(
`tapindex:
${
this
.
tapIndex
}
, index:
${
this
.
index
}
, red`
)
this
.
tapColor
=
Color
.
Red
;
}
else
{
console
.
info
(
`tapindex:
${
this
.
tapIndex
}
, index:
${
this
.
index
}
, black`
)
this
.
tapColor
=
Color
.
Black
;
}
}
build() {
Column() {
Image(this.uri)
...
...
@@ -360,14 +424,18 @@ export struct TapImage {
.onClick(() => {
this.tapIndex = this.index;
})
.
border
({
width
:
5
,
style
:
BorderStyle
.
Dotted
,
color
:
this
.
tapColor
})
.border({
width: 5,
style: BorderStyle.Dotted,
color: (this.tapIndex >= 0 && this.index === this.tapIndex) ? Color.Red : Color.Black
})
}
}
}
```
## 限制条件
AppStorage与
[
PersistentStorage
](
arkts-persiststorage.md
)
以及
[
Environment
](
arkts-environment.md
)
配合使用时,需要注意以下几点:
...
...
zh-cn/application-dev/reference/apis/js-apis-installer.md
浏览文件 @
47fdba0d
...
...
@@ -19,6 +19,8 @@ import installer from '@ohos.bundle.installer';
| ohos.permission.INSTALL_ENTERPRISE_BUNDLE | system_core | 允许应用安装企业InHouse应用。 |
| ohos.permission.INSTALL_ENTERPRISE_MDM_BUNDLE | system_core | 允许在企业设备上安装企业MDM应用包。 |
| ohos.permission.INSTALL_ENTERPRISE_NORMAL_BUNDLE | system_core | 允许在企业设备上安装企业NORMAL应用包。 |
| ohos.permission.UNINSTALL_BUNDLE | system_core | 允许应用卸载应用。 |
| ohos.permission.RECOVER_BUNDLE | system_core | 允许应用恢复预置应用。 |
| ohos.permission.INSTALL_SELF_BUNDLE | system_core | 允许企业MDM应用在企业设备上自升级。|
...
...
@@ -322,7 +324,7 @@ uninstall(bundleName: string, installParam: InstallParam, callback: AsyncCallbac
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.UNINSTALL_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -382,7 +384,7 @@ uninstall(bundleName: string, callback: AsyncCallback<void>): void;
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.UNINSTALL_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -434,7 +436,7 @@ uninstall(bundleName: string, installParam?: InstallParam) : Promise\<void\>;
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.UNINSTALL_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -497,7 +499,7 @@ recover(bundleName: string, installParam: InstallParam, callback: AsyncCallback&
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.RECOVER_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -555,7 +557,7 @@ recover(bundleName: string, callback: AsyncCallback<void>): void;
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.RECOVER_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -605,7 +607,7 @@ recover(bundleName: string, installParam?: InstallParam) : Promise\<void\>;
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.RECOVER_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -665,7 +667,7 @@ uninstall(uninstallParam: UninstallParam, callback : AsyncCallback\<void>) : voi
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.UNINSTALL_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
@@ -719,7 +721,7 @@ uninstall(uninstallParam: UninstallParam) : Promise\<void>;
**系统接口:**
此接口为系统接口。
**需要权限:**
ohos.permission.INSTALL_BUNDLE
**需要权限:**
ohos.permission.INSTALL_BUNDLE
或 ohos.permission.UNINSTALL_BUNDLE
<sup>
10+
</sup>
**系统能力:**
SystemCapability.BundleManager.BundleFramework.Core
...
...
zh-cn/device-dev/porting/porting-smallchip-driver-oom.md
浏览文件 @
47fdba0d
...
...
@@ -8,9 +8,10 @@
移植LCD驱动的主要工作是编写一个驱动,在驱动中生成模型的实例,并完成注册。
这些LCD的驱动被放置在源码目录
//drivers/hdf_core/framework/model/display/driver/panel
中。
这些LCD的驱动被放置在源码目录
`//drivers/hdf_core/framework/model/display/driver/panel`
中。
1.
创建Panel驱动
创建HDF驱动,在驱动初始化中调用RegisterPanel接口注册模型实例。如:
...
...
@@ -36,7 +37,8 @@
```
2.
配置加载panel驱动
产品的所有设备信息被定义在源码文件//vendor/vendor_name/product_name/config/device_info/device_info.hcs中。修改该文件,在display的host中,名为device_lcd的device中增加配置。
产品的所有设备信息被定义在源码文件
`//vendor/vendor_name/product_name/config/device_info/device_info.hcs`
中。修改该文件,在display的host中,名为device_lcd的device中增加配置。
>  **注意:**
> moduleName 要与panel驱动中的moduleName相同。
...
...
@@ -61,12 +63,13 @@
## TP驱动移植
本节描述如何移植触摸屏驱动。触摸屏的器件驱动被放置在源码目录
//drivers/hdf_core/framework/model/input/driver/touchscreen
中。 移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。
本节描述如何移植触摸屏驱动。触摸屏的器件驱动被放置在源码目录
`//drivers/hdf_core/framework/model/input/driver/touchscreen`
中。 移植触摸屏驱动主要工作是向系统注册ChipDevice模型实例。
详细的驱动开发指导,请参考
[
TOUCHSCREEN开发指导
](
../driver/driver-peripherals-touch-des.md
)
。
1.
创建触摸屏器件驱动
在上述touchscreen目录中创建名为touch_ic_name.c的文件。编写如下内容
在上述touchscreen目录中创建名为
`touch_ic_name.c`
的文件。编写如下内容
```
...
...
@@ -103,21 +106,22 @@
| int32_t
(\*UpdateFirmware)(ChipDevice
\*
device) | 实现固件升级 |
2.
配置产品,加载器件驱动
产品的所有设备信息被定义在源码文件//vendor/vendor_name/product_name/config/device_info/device_info.hcs中。修改该文件,在名为input的host中,名为device_touch_chip的device中增加配置。
产品的所有设备信息被定义在源码文件
`//vendor/vendor_name/product_name/config/device_info/device_info.hcs`
中。修改该文件,在名为input的host中,名为device_touch_chip的device中增加配置。
>  **说明:**
> moduleName 要与触摸屏驱动中的moduleName相同。
```
deviceN :: deviceNode {
policy = 0;
priority = 130;
preload = 0;
permission = 0660;
moduleName = "HDF_TOUCH_XXXX";
deviceMatchAttr = "touch_XXXX_configs";
}
deviceN :: deviceNode {
policy = 0;
priority = 130;
preload = 0;
permission = 0660;
moduleName = "HDF_TOUCH_XXXX";
deviceMatchAttr = "touch_XXXX_configs";
}
```
...
...
@@ -126,6 +130,7 @@
WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负责处理WLAN流量。
**图1**
OpenHarmony WLAN结构示意图
!
[
zh-cn_image_0000001207756867
](
figures/zh-cn_image_0000001207756867.png
)
如图1,左半部分负责管理WLAN设备,右半部分负责WLAN流量。HDF WLAN分别为这两部分做了抽象,驱动的移植过程可以看做分别实现这两部分所需接口。这些接口有:
...
...
@@ -141,8 +146,9 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
具体的移植步骤如下:
1.
创建HDF WLAN 芯片驱动
在目录/device/vendor_name/peripheral/wifi/chip_name/ 创建文件 hdf_wlan_chip_name.c。内容模板如下:
1.
创建HDF WLAN芯片驱动
在目录
`/device/vendor_name/peripheral/wifi/chip_name/`
创建文件
`hdf_wlan_chip_name.c`
。内容模板如下:
```
...
...
@@ -166,7 +172,7 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
HDF_INIT(g_hdfXXXChipEntry);
```
在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法
在上述代码的CreateChipDriverFactory方法中,需要创建一个HdfChipDriverFactory类型的对象。该对象提供如下方法
:
| 接口 | 说明 |
| -------- | -------- |
...
...
@@ -178,7 +184,7 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
| void
(\*Release)(struct
HdfChipDriver
\*
chipDriver) | 释放chipDriver |
| uint8_t
(\*GetMaxIFCount)(struct
HdfChipDriverFactory
\*
factory) | 获取当前芯片支持的最大接口数 |
其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver
。该对象需要提供方法:
其中Build方法负责创建一个管理指定网络接口的对象HdfChipDriver
。该对象需要提供方法:
| 接口 | 说明 |
| -------- | -------- |
...
...
@@ -189,7 +195,8 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
| struct
HdfMac80211APOps
\*
apOps | 支持AP模式所需要的接口集 |
2.
编写配置文件描述驱动支持的芯片
在产品配置目录下创建芯片的配置文件,保存至源码路径//vendor/vendor_name/product_name/config/wifi/wlan_chip_chip_name.hcs
在产品配置目录下创建芯片的配置文件,保存至源码路径
`//vendor/vendor_name/product_name/config/wifi/wlan_chip_chip_name.hcs`
该文件模板如下:
...
...
@@ -212,29 +219,32 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
```
>  **说明:**
> 路径和文件中的vendor_name、product_name、chip_name请替换成实际名称
>
> 路径和文件中的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中增加配置。模板如下:
产品的所有设备信息被定义在源码文件
`//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";
}
deviceN :: deviceNode {
policy = 0;
preload = 2;
moduleName = "HDF_WLAN_CHIPS";
deviceMatchAttr = "hdf_wlan_chips_chip_name";
serviceName = "driverName";
}
```
>  **说明:**
> moduleName 要与HDF WLAN 芯片驱动中的moduleName相同。
4.
修改Kconfig文件,让移植的WLAN模组出现再内核配置中
在device/vendor_name/drivers/Kconfig中增加配置菜单,模板如下
在
`device/vendor_name/drivers/Kconfig`
中增加配置菜单,模板如下
```
...
...
@@ -246,10 +256,11 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
```
>  **说明:**
> 请替换模板中的chip_name为实际的芯片名称
> 请替换模板中的chip_name为实际的芯片名称
。
5.
修改构建脚本,让驱动参与内核构建
在源码文件//device/vendor_name/drivers/lite.mk末尾追加如下内容
在源码文件
`//device/vendor_name/drivers/lite.mk`
末尾追加如下内容。
```
...
...
@@ -262,4 +273,4 @@ WLAN驱动分为两部分,一部分负责管理WLAN设备,另一个部分负
```
>  **说明:**
> 请替换模板中的chip_name为实际的芯片名称
> 请替换模板中的chip_name为实际的芯片名称
。
zh-cn/device-dev/porting/porting-smallchip-kernel-linux.md
浏览文件 @
47fdba0d
...
...
@@ -8,7 +8,7 @@ Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后
### 基本信息
当前Linux内核基线是基于Linux社区 4.19 LTS版本演进,合入CVE及bugfix补丁。具体信息参考
[
代码库
](
https://gitee.com/openharmony/kernel_linux
)
,对应repo工程代码路径为
kernel/linux-4.19
。
当前Linux内核基线是基于Linux社区 4.19 LTS版本演进,合入CVE及bugfix补丁。具体信息参考
[
代码库
](
https://gitee.com/openharmony/kernel_linux
)
,对应repo工程代码路径为
`kernel/linux-4.19`
。
### Bootloader
...
...
@@ -19,17 +19,20 @@ Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后
## 适配编译和烧录启动
1.
准备内核config(特别是芯片相关的config)。
config文件所在源码目录:kernel/linux/config/
以hi3516dv300芯片为例,可在对应的linux-4.19/arch/arm/configs/目录下新建
<
YOUR_CHIP
>
_small_
defconfig,如hi3516dv300_small_defconfig表示针对hi3516dv300小型系统的defconfig。该config文件可以由基础defconfig文件small_common_defconfig与该芯片相关的config组合生成。
config文件所在源码目录:
`kernel/linux/config/`
以hi3516dv300芯片为例,可在对应的
`linux-4.19/arch/arm/configs/`
目录下新建
<
YOUR_CHIP
>
_small_
defconfig,如
`hi3516dv300_small_defconfig`
表示针对hi3516dv300小型系统的defconfig。该config文件可以由基础defconfig文件
`small_common_defconfig`
与该芯片相关的config组合生成。
2.
准备芯片补丁。
补丁文件所在源码目录:kernel/linux/patches/linux-4.19
补丁文件所在源码目录:
`kernel/linux/patches/linux-4.19`
以hi3516dv300芯片为例,参考已有的patch目录hi3516dv300_small_patch目录,新建
<
YOUR_CHIP
>
_patch目录,放置相关芯片补丁,注意hdf.patch等驱动补丁。
3.
编译。
具体内核编译入口脚本位于工程目录kernel/linux/patches/下面,版本级整编命令会通过BUILD.gn进入kernel_module_build.sh和kernel.mk,需要在这2个文件中针对性进行patch及defconfig文件路径、编译器、芯片架构、内核Image格式等的适配。
具体内核编译入口脚本位于工程目录
`kernel/linux/patches/`
下面,版本级整编命令会通过BUILD.gn进入
`kernel_module_build.sh`
和
`kernel.mk`
,需要在这2个文件中针对性进行patch及defconfig文件路径、编译器、芯片架构、内核Image格式等的适配。
通过编译错误日志调整补丁,典型错误场景:
...
...
@@ -38,11 +41,12 @@ Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后
(2)编译失败,内核版本差异(函数实现调整等)需要针对性进行内核适配。
>  **注意:**
> - 参考
kernel.mk
,在OpenHarmony工程的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用版本级编译命令前,需要kernel/linux-4.19保持原代码环境。
> - 参考
`kernel.mk`
,在OpenHarmony工程的编译构建流程中会拷贝kernel/linux-4.19的代码环境后进行打补丁动作,在使用版本级编译命令前,需要kernel/linux-4.19保持原代码环境。
>
> - 对应拷贝后的目录位于
: out/<\*\*\*>/kernel/linux-4.19
,可以在该目录下进行补丁的修改适配。
> - 对应拷贝后的目录位于
:`out/<***>/kernel/linux-4.19`
,可以在该目录下进行补丁的修改适配。
4.
烧录启动。
由于不同芯片的开发板的烧录方式不一样,此处不表述具体的烧录方式。需要注意烧录的各镜像的大小及启动参数的配置,参考hi3516dv300采用uboot启动参数:
...
...
@@ -56,43 +60,56 @@ Linux内核移植主要涉及基于linux内核基线合入三方芯片补丁后
调试init进程、启动shell和运行简单的用户态程序,验证内核移植是否成功。OpenHarmony小型系统的OS镜像结构以及linux用户态的启动流程如下图1所示:
**图1**
基于linux内核的OS镜像结构和用户态程序启动流程
!
[
zh-cn_image_0000001154372318
](
figures/zh-cn_image_0000001154372318.png
)
基于上述流程,推荐按以下步骤完成验证:
1.
制作根文件系统镜像。
请参考
[
新建芯片解决方案和产品解决方案
](
../subsystems/subsys-build-all.md
)
生成根文件系统镜像rootfs.img。从上图可以看到启动过程与产品配置强相关,在制作rootfs.img过程中请完成如下四种配置:
请参考
[
新建芯片解决方案和产品解决方案
](
../subsystems/subsys-build-all.md
)
生成根文件系统镜像
`rootfs.img`
。从上图可以看到启动过程与产品配置强相关,在制作rootfs.img过程中请完成如下四种配置:
-
组件配置
产品组件配置文件vendor/{company}/{product}/config.json需配置启动恢复子系统(startup)的init_lite组件和内核子系统的linux_4_1_9组件。
产品组件配置文件`vendor/{company}/{product}/config.json`需配置启动恢复子系统(startup)的init_lite组件和内核子系统的linux_4_1_9组件。
-
系统服务配置
系统服务配置文件vendor/{company}/{product}/init_configs/init_xxx.cfg需要启动shell服务。
系统服务配置文件`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}/fs.yml`中需要创建`/bin/sh -> mksh`和`/lib/ld-musl-arm.so.1 -> libc.so`软连接,这两个文件分别是shell可执行程序和可执行程序依赖的c库。
-
启动配置
启动配置在vendor/{company}/{product}/init_configs/etc目录下,包括fstab、rsS和Sxxx文件,请按开发板实际情况配置。
启动配置在`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脚本完成设备节点创建和扫描、文件权限配置等操作
。
烧录
`rootfs.img`
并调试init进程和shell,不同厂商的开发板的烧录工具和流程可能不同,请按芯片解决方案提供的流程进行烧录。烧录
`rootfs.img`
前请确认bootloader和linux内核启动正常。如果
`rootfs.img`
被内核正常挂载,接着将运行
`/bin/init`
程序,init进程为用户态的第一个应用程序,它的运行意味着用户态的开始
。
最后,init程序会读取init.cfg系统服务配置文件。根据步骤1中的设置,init程序将会启动shell。如果上述流程运行正常,系统则会进入shell。
init程序首先会调用
`/etc/init.d/rcS`
脚本,rcS脚本执行第一条命令为
`/bin/mount -a`
,该命令会加载fstab文件,在fstab中的命令执行完后rcS将顺序调用Sxxx脚本完成设备节点创建和扫描、文件权限配置等操作。
最后,init程序会读取
`init.cfg`
系统服务配置文件。根据步骤1中的设置,init程序将会启动shell。如果上述流程运行正常,系统则会进入shell。
若串口有如下版本号日志打印,则表示init程序启动正常:
**图2** init启动正常日志

正常进入shell后执行ls命令,串口打印信息如下图:
**图3** 正常进入shell后输入ls命令串口打印

3.
配置NFS。
init进程和shell正常启动后,以服务端IP为192.168.1.22、客户端IP为192.168.1.4为例,可在根目录执行如下命令开启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
...
...
zh-cn/device-dev/porting/porting-smallchip-prepare-building.md
浏览文件 @
47fdba0d
...
...
@@ -20,7 +20,8 @@ sudo apt-get install gcc-arm-linux-gnueabi
了解编译框架和搭建完编译环境后,请参考如下步骤新建芯片解决方案:
1.
新建目录
芯片解决方案的目录规则为:device/{芯片解决方案厂商}/{开发板}。以海思的hispark_taurus开发板为例,在代码根目录执行如下命令建立目录:
芯片解决方案的目录规则为:
`device/{芯片解决方案厂商}/{开发板}`
。以海思的hispark_taurus开发板为例,在代码根目录执行如下命令建立目录:
```
...
...
@@ -59,7 +60,8 @@ sudo apt-get install gcc-arm-linux-gnueabi
目录树建立后开发板相关的源码放到hispark_taurus目录下。
2.
配置开发板编译选项
步骤1中的config.gni可配置开发板相关的编译选项,编译构建框架将会遵照该配置文件中的参数编译所有用户态OS组件。其中关键的字段说明如下:
步骤1中的
`config.gni`
可配置开发板相关的编译选项,编译构建框架将会遵照该配置文件中的参数编译所有用户态OS组件。其中关键的字段说明如下:
```
...
...
@@ -75,7 +77,7 @@ sudo apt-get install gcc-arm-linux-gnueabi
board_ld_flags: 开发板配置的链接选项。
```
还以海思的hispark_taurus开发板为例,对应的
device/hisilicon/hispark_taurus/config.gni
内容如下:
还以海思的hispark_taurus开发板为例,对应的
`device/hisilicon/hispark_taurus/config.gni`
内容如下:
```
# Board CPU type, e.g. "cortex-a7", "riscv32".
...
...
@@ -121,9 +123,10 @@ sudo apt-get install gcc-arm-linux-gnueabi
```
3.
编写开发板编译脚本
步骤1中的BUILD.gn为新增的开发板的编译入口,主要用于编译开发板相关的代码,主要为设备侧驱动、设备侧接口适配(媒体,图形等)和开发板的SDK等等。
海思的hispark_taurus开发板的device/hisilicon/hispark_taurus/BUILD.gn可写成:
步骤1中的
`BUILD.gn`
为新增的开发板的编译入口,主要用于编译开发板相关的代码,主要为设备侧驱动、设备侧接口适配(媒体,图形等)和开发板的SDK等等。
海思的hispark_taurus开发板的
`device/hisilicon/hispark_taurus/BUILD.gn`
可写成:
```
...
...
@@ -137,4 +140,5 @@ sudo apt-get install gcc-arm-linux-gnueabi
```
4.
编译调试
在开发板目录下执行hb set和hb build即可启动芯片解决方案的编译,编译框架会以开发板下的BUILD.gn为入口启动编译。
在开发板目录下执行
`hb set`
和
`hb build`
即可启动芯片解决方案的编译,编译框架会以开发板下的
`BUILD.gn`
为入口启动编译。
zh-cn/device-dev/porting/standard-system-porting-guide.md
浏览文件 @
47fdba0d
此差异已折叠。
点击以展开。
zh-cn/release-notes/changelogs/OpenHarmony_4.0.10.1/changelog-ArkUI.md
0 → 100644
浏览文件 @
47fdba0d
# ArkUI子系统changelog
## cl.arkui.1 状态变量支持undefined和null
**变更影响**
API version 9:状态变量不支持undefined和null,当开发者给状态变量设置undefined或者null时,设置失败,即状态变量还是上一次的值。
API version 10:状态变量支持undefined和null,当开发者给状态变量设置undefined和null时,ArkUI框架会接受该值,即下一次读状态变量的是undefined和null,开发者要注意做判空保护。
**适配指导**
API version 9,当开发者给状态变量设置undefined时,设置无效,会导致开发者忽略对undefined的校验。
```
ts
@
Entry
@
Component
struct
Page3
{
@
State
messages
:
string
[]
=
[
'
Hello World
'
]
aboutToAppear
()
{
// AppStorage里没有对应的key,返回undefined
// API version 9:赋值不生效,ArkUI框架会拒绝undefined,this.messages还为其初始值['Hello World']
// API version 10: 赋值生效,ArkUI框架会接受undefined,this.messages为undefined
this
.
messages
=
AppStorage
.
Get
(
"
aProp
"
)
}
build
()
{
Row
()
{
Column
()
{
// API version 9: 应用没有crash,length为1
// API version 10:应用crash, Error message: Cannot read property length of undefined
Text
(
`the messages length:
${
this
.
messages
.
length
}
`
)
.
fontSize
(
50
)
.
fontWeight
(
FontWeight
.
Bold
)
}
.
width
(
'
100%
'
)
}
.
height
(
'
100%
'
)
}
}
```
对于上述情况,当每一次给状态变量赋值undefined和null时,需要对状态变量是否为undefined做校验。
```
ts
Text
(
`the messages length:
${
this
.
messages
?.
length
}
`
)
```
API version 10,ArkUI框架增强对状态变量类型和初始化的校验,ArkUI框架会抛出运行时报错。具体有以下两种情况:
1.
@Link必须被父组件初始化。
对于以下示例,当前会抛出运行时报错,提示开发者需要初始化@Link。
```
ts
@
Entry
@
Component
struct
Page3
{
@
State
aProp
:
boolean
=
true
build
()
{
Row
()
{
Column
()
{
// crash: SynchedPropertyObjectTwoWayPU[9, 'linkProp']: constructor @Link/@Consume source variable in
// parent/ancestor @Component must be defined. Application error!
LinkChild
()
// 错误的用常规变量初始化linkProp,ArkUI框架无认为没有初始化,和上述一样的报错
LinkChild
({
aProp
:
false
})
// 正确,用状态变量this.aProp初始化@Link
LinkChild
({
aProp
:
this
.
aProp
})
}
.
width
(
'
100%
'
)
}
.
height
(
'
100%
'
)
}
}
@
Component
struct
LinkChild
{
@
Link
aProp
:
boolean
build
()
{
Text
(
`linkProp:
${
this
.
aProp
}
`
)
.
fontSize
(
50
)
.
fontWeight
(
FontWeight
.
Bold
)
}
}
```
2.
校验状态变量不支持的类型。
状态变量对于不支持的类型,比如function,抛出运行时报错来提示开发者。
```
ts
@
Entry
@
Component
struct
Page3
{
// API version 10:运行时报错:@Component 'Page3': Illegal variable value error with decorated variable @State/@Provide 'functionProp': failed
// validation: 'undefined, null, number, boolean, string, or Object but not function, attempt to assign value type: 'function',
@
State
functionProp
:
()
=>
void
=
()
=>
{
console
.
info
(
"
123
"
)
}
aboutToAppear
()
{
this
.
functionProp
()
}
build
()
{
Row
()
{
Column
()
{
Text
(
"
hello
"
)
}
.
width
(
'
100%
'
)
}
.
height
(
'
100%
'
)
}
}
```
## cl.arkui.2 @StorageLink在页面跳转和页签场景行为优化
**变更影响**
AppStorage是应用全局的UI状态存储,@StorageLink是对AppStorage中对应key的双向同步,即@StorageLink修饰的变量的改变会同步回AppStorage,AppStorage的修改也会同步给@StorageLink。
当AppStorage某一个key发生改变时,会通知所有绑定该key的@StorageLink,@StorageLink装饰的变量的改变,会触发组件的重新渲染,包括不可见页面或者TabContent组件,这就造成了不必要的更新和性能浪费。
本次优化针对两个场景做出了优化:
1.
不可见页面的@StorageLink不会被通知刷新。
2.
不可见TabContent的@StorageLink不会被通知刷新。
AppStorage的属性改变,将不立即通知这两个场景下的@StorageLink更新和其@Watch回调,而是当页面或TabContent重新回到激活状态时,即可见状态,再去触发UI更新和其@Watch回调。
可见切换不可见状态或不可见切换可见状态流程如下:
1.
页面或TabContent内的自定义组件从可见到不可见,即标记组件为inActive。
2.
当AppStorage的属性变化时,标记不可见节点的@StorageLink装饰的变量已经变化,但不通知UI刷新。
3.
当页面或TabContent重新可见,即从inActive回到Active状态,将@StorageLink的dependentElementIds添加到其所属自定义组件的脏节点,调用其@Watch方法,刷新UI。
这次优化带来的最重要的应用行为变更是:不可见的页面和TabContent的@StorageLink的watch方法将不被回调。当其回到可见状态时,才会触发@Watch方法回调和UI更新。
**适配指导**
不建议开发者通过借助@StorageLink和@Watch作为事件通知机制,因为@StorageLink是和UI强相关的装饰器,更新成本相较于一般的事件通知机制emit较高。
TapImage中的点击事件,会触发AppStorage中tapIndex对应属性的改变。因为@StorageLink是双向同步,修改会同步会AppStorage中,所以,所有绑定AppStorage的tapIndex可见自定义组件都会被通知UI刷新。UI刷新带来的成本是巨大的,因此不建议开发者使用此方式来实现基本的事件通知功能。
```
ts
// xxx.ets
class
ViewData
{
title
:
string
;
uri
:
Resource
;
color
:
Color
=
Color
.
Black
;
constructor
(
title
:
string
,
uri
:
Resource
)
{
this
.
title
=
title
;
this
.
uri
=
uri
}
}
@
Entry
@
Component
struct
Gallery2
{
dataList
:
Array
<
ViewData
>
=
[
new
ViewData
(
'
flower
'
,
$r
(
'
app.media.icon
'
)),
new
ViewData
(
'
OMG
'
,
$r
(
'
app.media.icon
'
)),
new
ViewData
(
'
OMG
'
,
$r
(
'
app.media.icon
'
))]
scroller
:
Scroller
=
new
Scroller
()
build
()
{
Column
()
{
Grid
(
this
.
scroller
)
{
ForEach
(
this
.
dataList
,
(
item
:
ViewData
,
index
?:
number
)
=>
{
GridItem
()
{
TapImage
({
uri
:
item
.
uri
,
index
:
index
})
}.
aspectRatio
(
1
)
},
(
item
:
ViewData
,
index
?:
number
)
=>
{
return
JSON
.
stringify
(
item
)
+
index
;
})
}.
columnsTemplate
(
'
1fr 1fr
'
)
}
}
}
@
Component
export
struct
TapImage
{
@
StorageLink
(
'
tapIndex
'
)
@
Watch
(
'
onTapIndexChange
'
)
tapIndex
:
number
=
-
1
;
@
State
tapColor
:
Color
=
Color
.
Black
;
private
index
:
number
;
private
uri
:
Resource
;
// 判断是否被选中
onTapIndexChange
()
{
if
(
this
.
tapIndex
>=
0
&&
this
.
index
===
this
.
tapIndex
)
{
console
.
info
(
`tapindex:
${
this
.
tapIndex
}
, index:
${
this
.
index
}
, red`
)
this
.
tapColor
=
Color
.
Red
;
}
else
{
console
.
info
(
`tapindex:
${
this
.
tapIndex
}
, index:
${
this
.
index
}
, black`
)
this
.
tapColor
=
Color
.
Black
;
}
}
build
()
{
Column
()
{
Image
(
this
.
uri
)
.
objectFit
(
ImageFit
.
Cover
)
.
onClick
(()
=>
{
this
.
tapIndex
=
this
.
index
;
})
.
border
({
width
:
5
,
style
:
BorderStyle
.
Dotted
,
color
:
this
.
tapColor
})
}
}
}
```
开发者可以使用emit订阅某个事件并接收事件回调,可以减少开销,增强代码的可读性。
```
ts
// xxx.ets
import
emitter
from
'
@ohos.events.emitter
'
;
let
NextID
:
number
=
0
;
class
ViewData
{
title
:
string
;
uri
:
Resource
;
color
:
Color
=
Color
.
Black
;
id
:
number
;
constructor
(
title
:
string
,
uri
:
Resource
)
{
this
.
title
=
title
;
this
.
uri
=
uri
this
.
id
=
NextID
++
;
}
}
@
Entry
@
Component
struct
Gallery2
{
dataList
:
Array
<
ViewData
>
=
[
new
ViewData
(
'
flower
'
,
$r
(
'
app.media.icon
'
)),
new
ViewData
(
'
OMG
'
,
$r
(
'
app.media.icon
'
)),
new
ViewData
(
'
OMG
'
,
$r
(
'
app.media.icon
'
))]
scroller
:
Scroller
=
new
Scroller
()
private
preIndex
:
number
=
-
1
build
()
{
Column
()
{
Grid
(
this
.
scroller
)
{
ForEach
(
this
.
dataList
,
(
item
:
ViewData
)
=>
{
GridItem
()
{
TapImage
({
uri
:
item
.
uri
,
index
:
item
.
id
})
}.
aspectRatio
(
1
)
.
onClick
(()
=>
{
if
(
this
.
preIndex
===
item
.
id
)
{
return
}
var
innerEvent
=
{
eventId
:
item
.
id
}
// 选中态:黑变红
var
eventData
=
{
data
:
{
"
colorTag
"
:
1
}
}
emitter
.
emit
(
innerEvent
,
eventData
)
if
(
this
.
preIndex
!=
-
1
)
{
console
.
info
(
`preIndex:
${
this
.
preIndex
}
, index:
${
item
.
id
}
, black`
)
var
innerEvent
=
{
eventId
:
this
.
preIndex
}
// 取消选中态:红变黑
var
eventData
=
{
data
:
{
"
colorTag
"
:
0
}
}
emitter
.
emit
(
innerEvent
,
eventData
)
}
this
.
preIndex
=
item
.
id
})
},
(
item
:
ViewData
)
=>
JSON
.
stringify
(
item
))
}.
columnsTemplate
(
'
1fr 1fr
'
)
}
}
}
@
Component
export
struct
TapImage
{
@
State
tapColor
:
Color
=
Color
.
Black
;
private
index
:
number
;
private
uri
:
Resource
;
onTapIndexChange
(
colorTag
:
emitter
.
EventData
)
{
this
.
tapColor
=
colorTag
.
data
.
colorTag
?
Color
.
Red
:
Color
.
Black
}
aboutToAppear
()
{
//定义事件ID
var
innerEvent
=
{
eventId
:
this
.
index
}
emitter
.
on
(
innerEvent
,
this
.
onTapIndexChange
.
bind
(
this
))
}
build
()
{
Column
()
{
Image
(
this
.
uri
)
.
objectFit
(
ImageFit
.
Cover
)
.
border
({
width
:
5
,
style
:
BorderStyle
.
Dotted
,
color
:
this
.
tapColor
})
}
}
}
```
以上通知事件逻辑简单,也可以简化成三元表达式。
```
// xxx.ets
class ViewData {
title: string;
uri: Resource;
color: Color = Color.Black;
constructor(title: string, uri: Resource) {
this.title = title;
this.uri = uri
}
}
@Entry
@Component
struct Gallery2 {
dataList: Array<ViewData> = [new ViewData('flower', $r('app.media.icon')), new ViewData('OMG', $r('app.media.icon')), new ViewData('OMG', $r('app.media.icon'))]
scroller: Scroller = new Scroller()
build() {
Column() {
Grid(this.scroller) {
ForEach(this.dataList, (item: ViewData, index?: number) => {
GridItem() {
TapImage({
uri: item.uri,
index: index
})
}.aspectRatio(1)
}, (item: ViewData, index?: number) => {
return JSON.stringify(item) + index;
})
}.columnsTemplate('1fr 1fr')
}
}
}
@Component
export struct TapImage {
@StorageLink('tapIndex') tapIndex: number = -1;
@State tapColor: Color = Color.Black;
private index: number;
private uri: Resource;
build() {
Column() {
Image(this.uri)
.objectFit(ImageFit.Cover)
.onClick(() => {
this.tapIndex = this.index;
})
.border({
width: 5,
style: BorderStyle.Dotted,
color: (this.tapIndex >= 0 && this.index === this.tapIndex) ? Color.Red : Color.Black
})
}
}
}
```
zh-cn/release-notes/changelogs/OpenHarmony_4.0.9.5/changelogs-arkui.md
浏览文件 @
47fdba0d
...
...
@@ -105,6 +105,7 @@ struct GridRowExample {
.
border
({
color
:
'
#880606
'
,
width
:
2
})
}
}
```
API Version 9:上方示例中的GridRow设定width中的"80pv"会等同于width设定字符串"80"
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录