[其他] 【OK1126BJ-S 开发板测评(三):从环境搭建到 NPU 推理——7 个脚本跑通 YOLOv5s 】

[复制链接]
8|0
怀揣少年梦 发表于 2026-9-1 16:40 | 显示全部楼层 |阅读模式

上一篇把板子点亮,这一篇不整那些虚的,就干一件事:把 RKNN 环境老老实实搭起来,再用一套脚本把「模型转换 → 连板推理 → 量化对比」整条链路跑穿。

说句掏心窝子的话,玩瑞芯微这种带 NPU 的板子,大部分新手不是卡在硬件上,而是卡在工具链上——PC 端要有做模型转换的 RKNN-Toolkit2,板端要有做推理的运行时,中间还横着一个更基础的问题:板子得先稳定在线。WiFi 不会自动连、adb 每次重启都得串口手动拉起来,这种状态谈什么模型部署?所以这篇的顺序是:先把板子的「开机三件套」配好 → 再装 PC 工具链 → 最后七个脚本一条线跑通全程。踩过的坑全摊开讲,照着我走基本一次过。

一、先弄明白:模型是怎么"坐上"NPU 的

在动手之前,我强烈建议你把下面这个流程先看明白,不然只会对着命令复制粘贴,出了问题根本不知道查哪儿。

      训练好的模型(PyTorch/TF等)
              │  (电脑上一锤定音)
              ▼
      转成中间格式 ONNX
              │  (电脑上,用 RKNN-Toolkit2)
              ▼
      生成板子认得的 .rknn 文件
              │  (拷到板子上)
              ▼
      板端用 rknn-toolkit-lite2 或 C API 加载推理

关键点有三条:

  • 模型转换在 PC 上进行(叫"宿主侧"),用 Python 环境里的 RKNN-Toolkit2;
  • 推理在板子上进行,用轻量版的运行时库(RKNN-Lite2 或 C 接口);
  • 二者版本必须对应,安装时报错大概率就是版本没对上。

落到这块板子上,整套环境的连接拓扑长这样:

 PC (WSL Ubuntu 22.04)                     OK1126B (RV1126B)
┌─────────────────────┐      WiFi 同网段   ┌──────────────────────────┐
│ RKNN-Toolkit2       │ ─── adb :5555 ──▶ │ adbd ──▶ rknn_server     │
│  ├ 模型转换(离线)     │                   │           └─▶ NPU       │
│  └ 连板调试推理       │                   │        (librknnrt.so)    │
└─────────────────────┘                   └──────────────────────────┘
        │                                            ▲
        └──────────── USB 串口 (COM25, 仅调试急救) ────┘

两个容易想当然的点先纠正

  • rknn_server 不监听任何 TCP 端口,它靠 adb 通道传数据。
  • 板子和 PC 之间唯一的物理连接是一根 USB 串口线(救急用),跑模型走的是 WiFi 网络 adb。网络不通,一切免谈——这就是为什么前置配置要放在第一节。

RKNN模型部署全流程图.png

二、前置第一课:开机三件套自启(WiFi / adbd / rknn_server)

这块板子出厂有个"惊喜":WiFi、adbd、rknn_server 三样全都没有开机自启。我一开始也被表象骗了——/etc/profile.d/adbd.sh 看着像启动脚本,其实只 export 了两个环境变量,一个进程都不会拉起;systemd 里那个 wpa_supplicant.service 用的是 -u 纯 dbus 模式,压根不读配置文件。所以以前每次断电重启,都得串口手动来一遍:

1. 手动拉取adb

【老办法——串口手动拉起 adbd(应急用)】

root@OK1126B-buildroot:~# ps | grep adbd
root@OK1126B-buildroot:~# export ADB_TCP_PORT=5555
root@OK1126B-buildroot:~# adbd &
[1] 1508
root@OK1126B-buildroot:~# adbd I 09-01 03:16:35  1508  1508 main.cpp:197] adbd listening on port 5555

file-20260901111931785.png

一次两次无所谓,次数多了谁受得了?这次直接彻底办了:往 /etc/init.d/ 放两个开机脚本

