1# 一种快速移植OpenHarmony Linux内核的方法 2 3 4## 移植概述 5 6 7本文面向希望将OpenHarmony移植到三方芯片平台硬件的开发者,介绍一种借助三方芯片平台自带Linux内核的现有能力,快速移植OpenHarmony到三方芯片平台的方法。 8 9 10## 移植到三方芯片平台的整体思路 11 12 13### 内核态层和用户态层 14 15为了更好的解释整个内核移植,首先需要介绍一些概念: 16 17我们可以把OpenHarmony简单的分为 18 19OpenHarmony = OpenHarmony内核态层 + OpenHarmony用户态层 20 21![zh-cn_image_0000001167753296](figures/zh-cn_image_0000001167753296.png) 22 23其中OpenHarmony内核层就是上图的紫色部分,可以看到,它主要由内核本身(如Linux Kernel,LiteOS),和一些运行在内核态的一些特性组成,比如HDF等。 24 25而OpenHarmony用户态层,在上图,就是紫色之外的部分。可以看到,由下往上看,它主要由系统服务层,框架层,应用层组成。在这儿我们将这三层整体称为“OpenHarmony用户态层”。 26 27为什么这么区分呢?因为我们这篇文章主要是要讨论如何快速的把OpenHarmony移植到三方芯片平台上。而OpenHarmony的用户态层,整体来说和三方芯片平台的耦合度不高,移植较为方便。而内核态层中的内核本身以及HDF驱动框架等,和三方芯片平台的耦合度较高,是移植的重难点。我们先做这个区分,就是为了先把聚光灯打到我们最需要关注的OpenHarmony内核态层上,开始分析和解题。另外说明,本文只包含Linux内核的快速移植,不包含LiteOS的移植。 28 29 30### 获得内核态层的两种方法 31 32为了表述方便,我们在下文部分地方用“OH”代替“OpenHarmony”。 33 34将OH内核态层继续分解 35 36OH内核态层 = OH Linux内核 + OH内核态特性(可选特性或者必选特性,如必选特性HDF,今后的可选特性HMDFS等) 37 38而OH Linux内核 = 标准LTS Linux 内核 + 三方SoC芯片平台代码 + OH内核态基础代码(支撑OH用户态层运行的最基础代码) 39 40因此OH内核态层 = 标准LTS Linux 内核 + 三方SoC芯片平台代码 + OH内核态基础代码 + OH内核态特性(如HDF) 41 42![zh-cn_image_0000001210623027](figures/zh-cn_image_0000001210623027.png) 43 44而将前两项组合,标准LTS Linux 内核 + 三方SoC芯片平台代码,其实就是一个三方Linux内核的基础组成。从上面的推导可以看出,OpenHarmony 内核态层其实能够由两种方法得到: 45 46方法一:OH 内核态层 = 三方Linux内核 + OH内核态基础代码 + OH内核态特性(如HDF,今后的HMDFS等) 47 48也就是直接借助三方Linux内核,再加上基础OH内核态基础代码、以及HDF等OH内核态特性。 49 50方法二:OH 内核态层 = OH Linux内核 + OH内核态特性(如HDF,今后的HMDFS等) 51 52也就是直接采用OHLinux内核,然后再加入OH的其他内核态特性。 53 54当前方法二中OHLinux内核支持的三方芯片平台还不够丰富。为了能够响应三方开发者快速移植OpenHarmony的要求,下文会着重介绍方法一,即借助三方已有的Linux内核,来快速移植OpenHarmony。 55 56 57### **借助已有Linux内核来移植OpenHarmony的流程** 58 59 60整个移植流程可以分为三步: 61 62 631. 准备整体构建环境,包括将三方芯片平台的现有内核代码拷贝到OpenHarmony的整体编译环境下。 64 652. OpenHarmony内核态基础代码的移植。 66 673. OpenHarmony内核态必选特性(如HDF等)的移植。 68 69 70详细步骤在接下来的章节中介绍。 71 72 73## 移植到三方芯片平台的步骤 74 75下面以树莓派3b (BCM2837) 为例,演示将OpenHarmony移植到树莓派的过程。 76 77 78### 准备整体构建环境 79 801. 将三方内核纳入OpenHarmony编译环境。 81 完整编译过一遍标准Hi3516DV300的内核之后,clone树莓派内核源码并复制到manifest输出目录下: 82 83 84 ``` 85 export PROJ_ROOT=[OpenHarmony manifest] 86 git clone https://gitee.com/xfan1024/oh-rpi3b-kernel.git 87 cp -r oh-rpi3b-kernel $PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b 88 ``` 89 902. 配置树莓派内核编译环境。 91 92 ``` 93 # 进入树莓派kernel目录 94 cd out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b 95 96 # 配置编译环境,使用工程项目自带的clang 97 export PATH=$PROJ_ROOT/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PROJ_ROOT/prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/bin/:$PATH 98 export MAKE_OPTIONS="ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- CC=clang HOSTCC=clang" 99 export PRODUCT_PATH=vendor/hisilicon/hispark_taurus_linux 100 ``` 101 1023. 注释掉clang不识别的flag。 103 PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b/arch/arm/Makefile注释掉以下这一行: 104 105 106 ``` 107 KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog 108 ``` 109 110 111### 移植内核态基础代码 112 113目前OpenHarmony内核态的基础代码,主要是日志服务相关。轻量化内核日志服务代码包含: 114 115 116``` 117drivers/staging/hilog 118drivers/staging/hievent 119``` 120 121将以上代码,从OpenHarmony内核代码目录kernel/linux/linux-4.19/drivers/staging中,拷贝到out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b/drivers/staging下。 122 123在三方内核的drivers/staging/Kconfig文件内增加如下代码: 124 125 126``` 127source "drivers/staging/hilog/Kconfig" 128source "drivers/staging/hievent/Kconfig" 129``` 130 131在三方内核的drivers/staging/Makefile文件内增加如下代码: 132``` 133obj-$(CONFIG_HILOG) += hilog/ 134obj-$(CONFIG_HIEVENT) += hievent/ 135``` 136 137在内核config项中打开对应的CONFIG控制宏:CONFIG_HILOG和CONFIG_HIEVENT。 138 139具体日志使用说明请参见:[Hilog_lite组件介绍](https://gitee.com/openharmony/hiviewdfx_hilog_lite/blob/master/README_zh.md)。 140 141 142### 移植内核态必选特性HDF 143 1441. 打HDF补丁。 145 在Linux内核打HDF补丁时,执行补丁shell脚本合入HDF补丁。 146 147 1. 配置HDF补丁脚本的四个变量参数。 148 2. 获取patch_hdf.sh脚本。 149 3. 执行patch_hdf.sh脚本依次传入四个变量参数。 150 151 patch_hdf.sh脚本四个参数含义为:第一个入参为工程根目录路径,第二入参为内核目录路径,第三个入参为内核版本路径,第四个参数是当前设备名。 152 153 154 ``` 155 ./patch_hdf.sh [工程根目录路径] [内核目录路径] [内核补丁路径] [设备名] 156 ``` 157 158 以树莓派3b为示例介绍: 159 160 161 ``` 162 # 进入树莓派kernel目录 163 PROJ_ROOT/drivers/adapter/khdf/linux/patch_hdf.sh \ 164 PROJ_ROOT # 指定工程根目录路径 \ 165 PROJ_ROOT/out/KERNEL_OBJ/kernel/src_tmp/linux-rpi3b # 打补丁的内核目录路径 \ 166 PROJ_ROOT/kernel/linux/patches/linux-4.19 # 内核补丁路径.\ 167 hi3516dv300 # 设备名. 168 ``` 169 1702. 配置config。 171 提供HDF基本配置,如果需要其他功能,通过menuconfig打开对应驱动开关即可。 172 173 HDF补丁执行成功后,默认HDF开关是关闭的,打开HDF基本配置选项如下: 174 175 176 ``` 177 CONFIG_DRIVERS_HDF=y 178 CONFIG_HDF_SUPPORT_LEVEL=2 179 CONFIG_DRIVERS_HDF_PLATFORM=y 180 CONFIG_DRIVERS_HDF_PLATFORM_MIPI_DSI=y 181 CONFIG_DRIVERS_HDF_PLATFORM_GPIO=y 182 CONFIG_DRIVERS_HDF_PLATFORM_I2C=y 183 CONFIG_DRIVERS_HDF_PLATFORM_UART=y 184 CONFIG_DRIVERS_HDF_TEST=y 185 ``` 186 187 或者通过menuconfig界面打开HDF相关配置,命令如下: 188 189 190 ``` 191 # 生成 .config 配置文件 192 make ${MAKE_OPTIONS} rpi3b_oh_defconfig 193 194 # 更改HDF内核配置 195 make ${MAKE_OPTIONS} menuconfig 196 # [*] Device Drivers 197 # [*] HDF driver framework support ---> 198 ``` 199 200 配置如下(在Device Drivers -> HDF driver framework support 目录下): 201 202 ![zh-cn_image_0000001208524821](figures/zh-cn_image_0000001208524821.png) 203 204 205### 编译Image 206 207 208``` 209# 执行编译命令 210make ${MAKE_OPTIONS} -j33 zImage 211``` 212 213 214### 编译和运行HDF测试用例(可选) 215 216**简介** 217 218HDF(Hardware Driver Foundation)自测试用例,用于测试HDF框架和外设的基本功能,本文主要介绍HDF内核态用例测试方法。 219 220**预置条件** 221 222测试前需要在menuconfig里检查HDF测试开关CONFIG_DRIVERS_HDF_TEST=y,代码全量编译通过。 223 224**用例编译和测试方法** 225 226 通过[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md)把用例执行文件推送到设备中,然后执行用例即可,操作步骤如下: 2271. 编译hdf测试用例。 228 2292. 用hdc_std工具推送测试文件到设备中。 230 2313. 进入设备data/test目录,执行测试文件即可。 232 233用例编译和测试详细步骤如下: 234 2351. 编译hdf测试用例。 236 编译hdf测试用例命令和文件路径如下: 237 238 239 ``` 240 ./build.sh --product-name hispark_taurus_standard --build-target hdf_test 241 ``` 242 243 等待编译完成。 244 2452. 将测试文件移动到目标移植设备上(以树莓派为例)。 246 247 方法一:使用[hdc_std工具](../subsystems/subsys-toolchain-hdc-guide.md)。 248 249 1. 先在树莓派里新建data/test目录。 250 251 ``` 252 mkdir -p data/test 253 ``` 254 2. 推送依赖库和测试用例到树莓派。 255 256 ``` 257 hdc file send XXX\out\{device_name}\hdf\hdf\libhdf_test_common.z.so /system/lib 258 hdc file send XXX\out\{device_name}\tests\unittest\hdf\config\hdf_adapter_uhdf_test_config /data/test 259 hdc file send XXX\out\{device_name}\tests\unittest\hdf\devmgr\DevMgrTest /data/test 260 hdc file send XXX\out\{device_name}\tests\unittest\hdf\osal\OsalTest /data/test 261 hdc file send XXX\out\{device_name}\tests\unittest\hdf\sbuf\SbufTest /data/test 262 ``` 263 264 方法二:移动到储存卡内,启动树莓派之后装载。 265 266 1. 拔掉树莓派连接电脑的串口、USB线,然后拔下数据卡。 267 2. 将数据卡插入到电脑的读取口,将编译好的zImage和测试文件夹test/下载到电脑,然后移动到数据卡的根目录下。zImage文件会被替换,请提前做好备份。 268 3. 最后将数据卡插回树莓派。 269 270 ``` 271 # 让树莓派文件系统读取储存卡根目录 272 mount -t vfat /dev/block/mmcblk0p1 /boot 273 cd /boot/[测试文件目录] 274 # 允许修改系统文件 275 mount -o remount,rw / 276 # 安装测试用库 277 mv libhdf_test_common.z.so /system/lib 278 mkdir /data/test 279 mv * /data/test 280 ``` 281 2823. 执行测试 283 1. 进入目录执行测试文件目录data/test。 284 285 ``` 286 cd /data/test 287 ``` 288 2. 修改文件执行权限。 289 290 ``` 291 chmod 777 hdf_adapter_uhdf_test_config DevMgrTest OsalTest SbufTest 292 ``` 293 3. 开始测试。 294 295 ``` 296 ./hdf_adapter_uhdf_test_config 297 ./DevMgrTest 298 ./OsalTest 299 ./SbufTest 300 ``` 301 4. 如果所有测试文件输出均显示 PASSED,那么HDF功能即安装成功。 302 示例:DevMgrTest用例成功结果显示: 303 304 ``` 305 ./DevMgrTest 306 Running main() from gmock_main.cc 307 [==========] Running 1 test from 1 test case. 308 [----------] Global test environment set-up. 309 [----------] 1 test from DevMgrTest 310 [ RUN ] DevMgrTest.DriverLoaderTest_001 311 [ OK ] DevMgrTest.DriverLoaderTest_001 (0 ms) 312 [----------] 1 test from DevMgrTest (0 ms total) 313 [----------] Global test environment tear-down 314 Gtest xml output finished 315 [==========] 1 test from 1 test case ran. (0 ms total) 316 [ PASSED ] 1 test. 317 ``` 318