积分311 / 贡献0

提问1答案被采纳1文章20

[经验分享] 开发板如何适配OpenHarmony3.2 精华

诚迈-陆志刚 显示全部楼层 发表于 2024-1-19 18:17:15
开发板如何适配OpenHarmony3.2

(文章已获得原作者诚迈科技高级技术专家-陆道授权)

简介

OpenHarmony3.2 Beta5 版本在 OpenHarmony 3.1 Release 版本的基础上,有以下改变:性能上有很大的提升、标准系统应用开发框架增强、标准系统分布式能力增强。
本文介绍诚迈科技基于RK3568设计的HCPAD-100开发板以及基于RK3566设计的中控屏HongzPad2022在OpenHarmony 3.2 Beta5 版本上的适配过程。
涉及到开发板的添加/u-boot /linux-5.10/分区表/根文件系统/显示/触摸/USB的移植过程以及 OpenHarmony 所依赖的驱动特性介绍。
如何添加新的开发板进行编译
参照DAYU200的工程配置文件我们新建自己的编译命令。

1)在device/board/目录新建archermind目录,新建rk3568/rk3588/rk3399目录,并添加相关的工程文件。
fakename.png

2)在vendor目录新建archermind目录。新建以下几个目录,并添加相关的工程文件。
fakename.png
3) 修改vendor/archermind/hongzos_rk3568/config.json文件,product_name改成hongzos_rk3568,device_build_path改成第一步新建的目录。
  1. {
  2.   "product_name": "hongzos_rk3568",
  3.   "device_company": "rockchip",
  4.   "device_build_path": "device/board/archermind/rk3568",
  5.   "target_cpu": "arm",
  6.   "type": "standard",
  7.   "version": "3.0",
  8.   "board": "rk3568",
复制代码
通过./build.sh --product-name hongzos_rk3568来编译出我们自己开发板的镜像,编译完后对应开发板的image镜像放在out/rk3568/packages/phone/目录。相关代码放在文章最后的参考链接。
U-Boot移植
U-boot是通过二进制镜像直接放在device/board/hihope/rk3568/loader目录下的,这个目录下涉及到文件如下
fakename.png

1)下载rk官方发布的uboot源码
  1. git clone https://github.com/rockchip-linux/u-boot.git
复制代码
2)修改make.sh, 指定RKBIN_TOOLS的路径

  1. RKBIN_TOOLS=rkbin/tools
复制代码
3)增加代码读取ramdisk分区到指定的内存位置,修改cmd/pxe.c

  1. include "boot_rkimg.h"
  2. #define BLK_CNT(_num_bytes, _block_size)        \
  3.                 ((_num_bytes + _block_size - 1) / _block_size)

  4. static char* load_ramdisk_from_partition(void *buffer)
  5. {
  6.         struct blk_desc *desc = rockchip_get_bootdev();
  7.         disk_partition_t part_ramdisk_boot;
  8.         static char initrd_str[28];
  9.         long blk_cnt = 0, blks_read = 0;
  10.         long blk_start = 0;
  11.         if (part_get_info_by_name(desc, "ramdisk", &part_ramdisk_boot) < 0) {
  12.                 printf("No ramdisk partition\n");
  13.                 return NULL;
  14.         }
  15.         blk_cnt = part_ramdisk_boot.size;
  16.         blk_start = part_ramdisk_boot.start;
  17.         printf("Load from partition ' ramdisk ' to address 0x%p, count: %ld total block(s) by ludao\n", buffer, blk_cnt);
  18.         blks_read = blk_dread(desc, blk_start, blk_cnt, buffer);
  19.         if (blks_read != blk_cnt) {
  20.              return NULL;
  21.         }
  22.         printf("Read from partition ' ramdisk ' done, from 0x%lx total block(s) 0x%lx\n", blk_start, blk_cnt);
  23.         sprintf(initrd_str, "0x%p:0x%lx", buffer, blk_cnt*(part_ramdisk_boot.blksz));
  24.         printf("Openharmony ramdisk_addr_r = %s\n", initrd_str);

  25.         return initrd_str;
  26. }
  27. static int label_boot(cmd_tbl_t *cmdtp, struct pxe_label *label)
  28.         if (label->initrd) {
  29.                 if (get_relfile_envaddr(cmdtp, label->initrd, "ramdisk_addr_r") < 0) {
  30.                         printf("Skipping %s for failure retrieving initrd\n",
  31.                                         label->name);
  32.                         return 1;
  33.                 }

  34.                 bootm_argv[2] = initrd_str;
  35.                 strncpy(bootm_argv[2], env_get("ramdisk_addr_r"), 18);
  36.                 strcat(bootm_argv[2], ":");
  37.                 strncat(bootm_argv[2], env_get("filesize"), 9);
  38.         }else{
  39.                 void *buffer = (void *)env_get_ulong("ramdisk_addr_r", 16, 0);
  40.                 bootm_argv[2] = load_ramdisk_from_partition(buffer);
  41.                 if(bootm_argv[2]){
  42.                     printk("initrd = %s \n", bootm_argv[2]);
  43.                 }
  44.         }