另外提醒一句:持久配置别放 /tmp,那是内存盘,重启就没;这块板也没有 /data 分区,统一放 /etc(rootfs 本身是可写的 ext4)。

2. WiFi 开机自连

第一步,把 WiFi 凭据写进板子自带的 /etc/wpa_supplicant.conf

  • 查看wifi配置文件

file-20260901103006988.png

  • 修改wifi账号和密码

file-20260901102936564.png

  • 启动 wpa_supplicant

file-20260901141811011.png

  • 获取 IP 地址(DHCP 客户端)

file-20260901142045791.png

第二步,写开机脚本 S98wifi.sh。

这里有个大坑必须重点说:我第一版脚本写完,重启死活不连,串口手动跑一遍却完全正常。查 journalctl 才水落石出——是时序竞争:脚本执行的那一刻,RTL8821CS 的驱动模块还没加载完(前后差 2 秒左右),ifconfig wlan0wpa_supplicantudhcpc 三条命令全部报 No such device 后败退。所以脚本里必须先等 wlan0 出现,再干活

【WiFi 开机自启脚本(板端)】

cat > /etc/init.d/S98wifi.sh << 'EOF'
#!/bin/sh
case "$1" in
  start)
    echo "Starting WiFi..."
    n=0
    while [ $n -lt 30 ]; do          # 等驱动加载完,最多30秒
      ifconfig wlan0 >/dev/null 2>&1 && break
      sleep 1
      n=$((n+1))
    done
    killall -q wpa_supplicant 2>/dev/null
    killall -q udhcpc 2>/dev/null
    ifconfig wlan0 up
    wpa_supplicant -B -D nl80211 -i wlan0 -c /etc/wpa_supplicant.conf
    udhcpc -b -i wlan0
    ;;
  stop)
    killall -q wpa_supplicant 2>/dev/null
    killall -q udhcpc 2>/dev/null
    ;;
esac
exit 0
EOF
chmod 755 /etc/init.d/S98wifi.sh

小经验:串口终端里粘贴多行 heredoc 容易被吞行(我就栽在这,配置文件压根没写进去,脚本空转半天)。建议先用代码块1的办法把 adbd 手动拉起来,之后所有写文件操作都走 adb shell,稳定得多。

file-20260901142548501.png

3. adbd + rknn_server 开机自启

同样的思路再来一个 S99rknn.sh:adbd 用环境变量指定监听 5555;rknn_server 不直接拉起,而是交给厂商自带的 start_rknn.sh 守护循环(server 意外挂了会自动重生,比裸拉一个进程可靠):

【adbd / rknn_server 开机自启脚本(板端)】

cat > /etc/init.d/S99rknn.sh << 'EOF'
#!/bin/sh
case "$1" in
  start)
    if ! pidof adbd >/dev/null 2>&1; then
      ADB_TCP_PORT=5555 ADBD_SHELL=/bin/bash /usr/bin/adbd >/dev/null 2>&1 &
    fi
    if ! pidof start_rknn.sh >/dev/null 2>&1; then
      /usr/bin/start_rknn.sh >/dev/null 2>&1 &
    fi
    ;;
  stop)
    killall adbd 2>/dev/null
    killall start_rknn.sh 2>/dev/null
    killall rknn_server 2>/dev/null
    ;;
esac
exit 0
EOF
chmod 755 /etc/init.d/S99rknn.sh

4. 重启验收:约 40 秒后全自动就绪

reboot 一次,等半分钟左右,三项检查全过就算配置成功:

【代码块5:重启后验收(板端串口)】

ifconfig wlan0        # 有 inet addr:192.168.77.x  → WiFi 自连 OK
pidof adbd            # 有 PID                     → adbd 自启 OK
pidof rknn_server     # 有 PID                     → rknn_server 自启 OK

file-20260901142658823.png

PC 侧(WSL)再补一刀:

adb connect 192.168.77.104:5555    # 换成你板子的实际 IP
adb devices                        # 应显示 device 状态
adb shell id                       # 应返回 uid=0(root)

file-20260901142758681.png

