社区编辑申请
注册/登录
OHOS LTS 3.0移植到RaspberryPi 4B
系统 OpenHarmony
下面是我将OHOS LTS3.0系统移植到 Raspberry Pi 4B 开发板上所做的一些事情。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

1、简介

《沉浸式剖析OpenHarmony源代码》一书没有涉及系统移植方面的内容,因此在交了书稿到出版社之后,我就开始考虑系统移植方面的事情。在了解一些情况后综合考量,我决定尝试一下在Raspberry Pi 4B上移植OHOS,因为已经有成功的先例了,一来可行性没问题,二来可以少走很多弯路。

本次移植参考了社区大佬 亮子力的“​​harmony-raspberry: 移植鸿蒙Harmony到树莓派 (gitee.com)​​” 和 hazhuzhu哈猪猪 的“​​#星光计划2.0# OpenHarmony3.0的树莓派4B移植-学习记录-开源基础软件社区-51CTO.COM​​” 。二位的成功移植案例,给了我不少启发,虽然在实际移植过程中,我也经历了一些他们没遇到过的问题,但最终都比较顺利地解决掉了。

下面是我将OHOS LTS3.0系统移植到 Raspberry Pi 4B 开发板上所做的一些事情,感兴趣的小伙伴可以参考下面的步骤进行操作,应该也能比较顺利地完成初步的移植工作。

视频链接:https://ost.51cto.com/show/13949

本次移植的相关代码见码云仓库:

https://gitee.com/liangkzgitee/ohoslts30rpi4b

已确认可运行的烧录镜像见百度网盘:

注意:本例触屏方案为“EDT_FT5X06”,其他方案的触屏可能会有显示但无触碰功能。
链接:https://pan.baidu.com/s/1KvSGFBf6pdyqdJTTq_1O6A?pwd=ohos
提取码:ohos

链接内OhosLts30Pi4b目录下的文件列表:

1.ohos_rpi4b.img:完整的系统镜像,直接用Raspberry Pi官方烧录工具烧录到SD卡上即可使用。
2.zImage:内核镜像,可用于直接替换SD卡上“/boot/”分区里的内核文件。
3.boot.img:烧录到SD卡上“/boot/”分区里的内容,已包含内核镜像。
4.system.imgOHOS系统镜像,Linux下可用dd命令单独烧录到SD卡内的“/”分区,用sudo权限可修改该分区内的文件,比如/system/etc/init.rpi4b.cfg 或 /system/etc/weston.ini 等。
5.vendor.imguserdata.img:目前并无实质性的重要内容,正常烧录一次后就不用再管这两个镜像了。

2、OHOS LTS3.0

创建 LTS30 目录,在该目录内下载 OHOS LTS3.0 源代码:

$ repo init -u git@gitee.com:openharmony/manifest.git -b refs/tags/OpenHarmony-v3.0-LTS --no-repo-verify
$ repo sync -c -j4
$ repo forall -c 'git lfs pull'
$ ./build/prebuilts_download.sh

3、产品配置部分

(1)rpi4b.json 设备部分

//productdefine/common/device/目录下,拷贝“hi3516dv300.json”,并重命名为“rpi4b.json”,并修改相关字段:

{
"device_name": "rpi4b",
"device_company": "raspberrypi",
"target_os": "ohos",
"target_cpu": "arm",
"kernel_version": "",
"device_build_path": "device/raspberrypi/build"
}

(2)rpi4b.json 产品部分

//productdefine/common/products/目录下,拷贝“Hi3516DV300.json”,并重命名为 “rpi4b.json”,并修改相关字段:

{
"product_name": "rpi4b",
"product_company": "raspberrypi",
"product_device": "rpi4b",
"version": "2.0",
"type": "standard",
"product_build_path": "device/raspberrypi/build",
"parts":{
"ace:ace_engine_standard":{},
"ace:napi":{},
......
#【删除“hisilicon_products”这一行】
"hisilicon_products:hisilicon_products":{},
#【新增子系统和部件,//build/subsystem_config.json文件中不添加该子系统信息也没关系】
"raspberrypi_products:raspberrypi_products":{},
......#【略,其他子系统/部件列表保持与Hi3516DV300一致即可,也可自行裁剪】
"ark:ark":{},
"ark:ark_js_runtime":{},
"ark:ark_ts2abc":{}
}
}

