三条路会选了。今天解决最烦的那件事:改一行代码不必等四十分钟。按改动选最小重建。 

现象:你改了超声波驱动里一个超时时间,跑 ./build.sh --product-name rk3568_evb --ccache,31 到 39 分钟过去了,刷进去测,发现改的不是那个文件。

原因:全量构建的时间几乎全花在用户态重链和大镜像上。system.img 一点六 GB,thinLTO 的大 .so 一个能编七分钟。内核 boot_linux 自己大约八分钟。你改的那个 hcsr04.c 跟这些无关。

动作大约耗时
全量含内核≈ 39 min
全量不含内核≈ 31 min
内核 boot_linux 整段≈ 8 min
增量 make Image(改 1 个 .c)1–2 min
只编 dtb几十秒
make M= 单个 .ko10–30 s

档选错,轻则浪费时间,重则刷上去的还是旧 dtb。


现象:改 .c 一次要半小时

原因

build.sh 默认把用户态、镜像打包全走一遍。GN 并不知道你只关心这个 ko。

代码:档 1

ROOT=/path/to/OpenHarmony
export PATH=$ROOT/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH
export KBUILD_OUTPUT=$ROOT/out/kernel/OBJ/linux-5.10
cd $ROOT/out/kernel/src_tmp/linux-5.10

make LLVM=1 LLVM_IAS=1 CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 \
     M=drivers/misc modules -j$(nproc)

$KBUILD_OUTPUT/scripts/sign-file sha1 \
    $KBUILD_OUTPUT/certs/signing_key.pem \
    $KBUILD_OUTPUT/certs/signing_key.x509 \
    drivers/misc/evb_misc.ko

hdc file send drivers/misc/evb_misc.ko /data/evb_misc.ko
hdc shell "rmmod evb_misc 2>/dev/null; insmod /data/evb_misc.ko; dmesg | tail -20"

增量 make 不要 rm -rf OBJ,否则 signing_key.pem 被重新生成,旧 ko 全废。.ko 是 aarch64;用户态测试程序必须 armv7 + musl。


现象:改了 DTS,刷完 /proc/device-tree 没变

原因

U-Boot 真正喂给内核的 dtb,经常是 resource 分区(p4)里的 rk-kernel.dtb,不是 boot_linux 里那个 toybrick.dtb。只刷 p5,p4 仍是旧屏。

GN 的 is_kernel_change() 看的 DEPS 不含 device/board/。只改板级 dts,ninja 可能根本不编 dtb。

代码:档 2

ROOT=/path/to/OpenHarmony
export PATH=$ROOT/prebuilts/clang/ohos/linux-x86_64/llvm/bin:$PATH
export KBUILD_OUTPUT=$ROOT/out/kernel/OBJ/linux-5.10
SRC=$ROOT/out/kernel/src_tmp/linux-5.10
cd $SRC

cp $ROOT/device/board/rk/rk3568_evb/kernel/rk3568-evb-linux.dts \
   arch/arm64/boot/dts/rockchip/rk3568-evb-linux.dts

make LLVM=1 LLVM_IAS=1 CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 \
     O=$KBUILD_OUTPUT rockchip/rk3568-evb-linux.dtb -j$(nproc)

目标必须带 rockchip/ 前缀。编完用 dtc 反编译,不要只看 make exit 码:

DTC=$KBUILD_OUTPUT/scripts/dtc/dtc
$DTC -I dtb -O dts -o /tmp/now.dts \
    $KBUILD_OUTPUT/arch/arm64/boot/dts/rockchip/rk3568-evb-linux.dtb
grep -n 'hdmi\|lvds-panel' /tmp/now.dts | head
cp $KBUILD_OUTPUT/arch/arm64/boot/dts/rockchip/rk3568-evb-linux.dtb \
   $SRC/boot_linux/extlinux/toybrick.dtb