交代一个历史遗留问题:如果 adb root 之后连接掉线、跑模型时报 rknn_server abnormal / ERROR_PIPE -9,那是 buildroot 自带 adbd 的锅(不支持网络 root)。解决办法是换成官方 adbd,我把它做成了应急脚本 04b_fix_adbd.sh,见第六节。先做 2/3的自启配置,大多数情况就用不上 04b 了——但知道它在那儿,心里踏实。

三、电脑上装 RKNN-Toolkit2(脚本 01)

板子用的 NPU 是瑞芯微的,对应的转换工具叫 RKNN-Toolkit2。注意是带 2 的,老的那个 Toolkit(不带 2)是给老芯片用的,别下错。

官方建议用一个干净的 Python 虚拟环境,别污染电脑上别的工程。所谓 venv 就是一份独立的 Python 沙盒(我用的 Python 3.10,include-system-site-packages=false 完全隔离),依赖坏了删掉重建就行,系统 Python 毫发无伤——这对 RKNN 这种依赖版本卡得死的工具来说简直是刚需。

实际操作我全部固化进了 01_env_setup.sh:自动建 venv(~/rknn_env)、锁版本装依赖、装 wheel、最后自检,一条命令到底:

【环境一键搭建(PC 端 WSL)】

cd ~/rknn_manual
bash 01_env_setup.sh

# 预期输出:
#   == python: Python 3.10.12  venv: /home/lxg/rknn_env ==
#   rknn_toolkit2 已就绪, version = 2.3.2
#   RESULT: ENV_READY

三个版本坑提前打预防针(都是实打实踩过的):

  • onnx 必须锁 1.16.1:新版删了 onnx.mapping,转换阶段直接崩;
  • setuptools 要 < 70:新版没有 pkg_resources,toolkit 一 import 就报错;
  • wheel 认准 x86_64 + cp310:WSL 里手滑装成 arm64 包的话,安装阶段就 Architecture 不匹配。

另外验证别用 import rknn 这种写法——2.3.2 是 namespace 包结构,没有顶层模块,正确姿势是 from rknn.api import RKNN(我就被自己写的探针坑过一回)。

file-20260901143016241.png

四、板端运行时:固件自带,只需确认

板子这头比想象的省事:rknn_server 在 /usr/bin、librknnrt.so 在 /usr/lib,固件出厂就带,不用装任何东西。(想走板端 Python 路线的话还有个 rknn-toolkit-lite2 可以 pip 装,但我们这套流程用不上——转换在 PC、调试走连板、量产走 C API,三板斧够用了。)

要做的只是"确认它活着",这步固化成 04_board_deploy.sh:连板、确认 root、检查 librknnrt / rknn_server / rknpu 设备节点,全过输出 BOARD_READY:

【代码块7:连板部署检查(PC 端)】

bash 04_board_deploy.sh

# 预期输出(S99 自启生效后 rknn_server 就是 running 状态):
#   connected to 192.168.77.104:5555
#   board user: root
#    librknnrt: librknnrt.so
#    rknn_server: running
#    dev: rknpu
#   RESULT: BOARD_READY

file-20260901143140502.png

五、七个脚本,把整条RKNN转换链路跑通

前面铺垫完,正餐来了。整套流程我整理成 1 个配置文件 + 7 个脚本(外加一个应急备胎),全放在 rknn_manual/ 目录。每个脚本干完活都会打一个 RESULT 标记,一眼就能判断这步过没过:

文件 干什么 预期输出
00_env.env 唯一要改的配置:venv/SDK 路径、板子 IP
01_env_setup.sh 装 / 自检 RKNN-Toolkit2 环境 ENV_READY
02_small_check.sh 手写最小模型,先验证转换链路(可选) SMALL_OK
03_yolo_convert.sh YOLOv5s → RKNN,一次产出 INT8 + FP16 YOLO_CONVERT_DONE
04_board_deploy.sh 网络 adb 连板 + 板端检查 BOARD_READY
05_yolo_infer.sh 板端 NPU 推理,测耗时 / 张量统计 INFER_DONE
06_yolo_decode.sh INT8 vs FP16 解码对比 + 逐框 IoU DECODE_DONE
07_perf_cpu.sh 推理期间 CPU / NPU 占用采样 CPU/NPU 采样结果
04b_fix_adbd.sh (备胎)adb root 掉线时换官方 adbd ADBD_SWAPPED