可以对部件列表进行一下裁剪,把不相关部分部件去掉,但要注意可能会因为依赖关系的原因导致编译异常。

4、vendor部分

创建//vendor/raspberrypi/rpi4b/目录,整体拷贝//vendor/hisilicon/Hi3516DV300/目录下的 hdf_config 目录到 //vendor/raspberrypi/rpi4b/ 目录下,修改 hdf_config/khdf/hdf.hcs 文件为:

#include "device_info/device_info.hcs"
root {
module = "raspberry,bcm2711_chip";
}

本例是有移植HDF的,不过在8.3的内核配置中,把“CONFIG_DRIVERS_HDF_TEST”注释掉了,因此这里需要增加一个Makefile去直接编译 hdf_config/khdf/hdf.hcs, 而不去编译 hdf_config/khdf/hdf_test/hdf.hcs。

以后再根据Raspberry Pi 4B的硬件实情来修改hdf_config的其他部分。

5、device部分

增加//device/raspberrypi/目录下的内容,见本仓库//device/raspberrypi/目录下的文件修改和同目录下的README.md文档

6、init_lite部分

修改//base/startup/init_lite/services/BUILD.gn 文件,增加下面一句:

# init etc files group
ohos_prebuilt_etc("init.cfg") {
source = "//base/startup/init_lite/services/etc/init.cfg"
#add for rpi4b begin:
if( product_name == "rpi4b" ) {
source = "//base/startup/init_lite/services/etc/rpi4b_init_cfg/init.cfg"
}
#add for rpi4b end.
part_name = "init"
}

//base/startup/init_lite/services/etc/目录下增加 “rpi4b_init_cfg/”目录,将同目录系的init.cfg文件拷贝进去,并做修改。

7、drivers部分

把//drivers/peripheral/camera/hal/adapter/chipset/gni/ 目录下的camera.rpi3.gni拷贝一份,并重命名为camera.rpi4b.gni,内容不需要修改。

8、kernel部分

(1)//kernel/linux/ 内核代码部分

Linux内核,不用OHOS自带的 linux-5.10 源代码,而是用RaspberryPi官方的5.10版本源代码,这样可以免去内核部分的移植工作。

在 //kernel/linux/ 目录下创建 “linux-5.10-rpi4b” 目录,把RaspberryPi官方的5.10分支内核源代码,下载到该目录下:

git clone https://github.com/raspberrypi/linux linux-5.10-rpi4b

如果无法通过github下载,那就在gitee上搜索同版本的镜像代码下载回来使用也可以。

(2)//kernel/linux/build/ 编译脚本部分

OHOS内核默认编译生成 uImage,rpi4b 需要修改编译生成 zImage。

BUILD.gn 文件内:

增加下面两处对(device_name == “rpi4b”)的判断和修改,可以让rpi4b产品选用 8.1 中下载的“linux-5.10-rpi4b”内核源代码去生成zImage镜像文件。

if (device_name == "rpi4b") {
kernel_source_dir = "//kernel/linux/$linux_kernel_version-$device_name"
}
......
if (device_name == "rpi4b") {
outputs = [ "$root_build_dir/packages/phone/images/zImage" ]
} else {
outputs = [ "$root_build_dir/packages/phone/images/uImage" ]
}

build_kernel.sh 文件内:

if [ "$7" == "rpi4b" ];then
# 将zImage、dtb、overlays、modules拷贝到images目录下备用
cp ${2}/kernel/src_tmp/${8}/arch/arm/boot/zImage ${3}/zImage
cp ${2}/kernel/src_tmp/${8}/arch/arm/boot/dts/bcm2711-rpi-4-b.dtb ${3}/
cp -r ${2}/kernel/src_tmp/${8}/arch/arm/boot/dts/overlays ${3}/
cp -r ${2}/kernel/src_tmp/${8}/modules ${3}/
# 删除modules下的两个软链接,否则在制作img阶段会把软链接的内容一并拷贝,会出现异常。
rm ${3}/modules/lib/modules/5.10*/build
rm ${3}/modules/lib/modules/5.10*/source
else
#if [ "$7" == "hi3516dv300" ];then
cp ${2}/kernel/src_tmp/${8}/arch/arm/boot/uImage ${3}/uImage
fi