genext2fs -B 4096 -b 16384 -d $SRC/boot_linux -i 8192 -U $SRC/boot_linux.img
cp $SRC/boot_linux.img $ROOT/out/rk3568_evb/packages/phone/images/boot_linux.img

resource 单独打:

resource_tool --pack --image=resource.img rk-kernel.dtb logo.bmp logo_kernel.bmp
cp resource.img $ROOT/out/rk3568_evb/packages/phone/images/resource.img

改内核 C 而不是 dts:

make LLVM=1 LLVM_IAS=1 CROSS_COMPILE=aarch64-linux-gnu- ARCH=arm64 \
     O=$KBUILD_OUTPUT Image -j$(nproc)

刷之前:

hdc shell "cat /proc/partitions"
hdc file send boot_linux.img /data/boot_linux.img
hdc file send resource.img /data/resource.img
hdc shell "dd if=/data/boot_linux.img of=/dev/block/mmcblk1p5 bs=4M conv=fsync"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk1p4 bs=4M conv=fsync"
hdc shell "dd if=/data/resource.img of=/dev/block/mmcblk0p4 bs=4M conv=fsync"
hdc shell reboot

写成 /dev/mmcblk1p5(少了 block),dd 会在 /dev 建普通文件,返回成功,重启还是旧内核。by-name 永远指向 eMMC。


现象:改了 .so,板上 strings 仍是旧的

原因

--build-target 只编这个目标,不会 install 进 packages/phone/vendor。直接 ninja 还可能撞 stale multiple rules。

代码:档 3

cd $ROOT
./build.sh --product-name rk3568_evb --build-target camera_pipeline_core --ccache
cp out/rk3568_evb/device_rk3568_evb/device_rk3568_evb/libcamera_pipeline_core.z.so \
   out/rk3568_evb/packages/phone/vendor/lib/

打 vendor.img 以 toolchain.ninja 里那条为准。打完 debugfs 核对:

debugfs -R "dump /lib/libcamera_pipeline_core.z.so /tmp/x.so" \
    packages/phone/images/vendor.img
strings /tmp/x.so | grep '你埋的那句日志'
hdc file send vendor.img /data/vendor.img
hdc shell "dd if=/data/vendor.img of=/dev/block/mmcblk1p8 bs=4M conv=fsync && reboot"

uhdf HCS 也落在 vendor,改之前删 hcb:

rm -f out/rk3568_evb/gen/vendor/rk/rk3568_evb/hdf_config/uhdf/hdf_default.hcb
rm -f out/rk3568_evb/packages/phone/vendor/etc/hdfconfig/hdf_default.hcb
rm -f out/rk3568_evb/packages/phone/images/vendor.img

khdf 的 HCS 编进内核,刷 boot_linux,别和 vendor 搞混。


现象:改了 build_kernel.sh,.config 还是旧值

原因

is_kernel_change() 的 DEPS 不含 device/board/。只改 board 下的脚本、dts、HCS,不会 rm -rf OBJ 重新 defconfig。增量 make 用旧 .config

代码:三种删除效果不同

# 强制「内核变了」——改 board 脚本 / dts / §13 CONFIG
rm -rf out/kernel/checkpoint
./build.sh --product-name rk3568_evb --ccache --build-target kernel --fast-rebuild --disable-package-image

# 内核树脏了
# rm -rf out/kernel

# 核弹,31–39 min,交付或 part 列表错了才用
# rm -rf out
你改了什么删什么重建什么上板
某个 .c,当 ko 调什么都别删make M= + sign-filehdc send + insmod
板级 dts / 时序checkpoint,或直 make dtbdtb + boot_linux + **resource**p5 + p4
内核 C 定稿内置checkpointImage + boot_linuxp5
khdf HCShcb + checkpointboot_linuxp5
uhdf HCS / vendor 库uhdf hcbvendor.imgp8
说不清、要出交付包视污染范围全量整张 sd_image
grep CONFIG_EVB_MISC out/kernel/OBJ/linux-5.10/.config
strings out/kernel/OBJ/linux-5.10/vmlinux | grep evb_misc | head

