RK3576 + OpenHarmony 6.1 RKNN2 NPU 验证指南

📅 2026/8/5 11:48:58
RK3576 + OpenHarmony 6.1 RKNN2 NPU 验证指南
0. 前置条件项目说明开发板RK3576 OpenHarmony 6.1 标准系统调试工具hdc (HarmonyOS Device Connector)能hdc shellPC 编译环境WSL2 GCC linaro 7.5.0 aarch64 交叉编译器RKNN2 SDKrknpu2/runtime/Linux/目录含librknnrt.so、rknn_api.h测试模型rknpu2/examples/rknn_api_demo/model/RK3576/mobilenet_v1.rknnGCC linaro 路径参考D:\Projects\RKNN3\gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu\gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu1. 板端 NPU 驱动检查通过 hdc shell 连上板子依次执行hdc shell# 1.1 NPU 驱动版本 cat /sys/kernel/debug/rknpu/version期望输出RKNPU driver: v0.9.x# 1.2 NPU 设备节点 ls -la /dev/dri/renderD128期望输出crw-rw-rw- 1 root graphics 226, 128 ...# 1.3 板端 libc 类型确认 ls /lib/ld-musl* /lib/ld-linux* 2/dev/null期望输出/lib/ld-musl-aarch64.so.1OH 6.1 使用 musl libc这是后续需要 glibc 兼容层的原因如果驱动未加载检查内核配置dmesg | grep -i rknpu zcat /proc/config.gz | grep RKNPU 2/dev/null若 NPU 驱动未编译进内核需要重新编译 OH 内核并启用 RKNPU 驱动。2. 在板端搭建 glibc 兼容环境由于librknnrt.so用 GCC linaro 编译、依赖 glibc而 OH 6.1 使用 musl需要自带 glibc 运行时。2.1 从 GCC 工具链提取 glibc 文件在 PC 端PowerShell$GCC_LIB D:\Projects\RKNN3\gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu\gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu\aarch64-linux-gnu\libc\lib $HDC D:\hdc\hdc.exe $BOARD_DIR /data/glibc ​ # 创建目录 $HDC shell mkdir -p $BOARD_DIR ​ # 推送 8 个核心库文件 $files ( ld-2.25.so, libc-2.25.so, libm-2.25.so, libdl-2.25.so, libpthread-2.25.so, libstdc.so.6.0.24, libgcc_s.so.1, librt-2.25.so ) ​ foreach ($f in $files) { $HDC file send $GCC_LIB\$f $BOARD_DIR/$f }2.2 创建 SONAME 符号链接在板端 shell 中cd /data/glibc ln -sf ld-2.25.so ld-linux-aarch64.so.1 ln -sf libc-2.25.so libc.so.6 ln -sf libm-2.25.so libm.so.6 ln -sf libdl-2.25.so libdl.so.2 ln -sf libpthread-2.25.so libpthread.so.0 ln -sf libstdc.so.6.0.24 libstdc.so.6 ln -sf librt-2.25.so librt.so.12.3 验证 glibc 环境ls -la /data/glibc/期望看到 8 个*-2.25.so文件 7 个*.so.*符号链接3. 编译推理测试程序3.1 源文件源文件位于rknpu2/rknn_oh_test.c可以作为模板直接使用。核心调用链rknn_init()→rknn_query()→rknn_inputs_set()→rknn_run()→rknn_outputs_get()→rknn_destroy()3.2 在 WSL 中用 GCC linaro 编译编译脚本build_oh_test.sh位于rknpu2/目录在 WSL 中执行wsl bash /mnt/d/Projects/rknn-toolkit2/rknpu2/build_oh_test.sh编译脚本做了什么修复 LTO plugin 符号链接缺失在 sysroot 中用cp创建 SONAME 别名DrvFS 不支持 symlink编译命令关键参数-Wl,-rpath-link,$LIBC_LIB— 链接时找到 glibc 库-Wl,--dynamic-linker/data/glibc/ld-linux-aarch64.so.1— 运行时使用板端的 glibc ld-Wl,-rpath$ORIGIN:/data/glibc:/data/local/tmp— 运行时库搜索路径编译输出rknpu2/rknn_oh_testaarch64 ELF 可执行文件3.3 编译常见问题错误原因解决fatal error: liblto_plugin.so not foundGCC 工具链 LTO plugin 文件名不对ln -sf liblto_plugin.so.0.0.0 liblto_plugin.socannot find -lpthreadsysroot 缺少 SONAME 符号链接cp libpthread-2.25.so libpthread.so.0cannot find -lstdc同上cp libstdc.so.6.0.24 libstdc.so.6cannot find -lgcc_s同上cp libgcc_s.so.1 libgcc_s.so4. 推送二进制和模型到板端4.1 推送文件$HDC D:\hdc\hdc.exe # 推送推理测试程序 $HDC file send D:\Projects\rknn-toolkit2\rknpu2\rknn_oh_test /data/local/tmp/rknn_oh_test # 推送测试模型 $HDC file send D:\Projects\rknn-toolkit2\rknpu2\examples\rknn_api_demo\model\RK3576\mobilenet_v1.rknn /data/local/tmp/mobilenet_v1.rknn # 推送 librknnrt.so如果首次部署 $HDC file send D:\Projects\rknn-toolkit2\rknpu2\runtime\Linux\librknn_api\aarch64\librknnrt.so /data/local/tmp/librknnrt.so # 设置权限 $HDC shell chmod 755 /data/local/tmp/rknn_oh_test4.2 验证文件就位hdc shell ls -la /data/local/tmp/rknn_oh_test /data/local/tmp/mobilenet_v1.rknn /data/local/tmp/librknnrt.so5. 运行推理测试hdc shellcd /data/local/tmp /data/glibc/ld-linux-aarch64.so.1 \ --library-path /data/glibc:/data/local/tmp \ ./rknn_oh_test mobilenet_v1.rknn期望输出 RKNN OH6.1 Test [1] Loading model: mobilenet_v1.rknn model size: xxxxxxx bytes [2] rknn_init()... OK, ctx366754551280 [3] Query SDK version... api: 2.3.2 drv: 0.9.8 [4] Query I/O count... inputs: 1, outputs: 1 [5] Input tensor(s): [0] input: INT8 NHWC dims[1,224,224,3] n_elems150528 size150528 [6] Output tensor(s): [0] MobilenetV1/Predictions/Reshape_1: FP16 NHWC dims[1,1001] n_elems1001 size2002 [7] Running inference... rknn_run OK rknn_outputs_get OK output[0] first 5: 0.0001 0.0003 0.0011 0.0000 0.0000 [8] Cleanup... done. ALL TESTS PASSED 6. 一键快速验证清单按以下顺序逐项确认全部 OK 即可判定 NPU 可用#检查项命令通过标准1NPU 驱动cat /sys/kernel/debug/rknpu/version输出v0.9.x2设备节点ls -la /dev/dri/renderD128存在且权限正确3glibc 环境ls /data/glibc/ld-linux-aarch64.so.1文件存在4librknnrt.sols /data/local/tmp/librknnrt.so文件存在5测试程序ls /data/local/tmp/rknn_oh_test文件存在且可执行6测试模型ls /data/local/tmp/mobilenet_v1.rknn文件存在7推理运行执行第 5 节命令ALL TESTS PASSED7. 常见问题排查7.1 No such file or directory即使文件确实存在原因动态链接器不匹配。OH 使用/lib/ld-musl-aarch64.so.1而程序编译时指定了 glibc 的 ld。确认readelf -l ./rknn_oh_test | grep interpreter # 应输出: [Requesting program interpreter: /data/glibc/ld-linux-aarch64.so.1]解决必须用 glibc 的 ld 启动/data/glibc/ld-linux-aarch64.so.1 --library-path /data/glibc:/data/local/tmp ./rknn_oh_test7.2 rknn_init 返回错误-1(RKNN_ERR_FAIL)检查模型文件完整性、检查/dev/dri/renderD128权限-4(RKNN_ERR_DEVICE_UNAVAILABLE)NPU 驱动未加载-6(RKNN_ERR_MODEL_INVALID)模型与 SDK 版本不匹配确认使用对应 RK3576 的模型7.3 rknn_server Address already in use原因/dev/usb-ffs/被 hdc 占用rknn_server 的 NPUTransfer 组件无法绑定 USB 通道。结论rknn_server 是给 PC↔板端 USB 通信用的RK3576 内部 NPU 推理不需要 rknn_server直接调用 librknnrt.so 即可。7.4 程序段错误 (SEGV)可能是--library-path路径不完整检查echo $LD_LIBRARY_PATH # 确认 /data/glibc 和 /data/local/tmp 都在搜索路径中8. 相关文件索引文件路径用途推理测试源码rknpu2/rknn_oh_test.c最小 RKNN 推理验证程序编译脚本rknpu2/build_oh_test.shWSL GCC linaro 编译RKNN API 头文件rknpu2/runtime/Linux/librknn_api/include/rknn_api.h完整 C API 定义运行时库rknpu2/runtime/Linux/librknn_api/aarch64/librknnrt.so7.7MB板端部署RK3576 模型rknpu2/examples/rknn_api_demo/model/RK3576/mobilenet_v1.rknn分类模型测试YOLOv5 模型rknpu2/examples/rknn_yolov5_demo/model/RK3576/yolov5s-640-640.rknn检测模型测试Reusable Skill~/.workbuddy/skills/rknn2-oh-cross-compile/可复用的 AI 辅助 skill9. 架构要点备忘┌─────────────────────────────────────────────────────┐ │ ArkTS App (OH 6.1 / LLVMmusl) │ │ │ 未来通过 IPC/NAPI 调用 │ │ ▼ │ │ rknn_oh_test (GCC linaro / glibc) │ │ │ 直接链接 │ │ ▼ │ │ librknnrt.so (GCC linaro / glibc) │ │ │ ioctl │ │ ▼ │ │ /dev/dri/renderD128 → NPU 驱动 v0.9.8 │ │ │ │ │ ▼ │ │ RK3576 双核 NPU (2×3 TOPS) │ └─────────────────────────────────────────────────────┘不要用 rknn_server它依赖 USB-FFS在 OH 上被 hdc 占用GCC linaro 编译所有直接调 RKNN API 的代码必须用 GCC 编译自带 glibc/data/glibc/是运行时基础每块新板子都要先搭好RK3576 双核可通过rknn_set_core_mask(ctx, RKNN_NPU_CORE_0_1)启用双核并行