复制代码
4)指定交叉编译器和平台开始编译,编译完成后根目录会生成u-boot.bin

  1. ./make.sh CROSS_COMPILE=aarch64-linux-gnu- rk3568
复制代码
所有相关代码已经放到开源社区,大家可以下载下来直接编译使用,相关代码放在文章最后的参考链接。

linux-5.10移植

1)内核编译脚本
linux编译脚本的是放在device/board/hihope/rk3568/kernel目录下的build_kernel.sh文件,由于kernel/linux/linux-5.10是公共代码,OpenHarmony 编译脚本是通过打补丁的方式来适配不同平台,不同的平台有自己的内核补丁。
编译脚本会先把 kernel/linux/linux-5.10 拷贝到out/kernel/src_tmp/linux-5.10/,然后打上3568的内核补丁patch -p1 < kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch
后编译生成自己的镜像,不利于我们开发,我们自己开发过程中做如下修改,这样方便我们开发过程中的修改。
  1. 先进入kernel/linux/linux-5.10目录
  2. patch -p1 < kernel/linux/patches/linux-5.10/rk3568_patch/kernel.patch
  3. 修改device/board/hihope/rk3568/kernel/build_kernel.sh
  4. 注释掉
  5. //patch -p1 < ${KERNEL_PATCH}
复制代码
2)     设备树的定制,首先我们需要有自己的板子的设备树例如rk3568-chujue-linux.dts

  1. 把设备树放到kernel/linux/linux-5.10/arch/arm64/boot/dts/rockchip/目录
  2. 修改kernel/linux/linux-5.10/ make-ohos.sh

  3. model_list=(
  4.         "TB-RK3568X0   arm64 0xfe660000 rk3568-toybrick-x0-linux  Image rockchip_linux_defconfig"
  5.         "TB-RK3568X10  arm64 0xfe660000 rk3568-toybrick-x10-linux Image rockchip_linux_defconfig"
  6. )
复制代码
  1. CONFIG_DRM_PANEL_SIMPLE = y
  2. kernel/linux/linux-5.10/drivers/gpu/drm/panel/panel-simple.c
  3. 注释掉
  4. //int panel_simple_loader_protect(struct drm_panel *panel)
复制代码

fakename.png
5)启动参数的定制
kernel/linux/linux-5.10/ make-ohos.sh
  1. cmdline="append earlycon=uart8250,mmio32,${uart} root=PARTUUID=614e0000-0000-4b53-8000-1d28000054a9 rw rootwait rootfstype=ext4
复制代码
  1. FIRMWARE_VER:11.0
  2. MACHINE_MODEL:rk3568_r
  3. MACHINE_ID:007
  4. MANUFACTURER: rockchip
  5. MAGIC: 0x5041524B
  6. ATAG: 0x00200800
  7. MACHINE: rk3568_r
  8. CHECK_MASK: 0x80
  9. PWR_HLD: 0,0,A,0,1
  10. TYPE: GPT
  11. CMDLINE:mtdparts=rk29xxnand:0x00002000@0x00002000(uboot),0x00002000@0x00004000(misc),0x00003000@0x00006000(resource),0x00030000@0x00009000(boot_linux:bootable),0x00002000@0x00039000(ramdisk),0x00400000@0x0003B000(system),0x00200000@0x0043B000(vendor),0x00019000@0x0063B000(sys-prod),0x00019000@0x00654000(chip-prod),0x00010000@0x0066D000(updater),-@0x0067D000(userdata:grow)
  12. uuid:system=614e0000-0000-4b53-8000-1d28000054a9
  13. uuid:boot_linux=a2d37d82-51e0-420d-83f5-470db993dd35
复制代码
device/board/hihope/rk3568/cfg/fstab.rk3568
  1. # fstab file.
  2. #<src>                                                  <mnt_point> <type>    <mnt_flags and options>                              <fs_mgr_flags>
  3. /dev/block/platform/fe310000.sdhci/by-name/system               /usr       ext4     ro,barrier=1  wait,required
  4. /dev/block/platform/fe310000.sdhci/by-name/vendor              /vendor        ext4     ro,barrier=1  wait,required
  5. /dev/block/platform/fe310000.sdhci/by-name/sys-prod              /sys_prod        ext4     ro,barrier=1  wait
  6. /dev/block/platform/fe310000.sdhci/by-name/chip-prod              /chip_prod        ext4     ro,barrier=1  wait
  7. /dev/block/platform/fe310000.sdhci/by-name/userdata               /data       f2fs     discard,noatime,nosuid,nodev,fscrypt=2:aes-256-cts:aes-256-xts  wait,check,fileencryption=software,quota
  8. /dev/block/platform/fe310000.sdhci/by-name/misc /misc none none wait,required