编完核产物,不要核心情:

grep CONFIG_EVB_MISC out/kernel/OBJ/linux-5.10/.config
strings out/kernel/OBJ/linux-5.10/vmlinux | grep evb_misc | head
stat out/rk3568_evb/packages/phone/images/boot_linux.img
stat out/rk3568_evb/packages/phone/images/resource.img

.config 是 =y 而 vmlinux 里没有符号,合成了但没链进。删 checkpoint 再编。


现象:--build-target phone_boot_image 报 unknown target

你从别处抄到 phone_boot_image,以为能只打 boot。

原因

这个产品的 GN 目标不叫这个名字。hb tool --ls 列出来的才算数。内核那一段是 action("kernel"),挂在板级 device/board/rk/rk3568_evb/kernel/BUILD.gn 上,跑的是 build_kernel.sh。随便猜一个 phone_*_image,ninja 回你 unknown,然后你以为只能全量。

代码

cd $ROOT
hb tool --ls | grep -iE 'kernel|boot|vendor|system'

只想让内核 action 跑一遍、不打大镜像:

./build.sh --product-name rk3568_evb --ccache \
    --build-target kernel --fast-rebuild --disable-package-image

--fast-rebuild 跳过 gn gen,省两三分钟。--disable-package-image 不生成 system.img / vendor.img。改的是 board 下的 dts 或 build_kernel.sh 时,这一条仍然可能判定「内核没变」——DEPS 不含 board,所以还是要先删 checkpoint。

直接 ninja 而不走 build.sh,偶尔撞 multiple rules generate xxx。不要加 -w dupbuild=warn 把警告吞掉当成功,走 build.sh 重新 gn gen。


现象:主机 dtb 新,boot_linux.img 里仍是旧的

你 make rockchip/rk3568-evb-linux.dtb 成功了,dtc 反编译看得到新节点。刷 p5 之后 /proc/device-tree 还是旧的。

原因

dtb 编出来在 OBJ 里。boot_linux.img 是一份 64 MiB 的 ext2,里面的文件叫 extlinux/toybrick.dtb。你没覆盖它、没 genext2fs,镜像还是上一份。显示相关还要打 resource 里的 rk-kernel.dtb,那才是 U-Boot 常喂给内核的。

整段 make-ohos.sh 会 make rockchip_linux_defconfig 再编 Image,纯 dts 改动用不上,几分钟到八分钟。外科就是:拷 dts → make dtb → 覆盖 toybrick.dtb → genext2fs

管道后面写 echo exit=$? 看到的是 echo 的 0,不是 make 的。无关的 rk628 一类 dts 报错也可能混在日志里。看产物时间戳,用 debugfs 抠出来对。

代码

debugfs -R "dump /extlinux/toybrick.dtb /tmp/in-img.dtb" \
    $ROOT/out/rk3568_evb/packages/phone/images/boot_linux.img
cmp $KBUILD_OUTPUT/arch/arm64/boot/dts/rockchip/rk3568-evb-linux.dtb /tmp/in-img.dtb
$DTC -I dtb -O dts -o /tmp/in-img.dts /tmp/in-img.dtb
grep -n 'status' /tmp/in-img.dts | head

cmp 对不上,说明 genext2fs 打的是另一个目录,或者你 cp 进 boot_linux/extlinux/ 之前 dtb 还是旧的。

dtb 目标必须带 rockchip/ 前缀。写成 make rk3568-evb-linux.dtb,make 去 dts 根目录找,报没有规则。包装脚本里的 ${dtb}.img 能解析子目录,你手动单编必须带前缀。

权威源永远是 device/board/。src_tmp 是副本。下次 build_kernel.sh 真跑起来,会从 board 再拷一次,把你在副本上的改动盖掉。