#在上述操作中拷贝的modules目录,将会被拷贝到//out/ohos-arm-release/packages/phone/system/lib/目录下,一并被打包到system.img内,烧录到SD卡里,系统启动时会insmod其中的部分模块。

kernel_module_build.sh 文件内:

if [ "$5" == "rpi4b" ];then
LINUX_KERNEL_UIMAGE_FILE=${LINUX_KERNEL_OUT}/arch/arm/boot/zImage
else
LINUX_KERNEL_UIMAGE_FILE=${LINUX_KERNEL_OUT}/arch/arm/boot/uImage
fi

kernel.mk 文件内:

从上到下的修改(请搜索关键字“rpi4b”):

  1. 增加编译modules的安装路径:
KERNEL_SRC_TMP_PATH := $(OUT_DIR)/kernel/src_tmp/${KERNEL_VERSION}
ifeq ($(DEVICE_NAME), rpi4b)
KERNEL_MODULES_PATH := $(OUT_DIR)/kernel/src_tmp/${KERNEL_VERSION}/modules
endif
  1. 修改内核源代码路径:
ifeq ($(DEVICE_NAME), rpi4b)
KERNEL_SRC_PATH := $(OHOS_BUILD_HOME)/kernel/linux/${KERNEL_VERSION}-${DEVICE_NAME}
else
KERNEL_SRC_PATH := $(OHOS_BUILD_HOME)/kernel/linux/${KERNEL_VERSION}
endif
  1. 修改编译内核的工具链:

OHOS默认使用 arm-linux-gnueabi 编译工具来编译Linux内核,用这个编译rpi4b使用的内核也可以。

但建议用RaspberryPi官方推荐的 arm-linux-gnueabihf 编译工具来编译内核(32位系统)。

请先执行 “sudo apt install crossbuild-essential-armhf ” 将编译工具安装到默认的 /usr/bin/ 目录下,然后修改编译工具链:

ifeq ($(DEVICE_NAME), rpi4b)
KERNEL_TARGET_TOOLCHAIN := /usr/bin
KERNEL_TARGET_TOOLCHAIN_PREFIX := $(KERNEL_TARGET_TOOLCHAIN)/arm-linux-gnueabihf-
else
KERNEL_TARGET_TOOLCHAIN := $(PREBUILTS_GCC_DIR)/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin
KERNEL_TARGET_TOOLCHAIN_PREFIX := $(KERNEL_TARGET_TOOLCHAIN)/arm-linux-gnueabi-
endif
  1. 修改编译目标:
ifeq ($(DEVICE_NAME), rpi4b)
KERNEL_IMAGE_FILE := $(KERNEL_SRC_TMP_PATH)/arch/arm/boot/zImage
else
KERNEL_IMAGE_FILE := $(KERNEL_SRC_TMP_PATH)/arch/arm/boot/uImage
endif
  1. 修改make命令的编译目标、安装modules到INSTALL_MOD_PATH指定的位置:
ifeq ($(DEVICE_NAME), rpi4b)
$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) -j64 zImage modules dtbs
$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) -j64 INSTALL_MOD_PATH=$(KERNEL_MODULES_PATH) modules_install
else
$(hide) $(KERNEL_MAKE) -C $(KERNEL_SRC_TMP_PATH) ARCH=$(KERNEL_ARCH) $(KERNEL_CROSS_COMPILE) -j64 uImage
endif

(3)//kernel/linux/config/ 编译配置部分

//kernel/linux/linux-5.10-rpi4b/arch/arm/configs/bcm2711_defconfig

将上述文件拷贝并改名到:

//kernel/linux/config/linux-5.10/arch/arm/configs/rpi4b_standard_defconfig