复制代码


根文件系统
1)     ramdisk从3.1到3.2的变化
3.1中ramdisk.Img是放在out/kernel/src_tmp/linux-5.10/boot_linux/目录下被打包到boot_linux.img中。
3.2的ramdisk.Img是直接放在单独的分区里面,由Boot在开机的模式不同的情况下选择加载不同的根文件系统
2)如何修改ramdisk
在.gn文件里面添加对应的配置文件,生成的文件将会被放到ramdisk镜像里面



  1.     image_list += [
  2.       "ramdisk",
  3.       "updater_ramdisk",
  4.     ]
复制代码
  1. CONFIG_DRM_PANEL_SIMPLE=y
  2. CONFIG_DRM_ANALOGIX_DP=y
  3. CONFIG_DRM_DW_HDMI=y
  4. CONFIG_DRM_DW_HDMI_I2S_AUDIO=y
  5. CONFIG_DRM_DW_HDMI_CEC=y
  6. CONFIG_DRM_DW_MIPI_DSI=y
复制代码

fakename.png

显示HDI需要适配两部分:gralloc 和 display_device。
display device适配
display device模块提供显示设备管理、layer管理、硬件加速等功能。
drm设备节点定义在//device/soc/rockchip/rk3568/hardware/display/src/display_device/drm_device.cpp文件中,可根据实际情况修改.

  1. std::shared_ptr<HdiDeviceInterface> DrmDevice::Create()
  2. {
  3.     DISPLAY_DEBUGLOG();
  4.     if (mDrmFd == nullptr) {
  5.         const std::string name("rockchip");
  6.         int drmFd = open("/dev/dri/card0", O_RDWR | O_CLOEXEC); // drmOpen(name.c_str(), nullptr);
  7. }
复制代码
如开发板不支持硬件合成或是有问题的时候,需要在drm_display.cpp文件中跳过gfx的初始化
  1. int32_t DrmDisplay::Init()
  2. {
  3.     ...
  4.     ...
  5.     ret = preComp->Init();                                                                                          // gfx初始化,这里需要跳过
  6.     DISPLAY_CHK_RETURN((ret != DISPLAY_SUCCESS), DISPLAY_FAILURE, DISPLAY_LOGE("can not init HdiGfxComposition"));  // 或者不判断返回值
  7. }
复制代码
同时在//device/soc/rockchip/rk3568/hardware/display/src//hdi_gfx_composition.cpp文件中修改set_layers方法,全部使用CPU合成显示
  1. int32_t HdiGfxComposition::SetLayers(std::vector<HdiLayer *> &layers, HdiLayer &clientLayer)
  2. {
  3. #if 0                                      // CPU合成
  4.             layer->SetDeviceSelect(COMPOSITION_CLIENT);
  5. #else
  6.             if ((layer->GetCompositionType() != COMPOSITION_VIDEO) &&
  7.                 (layer->GetCompositionType() != COMPOSITION_CURSOR)) {
  8.                 layer->SetDeviceSelect(COMPOSITION_DEVICE);
  9.             } else {
  10.                 layer->SetDeviceSelect(layer->GetCompositionType());
  11.             }
  12. #endif
  13. }
复制代码


drm设备节点定义在//device/soc/rockchip/rk3568/hardware/display/src/display_gralloc/display_gralloc_gbm.c文件中,可根据实际情况修改
  1. const char *g_drmFileNode = "/dev/dri/card0";
复制代码

  1. gt9xx: gt911@14 {
  2.         compatible = "goodix,gt9xx";
  3.         reg = <0x14>;
  4.         pinctrl-names = "default";
  5.         pinctrl-0 = <&tp_gpio>;
  6.         goodix_irq_gpio = <&gpio3 RK_PB4 IRQ_TYPE_LEVEL_LOW>;
  7.         goodix_rst_gpio = <&gpio3 RK_PB3 GPIO_ACTIVE_HIGH>;
  8.           /*touchscreen-inverted-x;*/
  9.           status = "okay";
  10.         };
复制代码
  1. //input_set_abs_params(ts->input_dev, ABS_MT_WIDTH_MAJOR, 0, 255, 0, 0);
复制代码
  1. "setparam sys.usb.controller fcc00000.dwc3"
复制代码

©著作权归作者所有,转载或内容合作请联系作者

您尚未登录,无法参与评论,登录后可以:
参与开源共建问题交流
认同或收藏高质量问答
获取积分成为开源共建先驱

Copyright   ©2023  OpenHarmony开发者论坛  京ICP备2020036654号-3 |技术支持 Discuz!

返回顶部