diff -u \
  device/board/rk/rk3568_evb/kernel/rk3568-evb-linux.dts \
  out/kernel/src_tmp/linux-5.10/arch/arm64/boot/dts/rockchip/rk3568-evb-linux.dts

有 diff 就先拷再编。不要在副本上改。


现象:用户态小工具在板上 No such file or directory

你用交叉 gcc 编了一个读 /dev/evb_misc 的 CLI,file 说它是 ELF,hdc 送上去,一跑这个错。

原因

内核 64 位,用户态 32 位。这不是「两个 ABI 都能跑」,是两套世界。ldd 在主机上看 aarch64 的解释器,板上没有那条路径。动态链接器必须是:

/system/lib/ld-musl-arm.so.1

档 3 的 .so 同理。你若用 aarch64 工具链编 camera pipeline,能链过,板上 dlopen 失败,进程退 255。走产品的 GN 目标,不要自己 clang 瞎编一份塞进去。

代码

# 错
aarch64-linux-gnu-gcc -o evb_misc_cli evb_misc_cli.c

# 对:走 SDK native 的 armv7 musl
clang --target=arm-linux-ohos -march=armv7-a \
      --sysroot=<ohos-sdk-native> \
      -o evb_misc_cli evb_misc_cli.c

file evb_misc_cli
# ELF 32-bit LSB executable, ARM, EABI5
hdc file send evb_misc_cli /data/evb_misc_cli
hdc shell "chmod 755 /data/evb_misc_cli; /data/evb_misc_cli"

档 1 的 .ko 不要用这条 clang。模块必须 aarch64,跟 vmlinux 同套 LLVM。vermagic 必须和正在跑的内核一致:

modinfo drivers/misc/evb_misc.ko | grep vermagic
hdc shell "cat /proc/version"
llvm-strip --strip-debug drivers/misc/evb_misc.ko

两边都是 5.10.184 这一类字符串,才能 insmod。差一个补丁号,内核直接拒。

vendor 镜像里的 so 打完也要 file

debugfs -R "dump /lib/libcamera_pipeline_core.z.so /tmp/x.so" \
    packages/phone/images/vendor.img
file /tmp/x.so
# 期望 ELF 32-bit LSB shared object, ARM

file 若报 64-bit ARM aarch64,这份 so 上不了板。


现象:改了 input_config.hcs,触摸分辨率纹丝不动

原因

khdf 和 uhdf 两套配置,进两张镜像。顶层 hdf.hcs 几乎全是 #include,hc-gen 的依赖常常只盯这一份。你改了 input/input_config.hcs,顶层没动,hcb 不重生,Image 里仍是旧 hex。

khdf 刷 boot_linux。uhdf 刷 vendor。改错边、刷错分区,日志看起来一切正常。

代码