执行顺序就一条线:

【全流程执行(PC 端)】

cd ~/rknn_manual
nano 00_env.env          # 第一次跑只改这里:路径 + 板子 IP
bash 01_env_setup.sh     # ① 环境
bash 02_small_check.sh   # ② 可选:30 秒自检转换链路
bash 03_yolo_convert.sh  # ③ YOLOv5s 转出 INT8 + FP16 两个 .rknn
bash 04_board_deploy.sh  # ④ 连板
bash 05_yolo_infer.sh    # ⑤ 板端推理
bash 06_yolo_decode.sh   # ⑥ 量化对比
bash 07_perf_cpu.sh      # ⑦ 性能采样

③ 转换:一次出两个模型,INT8 比 FP16 小了快一半。注意 .rknn 要输出到用户可写目录(脚本里已经处理了;别学我第一次让它往 SDK 只读目录里写,直接 PermissionError 教做人):

yolov5s-int8-rv1126b.rknn   7766904 bytes  (INT8)
yolov5s-fp16-rv1126b.rknn  14895428 bytes  (FP16)
RESULT: YOLO_CONVERT_DONE

file-20260901144644229.png

⑤ 板端推理(bus.jpg,640×640,连板调试模式):

[INT8] NPU inference time = 32.147s
[FP16] NPU inference time = 44.857s
RESULT: INFER_DONE

说明:这个耗时是 PC 工具链经 adb 连板的调试模式耗时,含数据来回传输,不代表 NPU 极限——板端 C API 纯推理会快一个数量级,那是下一篇的内容。但做同条件对比已经够用:INT8 比 FP16 快约 30%,体积小约 48%

file-20260901145714165.png

⑥ 量化对比:两个模型对同一张图各检出 5 个目标(4 人 + 1 公交),逐框 IoU 全部 0.975以上——INT8 量化基本没伤筋动骨

===== INT8 : 5 detections  (NPU 29.924s) =====
  [person] conf=0.860 box=(480,241,559,525)
  ...
  INT8[person] conf=0.860 <-> FP16[person] conf=0.848  IoU=0.975
RESULT: DECODE_DONE

file-20260901150601193.png

⑦ 性能采样:推理期间 CPU 计算占用(us+sy)仅 1.5%,98.5% 时间空闲——计算全卸载给了 NPU,CPU 只管调度和搬数据。这版内核的 NPU 占用 debugfs 节点读出来恒 0(接口没刷新);NPU 频率全程 800MHz,但基线不推理时也是 800MHz,频率不随负载变化。

file-20260901153215947.png

小结

这套环境搭完,我给你六个避坑清单,都是血泪:

  1. 版本必须对齐:PC 端 RKNN-Toolkit2、板端 librknnrt、固件里的 NPU 驱动,三者版本必须匹配。别贪新,用配套那套最稳(onnx 锁 1.16.1、setuptools 锁 <70)。
  2. Python 环境要隔离:别往系统 Python 里硬塞,一个 venv 解决所有烦恼,出事删了重建。
  3. 分清"转换在 PC,推理在板":两边的库千万别装反,装反了各种玄学报错。
  4. 开机三件套要先配:WiFi / adbd / rknn_server 这板子出厂全无自启,/etc/init.d/ 里两个脚本一劳永逸;写 WiFi 脚本记得加驱动等待循环,不然必踩时序竞争的坑。
  5. adb root 掉线不是玄学:报 ERROR_PIPE / rknn_server abnormal 就是 buildroot adbd 不支持网络 root,换官方 adbd(04b 脚本)立愈。
  6. 持久配置放 /etc,别放 /tmp:/tmp 是内存盘,重启全没——血泪+1。

环境至此全部就绪,而且重启不丢:断电再来,40 秒后 adb connect 一下直接续上。地基打牢了

脚本:

upload 附件:rknn_manu.zip

您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:一切皆有可能

49

主题

485

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部
0