在该文件内增加Android Binder、OHOS HDF、Security部分的配置,详细配置的开关,见本仓库上述路径下的文件,这些配置可根据实际情况微调。

另外,为避免OHOS HDF的USB部分编译失败,需将 rpi4b_standard_defconfig 文件内的:

“CONFIG_USB_CONFIGFS=m”

修改为:

“CONFIG_USB_CONFIGFS=y”

将该模块直接编译进内核。

其他默认编译成模块的部分如:

CONFIG_DRM=m
...
CONFIG_DRM_V3D=m
CONFIG_DRM_VC4=m

等,可先保持不动,我们会在”5.device部分“的“init.rpi4b.cfg”文件中加载相应的模块起来运行即可。

或者在这里将相应的CONFIG_XXX配置成“=y”,直接将其编译进内核,则在”5.device部分“ 的 “init.rpi4b.cfg” 文件中就不需要 insmod 了。

(4)//kernel/linux/patches/ 编译补丁部分

//kernel/linux/patches/linux-5.10/rpi4b_patch/目录下两个patch文件。

hdf.patch 文件拷贝自 …/hi3516dv300_patch/hdf.patch,完全不用修改。

rpi4b.patch 文件原本应该是OHOS移植到rpi4b平台上所需要的大量适配代码的patch,但因为目前使用的kernel 代码是RaspberryPi官方的内核,已经包含所有的适配代码了,因此rpi4b.patch可以留空,这里是直接拷贝 hi3516dv300_small.patch,并做简单处理:

diff --git a/include/uapi/linux/android/binder.h b/include/uapi/linux/android/binder.h
index ec84ad106568..9d7b05055726 100644
--- a/include/uapi/linux/android/binder.h
+++ b/include/uapi/linux/android/binder.h
@@ -27,6 +27,7 @@
#define B_PACK_CHARS(c1, c2, c3, c4) \
((((c1)<<24)) | (((c2)<<16)) | (((c3)<<8)) | (c4))
#define B_TYPE_LARGE 0x85
+
enum {
BINDER_TYPE_BINDER = B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE),

9、third_party部分

(1)eudev

//third_party/eudev/rules.d/touchscreen.rules 文件的修改。

Raspberry Pi 4B的触碰显示屏,有多个硬件方案,不同方案需要加载不同的驱动程序。

对于我的Raspberry Pi 4B开发板,在Raspberry Pi 4B上运行官方系统时,通过查看触屏的设备信息和驱动程序(驱动程序用于insmod,或者在编译内核时直接编译进去),看到有"vc4"和"generic ft5x06 (79)"两个,把它们都加进rules文件中去。这一步需要请小伙伴们根据自己的触屏设备的实际信息修改和添加:

ATTRS{name}=="vc4", ENV{ID_INPUT}="1", ENV{ID_INPUT_TOUCHSCREEN}="1"
ATTRS{name}=="generic ft5x06 (79)", ENV{ID_INPUT}="1", ENV{ID_INPUT_TOUCHSCREEN}="1"
......

(2)weston.ini

//third_party/weston/weston.ini 文件的修改。

在我的环境下,不改这个文件,显示屏也会有正常显示,但是触屏的触碰输入功能会失效,必须要在此文件末尾增加如下修改,触碰输入功能才会正常。

[output]
name=card0
#name=HDMI-A-1

注意:如果Raspberry Pi 4B不带(或不接)触屏,则要把HDMI设备接到HDMI0端口上,再把上面的name字段设置为“HDMI-A-1”即可。如果HDMI设备接到HDMI1端口上,则只会在开机阶段显示终端上的log,weston运行起来之后会无输出了。

10、build 部分

(1)打包modules到system.img

修改 //build/ohos/images/build_image.py 脚本:

def _prepare_root(system_path):
......
os.symlink('/system/bin', os.path.join(root_dir, 'bin'))
os.symlink('/system/bin/init', os.path.join(root_dir, 'init'))
os.symlink('/system/etc', os.path.join(root_dir, 'etc'))
#rpi4b added begin:
# if modules_src exists:
# copy .../phone/images/modules/lib/modules to .../system/lib/modules
modules_src = os.path.join(system_path, "../images/modules/lib/modules")
if os.path.exists(modules_src):
modules_dest = os.path.join(system_path, 'lib/modules')
shutil.rmtree(modules_dest, ignore_errors=True)
shutil.copytree(modules_src, modules_dest, symlinks=True)
os.symlink('/system/lib', os.path.join(root_dir, 'lib'))
#rpi4b added end.

在 _prepare_root 函数末尾增加这几句话,把modules部分拷贝到system对应目录下,一并生成到system.img 镜像内,并生成 /lib 到 /system/lib 的软链接。【Hi3516DV300项目会因为不存在modules_src目录而不会跑拷贝的步骤】。

修改 //build/ohos/images/mkimage/dac.txt 文件,增加两句:

# dir
system/lib/modules, 00751, 0, 2000, 0
# file
system/lib/modules/*, 00755, 0, 2000, 0

为了让system.img、vendor.img、userdata.img镜像不至于太大,修改 //build/ohos/images/mkimage/ 目录下的:

system_image_conf.txt 文件【本文件实际可不改】:

-1610612224
+536869888

​vendor_image_conf.txt 文件大小不改。

userdata_image_conf.txt 文件【本文件实际可不改】:

-1468006400
+268434944

(2)编译rpi4b产品

代码根目录下执行:

./build.sh --product-name rpi4b --ccache

即可开始编译rpi4b产品。

11、生成分离的烧录镜像

编译成功,生成的镜像有:zImage、system.img、vendor.img、userdata.img 这四个用于本项目的烧录,updater.img 镜像可先不管。

根据8.2的编译内核的脚本的更改,zImage、dtb、overlays、modules会被拷贝到images目录下。

根据10.1的打包镜像脚本的更改,modules会被拷贝到…/system/lib/modules/目录下,一并打包进system.img 里。

如果你已有烧录了Raspberry Pi官方系统的SD卡,可以保持上面的/boot分区不动,把这里的zImage拷贝进去,在config.txt文件中修改启动的内核为:kernel=zImage。

再在Linux下用fdisk命令,删除/rootfs分区,并重新建立三个主分区,分区大小建议大于 10.1 中修改的各分区镜像大小即可。再用dd命令分别将 system.img、vendor.img、userdata.img 三个镜像烧录到SD卡的mmcblk0p2、mmcblk0p3、mmcblk0p4 分区即可。

注意分区的烧录位置,system.img一定要烧录到mmcblk0p2分区,因为在/boot分区的cmdline.txt中指定了root分区的位置为 /dev/mmcblk0p2。

vendor.img和userdata.img两个镜像分别烧录到mmcblk0p3、mmcblk0p4分区。在 /system/etc/init.cfg 中有:

"mount ext4 /dev/block/mmcblk0p3 /vendor wait rdonly barrier=1",
"mount ext4 /dev/block/mmcblk0p4 /data wait nosuid nodev noatime barrier=1,data=ordered,noauto_da_alloc"

会把它们分别挂载到/vendor和/data下。

12、生成合并的ohos_rpi4b.img烧录镜像

如果想要生成合并的系统镜像,可以参考并使用亮子力的脚本,见仓库:​​harmony-raspberry: 移植鸿蒙Harmony到树莓派 (gitee.com)​​ 内的使用说明。

​本地步骤如下:

(1)整体拷贝烧录官方rpi4b系统的SD卡的boot分区内容到://device/raspberrypi/rpi4b/build/boot/ 目录下。

(2)根据实际情况修改 cmdline.txt 中的root字段:

... root=/dev/mmcblk0p2 ...

(3)修改 config.txt 文件,将启动的内核镜像修改为 zImage:

# which kernel to boot
kernel=zImage
# 启用fake KMS,而不是原来的vc4-kms-v3d
dtoverlay=vc4-fkms-v3d

(4)创建 //device/raspberrypi/mkimg/目录,把亮子力的仓库中的:

​https://gitee.com/liangzili/harmony-raspberry/blob/master/rpi4b/device/raspberrypi/images/​

目录下的脚本拷贝到此目录下(实际只需要mkboot.py 和 mergeImg.sh)。

在项目代码根目录下执行mkboot.py脚本命令,以生成 boot.img 镜像:

python device/raspberrypi/mkimg/mkboot.py --input-path ./out/ohos-arm-release/packages/phone --output-image ./out/ohos-arm-release/packages/phone/images/boot.img

在项目代码根目录下执行mergeImg.sh脚本命令,以生成 ohos_rpi4b.img 镜像:

./device/raspberrypi/mkimg/mergeImg.sh ./out/ohos-arm-release/packages/phone/images/boot.img ./out/ohos-arm-release/packages/phone/images/system.img ./out/ohos-arm-release/packages/phone/images/vendor.img ./out/ohos-arm-release/packages/phone/images/userdata.img ./out/ohos-arm-release/packages/phone/images/ohos_rpi4b.img

将 ohos_rpi4b.img 拷贝到Windows系统硬盘下,通过RaspberryPi官方的Imager烧录工具将其烧录到SD卡即可。

以后再修改代码和编译OHOS后:

  • 如只涉及内核的修改(不涉及modules的动态加载),可直接将新生成的zImage文件拷贝并替换SD卡内的boot分区中的zImage文件(或相关文件)即可。
  • 如只涉及system分区内容的相关修改(包括涉及modules的动态加载),可直接在Linux命令行下,使用 “dd” 命令单独烧录system.img镜像到SD卡的 /dev/mmcblk0p2 分区即可,不需要重新打包成ohos_rpi4b.img 和重新烧录全部分区了。
  • 默认的vendor分区和userdata分区,目前没有什么重要内容需要在rpi4b开发板上用到,但这两个分区会默认挂载到根目录下,暂没必要重复烧录。

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​​。

责任编辑:jianghua 来源: 鸿蒙社区
相关推荐

2022-04-15 14:31:02

鸿蒙操作系统

2022-06-16 10:53:22

SUSELinuxopenEuler

2022-06-09 14:40:14

系统移植鸿蒙

2022-04-07 15:28:16

HarmonyOS鸿蒙操作系统

2022-06-05 08:12:56

LinuxLinux Lite浏览器

2022-06-01 17:30:06

UbuntuKVM虚拟化

2022-04-27 12:35:42

Unity7桌面环境Ubuntu

2022-04-25 20:52:22

UbuntuLinux

2022-05-11 15:08:52

驱动开发系统移植

2022-04-19 12:21:58

开源技术

2022-04-25 09:39:42

桌面服务器Linux

2022-02-09 19:45:41

2022-06-03 09:41:03

DockerKubernetes容器

2022-05-13 10:24:44

WineWindowsLinux

2022-05-20 13:46:36

Linux激活Linux水印

2022-05-10 11:12:09

容器容器安全

2022-05-26 15:02:35

Docker容器云原生

2022-03-02 09:53:44

开源ZabbixCentOS 7

2022-04-28 15:55:49

鸿蒙XTS认证测试

2022-02-14 13:52:04

同话题下的热门内容

HarmonyOS - HDC命令与ADB命令使用对比OHOS构建自定义服务实战啃论文俱乐部—数据密集型应用内存压缩HarmonyOS - 自定义组件之计时器基于OpenHarmony3.1的购物车应用的实现HarmonyOS - 方舟开发框架ArkUI 流光按钮效果OpenHarmony3.1-Ace-Formcomponent源码解析OpenHarmony HiSysEvent打点调用实践(L2)

编辑推荐

HarmonyOS 2.0鸿蒙第二期开发者Beta公测申请指南HarmonyOS LYEVK-3861开发板播放《蜜雪冰城》鸿蒙HarmonyOS分布式软总线:构建低时延、高带宽的多设备虚拟网络华为HarmonyOS的强势突围: 直面物联网迷宫的蓄力进击鸿蒙HarmonyOS2.0发布会现场回忆录
我收藏的内容
点赞
收藏

51CTO技术栈公众号