find out/kernel -name '*.hcb' -print
rm -f out/kernel/src_tmp/linux-5.10/drivers/hdf/khdf/*.hcb
rm -rf out/kernel/checkpoint

uhdf:

rm -f out/rk3568_evb/gen/vendor/rk/rk3568_evb/hdf_config/uhdf/hdf_default.hcb
rm -f out/rk3568_evb/packages/phone/vendor/etc/hdfconfig/hdf_default.hcb
rm -f out/rk3568_evb/packages/phone/images/vendor.img

改 khdf 等于改内核。改 uhdf 等于改 vendor。HCS 那篇把管道画过,这里只强调:子文件不在依赖里,必须先删 hcb。


hdc 刷分区前的固定动作

hdc shell "cat /proc/partitions"
hdc shell "mount | grep ' on / '"
hdc shell "cat /proc/version"
hdc shell "ls -l /dev/block/mmcblk0p4 /dev/block/mmcblk1p4 /dev/block/mmcblk0p5 /dev/block/mmcblk1p5"

SD 启动:boot_linux → mmcblk1p5resource → mmcblk1p4system → mmcblk1p7vendor → mmcblk1p8。eMMC 把 1 换成 0。U-Boot 经常去 eMMC 找 p4/p5,所以你「从 SD 起」时,改显示仍可能要写 mmcblk0p4

hdc shell "dd if=/data/boot_linux.img of=/dev/block/mmcblk1p5 bs=4M conv=fsync"
hdc shell "sync; reboot"

纯 dts 改动 /proc/version 不变(没换 Image),要读节点:

hdc shell "cat /proc/device-tree/hdmi@fe0a0000/status; echo"
hdc shell "find /proc/device-tree -name status | grep -i hdmi"
hdc shell "strings /vendor/lib/xxx.so | grep 标记"

不要用镜像文件的 mtime 当证据。


一张图记住三档

改的是内核 .c,还在调逻辑
        → 档 1  make M= + sign-file + insmod          10–30 s

改的是 dts / 内置驱动 / khdf
        → 档 2  make dtb 或 Image + genext2fs
           显示还要重打 resource,刷 p4+p5              1–8 min

改的是 vendor 的 so / uhdf
        → 档 3  --build-target + cp + 打 vendor.img
           debugfs dump 核对后再刷 p8                   数分钟

交付、回归、说不清
        → 全量 build.sh                                31–39 min

档选错的典型:改 dts 跑全量(付钱给 userspace);改 so 只刷 boot_linux(分区根本不含那份 so);改 ko 去删 out/(钥匙换了,循环从秒级变回 39 分钟)。

gn gen 自己就要 2–4 分钟,扫六万多个 target。--fast-rebuild 跳过它。驱动迭代连 gn 都不必每次跑。


现象对照

现象原因做法
改一行等 39 min全量在重链 userspace按改动选档 1/2/3
insmod Key rejected删过 OBJ,钥匙换了板级固定 certs;增量 make 别 rm OBJ
改 dts 全量成功但板上旧ninja 没重跑 / 没刷 resource删 checkpoint 或直 make dtb;刷 p4
`make rk3568-evb-linux.dtb` 无规则目标不带 `rockchip/` 前缀`make ... rockchip/rk3568-evb-linux.dtb`
主机 dtb 新,img 里旧没覆盖 `toybrick.dtb` 或没 genext2fsdebugfs dump 再 cmp
`dd` 成功 md5 对,重启旧写到 `/dev/mmcblkXpY` 普通文件`/dev/block/`,先 cat partitions
by-name 刷了没效果by-name 指向 eMMC用当前启动盘的 mmcblkNpY
`--build-target` 编了 so 板上旧没 install、没重打 vendorcp 进 packages/phone/vendor/lib,debugfs 验
so 是 aarch64没用产品 GN,自己交叉错了32 位 ARM EABI5,file 核对
CLI `No such file or directory`用户态用了 aarch64 链接器armv7 + musl
改 HCS 没反应子文件不在 make 依赖;khdf/uhdf 刷错分区删对应 hcb
改第 13 段 CONFIG,.config 旧is_kernel_change 不看 board删 checkpoint
ninja multiple rules直接 ninja 脏图走 build.sh 重新 gn gen
`phone_boot_image` unknown目标名不是这个`hb tool --ls`;kernel + 三个开关
make 管道 `exit=0`,dtb 没变`echo exit=$?` 看到的是 echo看产物时间戳 + dtc
整段 make-ohos.sh 为换 dtb它会重做 defconfig 和 Image外科 genext2fs
删了整个 out你想省事驱动迭代不要删 out,31 min 买回来

档 1 解决「我在调逻辑」。档 2 解决「我在改硬件描述」。档 3 解决「我在改用户态库」。全量留给交付和回归。显示那几篇会反复用到档 2 加刷 p4,因为生效 dtb 不在你以为的那个分区。


系列第 15 篇 · 芯片:瑞芯微 RK3568 · OpenHarmony 4.1(API 11) · Linux 5.10

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