# openharmony_raspberry **Repository Path**: wuyunhu1/openharmony_raspberry ## Basic Information - **Project Name**: openharmony_raspberry - **Description**: oh3.2beta1移植到树莓派4b - **Primary Language**: C - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2023-09-08 - **Last Updated**: 2023-12-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ### OH3.2beta1移植到树莓派4b步骤 参考: - https://ost.51cto.com/posts/14280 - https://ost.51cto.com/posts/9473 - https://gitee.com/liangzili/harmony-raspberry OH的内核特性补丁通过OH社区获取: - https://gitee.com/openharmony/kernel_linux_5.10 ### 1.适配编译框架,加入树莓派的配置 要新建树莓派的vendor、divece_soc、board_board加入到相应的目录下,参考别的开发板目录再做一些修改,我做好了的在码仓里了 ### 1.1 vendor 在vendor目录下新建raspberrypi/rpi4目录,目录结构参考海思的(vendor/hisilicon/hispark_taurus_standard) 主要更改config.json文件:更改下基本的配置参数,产品子系统名字,最重要的是把kernel这个子系统去掉,要不然会报一个缺少sdk.json文件的错误,我看rk3568也没有用到这个子系统,就给它去掉就行了 基本参数的更改 ``` "product_name": "rpi4", "target_cpu": "arm", "type": "standard", "ohos_version": "OpenHarmony3.2Beta1", "version": "3.0", "board": "rpi4", "device_company": "raspberrypi", "enable_ramdisk": false, ``` 把海思的products子系统改成树莓派的名字 ``` "subsystem": "raspberrypi_products", "components": [ { "component": "raspberrypi_products", "features": [] } ] ``` 然后把kernel这个子系统去掉 ``` "subsystem": "kernel", "components": [ { "component": "linux", "features": [] } ] ``` 然后更改下product.gni文件,就是改下路径 `import("//device/board/${device_company}/${device_name}/device.gni")` ### 1.2 device/board board目录参考rk3568的目录,新建board/raspberrypi/rpi4目录,然后删除一些没用的构建配置,可参考我的board目录,gn中也就用到了cfg和kernel两个目录,留着camera(好像用到了,没深究),其他的删除就行了,patches目录用来存放hdf补丁和内核特性补丁,images用于编译完了后生成boot.img和firmware.img,这个到打包的时候再说 先更改下board/raspberrypi/rpi4下面的gn文件,只保留这两个deps就行了,cfg用来分区的 ``` import("//build/ohos.gni") group("rpi4_group") { deps = [ "cfg:init_configs", "kernel:rpi4_kernel", ] } ``` 然后更改board/raspberrypi/rpi4/device.gni,主要更改这两行,然后路径名称什么的改成自己的就可以了 ``` soc_company = "broadcom" soc_name = "bcm2711" ``` 再更改下ohos.build ``` { "subsystem": "raspberrypi_products", "parts": { "raspberrypi_products": { "module_list": [ "//device/board/raspberrypi/${device_name}:rpi4_group" ], "test_list": [ "//kernel/linux/build/test:linuxkerneltest" ] } } } ``` 这个根据名字改一下,然后这个rpi4_group要和gn里的group那个名字对起来,test_list这个其实删掉就行,没用到 然后更改下cfg目录下的文件,主要更改下文件的名字,改成rpi4的 ``` cfg ├── BUILD.gn ├── fstab.required ├── fstab.rpi4 ├── init.rpi4.cfg ├── init.rpi4.usb.cfg └── ramdisk_resource_config.ini ``` 更改下BUILD.gn,里面涉及的文件名字要自己改下,以及raspberrypi_products也要给他改过来 ``` ohos_prebuilt_etc("init.rpi4.cfg") { source = "init.rpi4.cfg" part_name = "raspberrypi_products" install_images = [ chipset_base_dir ] install_enable = true } ··· ``` 然后就是fstab.rpi4和fstab.required文件了,到时候内核回去找fstab.rpi4,这个会集成在vendor.img中,这两个文件都改成一样的就行了 ``` # fstab file. # #/dev/block/mmcblk0p2 /system ext4 ro,barrier=1 wait,required /dev/block/mmcblk0p3 /vendor ext4 ro,barrier=1 wait,required /dev/block/mmcblk0p4 /data ext4 nosuid,nodev,noatime,barrier=1,data=ordered,noauto_da_alloc wait,reservedsize=104857600 /dev/block/mmcblk0p5 /misc none none wait,required ``` 然后就是更改kernel目录了,这个比较重要,目录结构参考我的就可以了,configs目录下放了defconfig文件,用32的那个就可以,因为config.json文件中我们用的是arm架构,32位的。它之前默认的构建脚本build_kernel.sh不用了,删除就行,然后用到的脚本我解释一下作用,其余的没用到 - check_build.sh:作用不大的脚本,没实际作用,检查文件更新的 - check_patch.sh:打补丁脚本文件。将内核源码复制到out/kernel下,要在sh中将树莓派的源码路径和用到的KERNEL_SRC_PATH对应起来,这里直接用的别人提供好的hdf补丁直接打了,还调用了一个脚本打。内核补丁不用打,因为我们用的就是第三方的内核,他这个树莓派内核补丁是用在oh内核上的,所以打内核补丁的命令注释掉就可以了 ``` if [ ! -d "${KERNEL_SRC_TMP_PATH}" ];then mkdir -p ${KERNEL_SRC_TMP_PATH} cp -arfL ${KERNEL_SRC_PATH}/* ${KERNEL_SRC_TMP_PATH}/ cd ${KERNEL_SRC_TMP_PATH} #hdf patch 打入HDF补丁 bash ${PATCHES_PATH}/hdf_patch.sh ${PROJECT_ROOT} ${KERNEL_SRC_TMP_PATH} ${HDF_PATCH_FILE} #kernel patch #patch -p1 < ${KERNEL_PATCH} fi ``` - make_kernel.sh:调用执行make的脚本,并把zimage复制到images下 - make_kernel.mk:真正make的脚本,包含defconfig、image和dtb等 然后我说一下patches目录 - openharmony_kernel_patch.py:根据编号在社区补丁中下载内核特性补丁文件,然后进行git apply --check的验证,因为后边的补丁都是以前面的补丁为基础的,所以肯定会有很多错误输出,实际用的时候把验证的部分屏蔽就行了,只用来下载 - kernel-5.10:下载的补丁文件都会存到这个目录下 - hdf.patch和hdf_patch.sh:补丁和打补丁的脚本 ### 1.3 device/soc device/soc下新建broadcom目录,目录结构最好参考他的目录结构DAYU200的,虽然用的目录不多,但是可能在构建时因为相对目录的原因出现很多路径错误,其他soc的目录结构和他的还不太一样,不嫌麻烦的话可以自己改下,rk3568的也可以,这里更改的地方不多,主要修改下soc.gni,然后再修改下GN,以及各目录中的对应的名称。其中display里也需要改一些代码,到图形适配中再更改 ``` broadcom ├── bcm2711 │   └── soc.gni ├── common │   └── hal ├── hardware │   ├── BUILD.gn │   ├── display └── └── gpu ``` bcm2711/soc.gni: ``` usb_default_config_path = "//device/soc/broadcom/common/hal/usb/bcm2711/include" display_device_hal = "soc/broadcom/hardware" ``` ### 2.内核移植 在移植内核前先将三方树莓派内核源码单独编译一遍,保证内核能编译出来。然后将树莓派内核源码拉到OH3.2_Beta1的kernel源目录 我因为用的是第三方内核,我编译内核的思路: 1. 我把树莓派官方的内核源码linux-rpi-5.10复制到//kernel/linux下更名为linux-5.10作为源代码(记得保留一份oh的原始内核源码) 2. 在源代码目录先打上内核特性补丁(自己手打) 3. 然后执行构建,通过脚本打hdf补丁,然后编译内核(这个我试过了,先打内核特性补丁再打hdf补丁不会冲突) 具体步骤如下: 1. 先下载树莓派的5.10内核源码然后进行单独编译验证,然后复制到源码目录 ``` git clone --depth=1 -b rpi-5.10.y https://github.com/raspberrypi/linux.git linux-rpi-5.10 cd linux-rpi-5.10 KERNEL=kernel7 make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- bcm2711_defconfig make -j1024 #验证完可编译出内核后cp到源码目录,并保留下oh内核源码 mv ~/oh3.2_beta1/kernel/linux/linux-5.10 ~/oh3.2_beta1/kernel/linux/linux-5.10-oh cp -r linux-5.10-rpi ~/oh3.2_beta1/kernel/linux/ mv ~/oh3.2_beta1/kernel/linux/linux-5.10-rpi ~/oh3.2_beta1/kernel/linux/linux-5.10 ``` 2. 打内核特性补丁 使用如下命令下载内核特性补丁 `python ~/oh3.2_beta1/device/board/raspberrypi/rpi4/patchesopenharmony_kernel_patch.py` 脚本中有补丁序号列表,但hilog的补丁在社区没有,需要单独下载,保存为1.diff就行: https://gitee.com/openharmony/kernel_linux_5.10/commit/286181507c841fcc293a0a5761204bf8d8d79cc7 进入到内核根目录执行下列操作打补丁就可以了,建议打之前先--check,提前知道错误点在哪,然后再apply,顺序的话最好根据脚本里面的列表顺序,好像冲突少 这是一个没有冲突的操作示例 ``` git apply --check /home/wyh/oh3.2_beta1/device/board/raspberrypi/rpi4/patches/kernel-5.10/1.diff git apply /home/wyh/oh3.2_beta1/device/board/raspberrypi/rpi4/patches/kernel-5.10/1.diff ``` 然后这是一个有冲突的操作示例 ``` git apply --check /home/wyh/oh3.2_beta1/device/board/raspberrypi/rpi4/patches/kernel-5.10/1.diff error:xxxx无法应用补丁 git apply /home/wyh/oh3.2_beta1/device/board/raspberrypi/rpi4/patches/kernel-5.10/1.diff --reject ``` 直接git apply的话会由于这个冲突导致其他文件打不上补丁,因此需要加上--reject参数,让其他文件先打上补丁,然后自己根据rej文件自己去改。这样的话会在有冲突的文件同级目录下生成rej拒绝文件,打开rej文件查看一下怎么改就可以了,手动改一下,一般就几行,冲突不多,10个左右补丁文件有 3. 单独编译内核试试,看看补丁打完会不会出错 `sudo ./build.sh --product-name rpi4 --ccache --build-target rpi4_kernel` 注意,这个rpi4_kernel要和device/board/raspberrypi/rpi4/kernel/BUILD.gn中的group对应起来 然后可能会报一个错误 ``` [OHOS ERROR] mm/memcg_control.o: In function `memcg_force_swapin_write': [OHOS ERROR] memcg_control.c:(.text+0xc04): undefined reference to `__aeabi_ldivmod' [OHOS ERROR] mm/zswapd.o: In function `get_zram_current_watermark': [OHOS ERROR] zswapd.c:(.text+0x850): undefined reference to `__aeabi_uldivmod' [OHOS ERROR] mm/zswapd.o: In function `zram_watermark_ok': [OHOS ERROR] zswapd.c:(.text+0x96c): undefined reference to `__aeabi_uldivmod' [OHOS ERROR] mm/zswapd.o: In function `zram_watermark_diff': [OHOS ERROR] zswapd.c:(.text+0xd6c): undefined reference to `__aeabi_uldivmod' [OHOS ERROR] mm/zswapd.o: In function `zswapd': [OHOS ERROR] zswapd.c:(.text+0x13ec): undefined reference to `__aeabi_uldivmod' [OHOS ERROR] mm/zswapd.o: In function `zswapd_shrink_anon': [OHOS ERROR] zswapd.c:(.text+0x1fa0): undefined reference to `__aeabi_uldivmod' [OHOS ERROR] mm/zswapd.o:zswapd.c:(.text+0x2134): more undefined references to `__aeabi_uldivmod' follow ``` 这个错误是除法运算和建模用到的函数,编译器链接不到__aeabi_uldivmod和__aeabi_ldivmod这两个函数所在的库了,更改编译器参数配置的话进行链接不太好解决,所以解决方法如下: 在mm目录下新建__aeabi_uldivmod.c和__aeabi_ldivmod.c ``` __aeabi_ldivmod.c long long __aeabi_ldivmod(long long dividend, long long divisor) { long long quotient = dividend / divisor; long long remainder = dividend % divisor; return (quotient << 32) | (remainder & 0xFFFFFFFF); } __aeabi_uldivmod.c unsigned long long __aeabi_uldivmod(unsigned long long dividend, unsigned long long divisor, unsigned long long *remainder) { unsigned long long quotient = dividend / divisor; *remainder = dividend % divisor; return quotient; } ``` 然后更改下mm/Makefile ``` - obj-$(CONFIG_HYPERHOLD_ZSWAPD) += zswapd.o zswapd_control.o + obj-$(CONFIG_HYPERHOLD_ZSWAPD) += zswapd.o zswapd_control.o __aeabi_ldivmod.o __aeabi_uldivmod.o ``` 这样就可以在编译过程中链接上这两个函数了,然后就可以单独编译通过了,生成了zImage,内核的移植到这里就结束了 ### 适配图形显示 图形适配首先需要内核支持,先把驱动直接编译进内核,修改bcm2711_oh_32_defconfig https://ost.51cto.com/posts/9473 ``` CONFIG_KEYBOARD_GPIO=y CONFIG_TOUCHSCREEN_ADS7846=y CONFIG_TOUCHSCREEN_USB_COMPOSITE=y ``` 其实他这个defconfig的配置都已经都编译进内核了,不用make menuconfig自己去改了,上边那三个是另外追加的,应该没用到,还是改了吧 display下共有三类:device、gfx、gralloc bcm2711是没有2d加速功能的,所以display_gfx不用适配(gfx是管理硬件驱动加速的) 更改soc/hardware/display/src/display_device/drm/drm_device.cpp中的设备名称为“vc4” ``` std::shared_ptr DrmDevice::Create() { DISPLAY_LOGD(); if (mDrmFd == nullptr) { const std::string name("vc4"); ``` 修改//foundation/graphic/graphic/rosen/modules/render_service/BUILD.gn,添加自己的产品名rpi4 ``` ohos_shared_library("librender_service") { defines = [] if ("${product_name}" == "watchos" || "${product_name}" == "Hi3516DV300" || "${product_name}" == "ohos-arm64" || "${product_name}" == "ohos-sdk" || "${product_name}" == "qemu-arm-linux-min" || "${product_name}" == "rpi4" || "${product_name}" == "rk3566" || "${product_name}" == "rk3568") { defines += [] } else { defines += [ "PADDING_HEIGHT_32" ] } defines += gpu_defines ``` 到这里图形适配就完了,是不是简单到不可思议 ### 将镜像烧录至TF卡进行验证 在执行全量编译前还需要构建一下board/images/rpi4boot目录,用于生成boot.img,目录结构如下,gn文件用不到了,因为我们是全量编译完了后手动生成boot.img,所以用不到这个gn ``` images ├── build_bootimg.py ├── BUILD.gn ├── make_rpi_sdcard_image.py ├── ptgen ├── README.md └── rpi4boot ├── bcm2711-rpi-4-b.dtb ├── cmdline.txt ├── config.txt ├── fixup4.dat ├── overlays │   ├── rpi-backlight.dtbo │   ├── rpi-ft5406.dtbo │   └── vc4-fkms-v3d.dtbo └── start4.elf ``` - build_bootimg.py: 将rpi4boot目录打包整合,在//out/rpi4/packages/phone/images下生成boot.img - make_rpi_sdcard_image.py和ptgen: 他俩是联合使用的,用于将system.img、 vendor.img 、userdata.img 、boot.img生成可烧录固件firmware.img - rpi4boot目录: dtb和dtbo用自己编译出来的,fixup4.dat和start4.elf用给的就行,这东西在树莓派4b中都一样的,他俩是组合使用的,用于启动的时候读取 - cmdlinux.txt: `console=tty1 console=serial0,115200 no_console_suspend root=/dev/mmcblk0p2 rw rootfstype=ext4 elevator=deadline rootwait androidboot.selinux=permissive hardware=rpi4` - config.txt ``` hdmi_force_hotplug=1 hdmi_drive=2 hdmi_group=1 hdmi_mode=1 avoid_warnings=2 dtoverlay=vc4-fkms-v3d enable_uart=1 kernel=zImage uart_2ndstage=1 ``` | | | 都移植完成后输入命令进行全量编译,然后会生成system.img、 vendor.img 、userdata.img `sudo ./build.sh --product-name rpi4 --ccache` - build_bootimg.py的使用方法: `sudo python device/board/raspberrypi/rpi4/images/build_bootimg.py bootimg /home/wyh/oh3.2_beta1/out/rpi4/packages/phone` - make_rpi_sdcard_image.py和ptgen的使用方法为: 将//device/board/raspberrypi/rpi4/images/下的 ptgen 和 make_rpi_sdcard_image.py 复制到//out/rpi4/packages/phone/images/下,然后执行命令生成firmware.img `sudo python make_rpi_sdcard_image.py --output firmware.img --userdata 1000M boot.img system.img vendor.img userdata.img` 将生成的firmware.img拷贝到windows,然后用win32烧录工具进行烧录