尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
香橙派RK3588交叉编译YOLOv5s部署:从hello到NPU推理
今天是这个系列真正打开嵌入式大门的一篇香橙派 RK3588 部署 YOLOv5s 的第六期教程主题就两个字——交叉编译目标产物是嵌入式开发的经典 hello。前几篇我们已经把香橙派5Orange Pi 5的烧录、登录、基本环境都摸过一遍了。如果你跟着做过来会发现板子本身跑的是Ubuntu/Debian系统理论上可以直接在板子上编译C代码但后续我们要在RK3588上部署YOLOv5s模型、交叉编译NPU推理程序的时候每次都在开发板上编译会非常痛苦速度慢依赖管理也乱。所以这一篇先做一个最小闭环在PC上用交叉编译器生成一个aarch64架构的hello可执行文件传到香橙派RK3588上运行验证整条编译、传输、执行链路都是通的。我会按照我实际操作的顺序来先讲清楚为什么要交叉编译再准备工具链然后写代码、编译、传板、运行最后把常见报错和后续YOLOv5s部署怎么衔接一起说清楚。整个过程以Ubuntu 22.04 PC 香橙派5为例Windows用户我会在环境准备部分单独说明。1. 为什么要交叉编译RK3588开发场景下的第一课1.1 香橙派5与RK3588平台的基本认知香橙派5用的是瑞芯微RK3588S芯片这颗芯片和RK3588同平台CPU部分是4核Cortex-A76 4核Cortex-A55的big.LITTLE架构64位ARMv8指令集所以我们编译出来的程序必须是aarch64ARM 64位格式。很多刚接触开发板的读者会有一个惯性思维既然板子能跑Linux那我直接在板子上写代码、编译不就行了确实可以香橙派5的Ubuntu镜像里自带gcc编译一个hello完全没问题。但你要理解后续部署YOLOv5s时我们经常要和Rockchip的NPU运行库、OpenCV、FFmpeg这些体积很大的依赖打交道。比如rknn-toolkit2里提供的板端推理示例有些要编译整个demo工程在PC上交叉编译可能只要一两分钟在板子上编译可能要十几分钟甚至更久。而且开发板存储空间有限装一堆编译缓存、中间文件越用越脏。“交叉编译”这个词拆开看就是“在一个架构上编译出另一个架构的程序”。我们的PC通常是x86_64香橙派是aarch64两者指令集完全不同。你不可能在PC上直接运行ARM程序也不能把x86的二进制直接扔到板子上跑。要解决这个矛盾就得用交叉编译器它在x86机器上运行但生成的机器码是ARM64的。1.2 交叉编译到底“交叉”在哪里正常编译比如在香橙派上执行gcc -o hello hello.c用的是板子自带的gcc编译器生成的是aarch64指令。PC上直接执行gcc -o hello hello.c生成的是x86_64指令。交叉编译则是让PC上的aarch64版本的GCC编译器干活它自己跑在x86_64架构上但编译目标处理器被指定为aarch64。我用一个不那么严谨但容易理解的类比交叉编译就像是一个会做西餐的中国厨师他人在中国x86_64环境但按照你的要求做出了一份意大利菜aarch64程序。他掌握的是异地风格的技能而不是飞一趟意大利再做菜。对应到命令行普通编译是gcc交叉编译是aarch64-linux-gnu-gcc。整个编译过程涉及的连接器、汇编器、库文件全都是aarch64版本。这也是它为什么不能直接调用PC上已有的/usr/lib库而需要一套独立的交叉编译库的原因。1.3 什么时候必须在PC上编译什么时候可以上板编译我的经验是写一个小工具、调Python代码、测试NPU推理脚本这些直接在板子上做没毛病毕竟Python本来就是解释执行。但是只要涉及C/C编译尤其是大型工程优先考虑交叉编译。具体来说这几个场景我强烈建议交叉编译RKNN板端推理程序C/C API的demo集成OpenCV、FFmpeg等第三方库的可执行文件需要给客户或用户分发二进制程序的情况。而下面这些场景可以直接在板子上做一个两个源文件的临时测试程序往系统目录里安装的库源码编译安装因为目标系统就是本机依赖CPU本机特征编译的代码比如有些工具会读取/proc/cpuinfo做优化。YOLOv5s部署的前期阶段我们主要是把rknn-toolkit2生成的rknn模型放到板子上跑Python推理这部分不涉及交叉编译。但一旦你需要把推理demo打包成独立可执行文件比如给现场设备用交叉编译就是唯一靠谱的方式。2. 环境准备交叉编译工具链的安装与验证2.1 PC端环境要求Ubuntu为主Windows用WSL兜底我建议你的主力开发机用Ubuntu 20.04以上版本或者能装WSL的Windows。Ubuntu下面安装Arm交叉工具链是最简单的直接apt就能装完不需要手动配置PATH。Windows本身没有原生的Linux交叉编译环境虽然也可以用MinGW那套东西折腾但效率极低我也是踩过坑的。如果你的Windows已经装了WSL2那处理这个问题的方式很干净在WSL的Ubuntu容器里做编译。WSL和宿主机之间可以用cp、scp正常互传文件我实测下来和原生Ubuntu没有任何区别。唯一要注意的是如果你把交叉编译工具链装在了WSL里但编译好的文件要传到板子上网络配置要正确建议让WSL和Windows共享网络或者直接用scp从WSL发送到板子它们之间走的是局域网IP没问题。我自己的主力环境是Ubuntu 22.04交叉编译器用apt源里的gcc-aarch64-linux-gnu版本是GCC 11系列够用且稳定。2.2 用apt安装aarch64交叉编译器Debian/Ubuntu系统下安装命令如下sudo apt update sudo apt install -y gcc-aarch64-linux-gnu装完之后检查一下版本aarch64-linux-gnu-gcc --version正常情况下会输出类似这样的信息aarch64-linux-gnu-gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0这一步说明交叉编译器已经可以执行了。这个工具链包含的完整命令名是aarch64-linux-gnu-gcc aarch64-linux-gnu-g aarch64-linux-gnu-ld aarch64-linux-gnu-strip它们之间的关系和普通gcc套件完全一样。编译C程序时用g版本链接库、裁剪体积时用strip版本。2.3 手动工具链方案Linaro与Rockchip SDK工具链说明如果你不喜欢apt源里带的版本或者后续要编译RKNPU官方demo时希望和SDK版本保持一致可以选择手动下载工具链。一种方式是使用Arm官方提供的GNU工具链搜索关键词“Arm GNU Toolchain AArch64”下载后会得到一个类似arm-gnu-toolchain-x86_64-aarch64-none-linux-gnu的目录。解压后把bin目录加到PATH里即可export PATH$PATH:/path/to/arm-gnu-toolchain/bin它的编译器命令是aarch64-none-linux-gnu-gcc注意和apt版本的后缀略有不同但用法一样。另一种方式是直接使用Rockchip SDK或者rknn-toolkit2里面的预编译版本。瑞芯微在发布BSP时通常会带一套prebuilt GCC路径一般是prebuilts/gcc/linux-x86/aarch64/下你只要把它也export到PATH里就行。之前有网友询问野火RK3568交叉编译工具链下载其实RK3568和RK3588都是aarch64架构用同一套Linaro工具链完全没问题没必要非要区分“瑞芯微专用版本”。这里我给一个明确的建议新手直接用apt install gcc-aarch64-linux-gnu不要纠结什么版本特效。你的目标是先把hello跑起来不是要复现某个老工程的特定编译环境。2.4 工具链自检编译一个小目标确认版本工具链装好后我建议先做一个最小的编译测试确认它能正常生成aarch64文件。写一个单行的c文件int main(void) { return 0; }保存为test.c然后编译aarch64-linux-gnu-gcc -o test test.c file test执行file命令看到输出第一行是ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, for GNU/Linux 3.7.0, not stripped只要看到ARM aarch64就说明交叉编译器工作正常。这一步非常关键很多人装完工具链直接写hello跑出一个Exec format error回头排查半天才发现编译出来的是x86文件。3. 编写并交叉编译第一个hello程序3.1 hello.c怎么写不是“一句话”而是信息验证程序对于嵌入式开发来说hello程序的意义不只是打印一行“hello”而是验证整条工具链、运行环境、日志输出通道都是正常的。我习惯把hello写得稍微多一点让它输出板子的CPU架构、内核版本、CPU型号这样一旦程序跑起来所有想确认的信息就都出来了。新建hello.c#include stdio.h #include stdlib.h #include unistd.h int main(void) { printf(hello from OrangePi5 / RK3588S\n); printf(my pid: %d\n, getpid()); printf( uname info \n); int ret system(uname -a); (void)ret; printf( cpuinfo (first lines) \n); ret system(cat /proc/cpuinfo | grep -E model name|Hardware|CPU part | head -n 6); (void)ret; printf(hello done, cross-compile works!\n); return 0; }这段代码里有一个getpid()是为了确认程序确实在板子上作为独立进程执行了而不是某个shell内置操作的结果。system(uname -a)和cat /proc/cpuinfo则用来打印板级信息跑一次就能看到香橙派5的内核版本和CPU架构。注意你在PC上交叉编译的时候头文件unistd.h和stdlib.h都能找到因为apt工具链自带了aarch64版的C库头和linux内核头文件所以这个代码在PC上编译就能引用板端相关的头文件。3.2 编译命令与参数解释动态编译vs静态编译先把hello.c交叉编译成动态链接版本aarch64-linux-gnu-gcc -O2 -Wall -o hello hello.c参数含义-O2开启二级优化对于这种小代码无所谓但以后编译RKNN推理程序时必须开优化否则帧率会难看-Wall打开警告有隐性问题时会提示-o hello指定输出文件名为hello。编译之后用ls -lh hello看一下文件大小。动态链接的hello大概在10KB到30KB之间非常小。然后我们再编一个静态版本aarch64-linux-gnu-gcc -static -O2 -o hello_static hello.c静态版本通常有500KB到1MB多。为什么差别这么大因为静态编译会把用到的C库代码直接打进可执行文件里动态编译则只保留一个指向系统共享库的“引用”。这两种方式各有适用场景动态版本体积小依赖板子上的glibc和动态链接器适合你的板子系统版本和编译工具链匹配的情况静态版本不依赖板子上的动态库拷过去就能跑适合环境复杂的场合但体积大而且一旦C库有安全漏洞重新编译很麻烦。在YOLOv5s部署这类实际项目里我不会随便用-static。因为后续要链接rknn runtime、opencv这些库有些库只提供了动态库用静态编译会遇到各种额外问题。hello阶段两个版本都编译出来是为了体验区别更方便理解动态库机制。3.3 file、ldd、readelf三个命令判断编译结果是否合格编译完之后三个命令必用它们能帮你确认编译产物是不是真的能在板子上跑。首先是filefile hello hello_static如果输出里是ARM aarch64就是正确的。如果出现x86-64说明你用了本机gcc重新确认一下编译器命令。其次是readelf它可以看动态链接器的路径readelf -l hello | grep interp应该输出[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]这个路径是板端动态链接器的位置。如果路径不对板子运行时就会报“No such file or directory”哪怕文件本身是存在的。最后是ldd它在你PC上执行时是依靠qemu或直接解析二进制来显示依赖库的。如果没有安装qemu可能看不到预期的结果如果安装了你会看到类似linux-vdso.so.1 (0x0000fffff3ef0000) libc.so.6 /usr/aarch64-linux-gnu/lib/libc.so.6 /lib/ld-linux-aarch64.so.1正常情况下不需要在PC上纠结ldd在板子上执行更准确。你只需要记住动态编译产物的体积小静态编译的体积大。4. 把hello传到香橙派5上运行4.1 传输方式ssh/scp、U盘、串口编译好了怎么把文件弄到板子上最常见的是用scp。前提是PC和香橙派5在同一个局域网里并且板子的SSH服务已经开启。查看板子IP地址可以直接在板上执行ip addr show或者从路由器后台找香橙派的设备名。然后在PC上执行scp ./hello ./hello_static orangepi192.168.1.100:/home/orangepi/输入密码后文件就到板子上了。这里orangepi是香橙派官方Ubuntu镜像的默认用户名密码一般也是orangepi如果你改过就用自己的密码。如果你手边没有网络条件也可以用U盘把文件拷过去。把编译好的文件放进U盘插入香橙派挂载后复制到/home/orangepi/下面sudo mount /dev/sda1 /mnt cp /mnt/hello /home/orangepi/ sync sudo umount /mnt串口传输比较慢我一般只在没网、没U盘的情况下用通过minicom或MobaXterm的ZMODEM协议发送文件不太推荐给新手作为主路径。4.2 板端验证权限、执行路径、动态库依赖先SSH登录板子ssh orangepi192.168.1.100然后进入文件所在目录赋予执行权限并运行cd ~ chmod x hello hello_static ./hello如果一切正常你会看到类似输出hello from OrangePi5 / RK3588S my pid: 1234 uname info Linux orangepi5 5.10.110-xxx #1 SMP ... aarch64 aarch64 aarch64 GNU/Linux cpuinfo (first lines) ...看到这些输出说明交叉编译、传输、权限、运行环境四个环节全部跑通了。静态版本也可以运行一下./hello_static如果只验证“交叉编译能跑”静态版本在动态版本失败时是很重要的判断工具如果动态版本报错、静态版本能跑问题基本锁定在动态库/动态链接器不匹配如果两个都报Exec format error问题就在编译架构或内核。你还可以在板上执行ldd ./hello确认动态库是否存在ldd ./hello正常会输出/lib/ld-linux-aarch64.so.1对应的库列表。如果某个库缺失后面运行的报错信息会告诉你是哪一个。4.3 常见报错与排查Exec format error、not found、permission denied我把新手最常踩的板端报错汇总成一张表你在做这一篇时遇到问题可以直接对照。报错现象原因解决办法bash: ./hello: cannot execute binary file: Exec format error编译产物不是aarch64或者用了x86编译器生成x86程序用file hello检查确认输出是ARM aarch64重新用aarch64-linux-gnu-gcc编译bash: ./hello: No such file or directory文件确实存在但动态链接器路径不对或者动态库缺失也可能是文件没完全传完用readelf -l helloPermission denied文件没有执行权限执行chmod x hellohello: error while loading shared libraries: libxxx.so.6动态链接库缺失或版本不一致板上执行ldd hello确认缺失的库换静态编译版本或者编译链接时指定库路径串口/终端看不到输出程序可能卡在system调用上或者标准输出被缓冲代码里用printf(...\n)即可必要时加fflush(stdout)或者运行./hello还有一个隐藏坑如果你把hello放在了一个以noexec方式挂载的分区上比如某些/tmp挂载选项运行时会报Permission denied哪怕文件已经有执行权限。解决办法是把文件放到/home或/opt这种正常挂载的分区。5. 踩坑记录与后续YOLOv5s部署衔接5.1 我在实战中踩过的坑说一下我自己做这步时的真实经历希望能帮你绕开。第一次接触RK3588交叉编译时我在PC上直接用普通gcc编译了一个hello传到板子上一运行就报Exec format error。当时脑袋没转过弯来以为是板子系统坏了后来用file一看发现是x86-64的ELF立刻脸都红了。现在我的习惯是任何编译产物传到板子前先在PC上跑一遍file确认架构。第二次踩坑是动态库版本问题。我用Ubuntu 22.04的交叉工具链glibc 2.35编译hello然后放到板子上跑那个板子系统是别人精简过的glibc版本只有2.31结果报错找不到GLIBC_2.34。后来用-static编译解决了。这个教训对后续YOLOv5s部署非常重要如果你要给多台香橙派发布程序最好用目标系统自带glibc版本一致的编译器或者干脆静态链接别偷懒。第三次是scp传文件传一半文件大小不对运行时报“No such file or directory”。原因是网络传输过程中断了但scp没提示报错。解决办法很简单传完后对比一下大小或者直接重新传一遍。另外还要提醒一点不要在Windows上直接用记事本编辑hello.c然后保存。Windows记事本可能会加入BOM和CRLF换行虽然这段代码大概率不影响编译但后续写CMakeLists.txt时会被坑得欲哭无泪。建议统一用VS Code、Notepad或者直接在Ubuntu里用vim/nano编辑。5.2 交接下一个任务从hello到YOLOv5s的NPU推理hello跑通之后接下来YOLOv5s部署就顺理成章了。瑞芯微官方的rknn-toolkit2在PC端负责把yolov5s的PyTorch模型转换成rknn格式转换后的rknn模型要在香橙派RK3588上进行NPU推理。官方提供的板端示例C代码就需要用交叉编译来生成aarch64可执行文件。这一步通常涉及交叉编译时链接librknnrt.soRKNN runtime库用CMake组织工程指定工具链为aarch64-linux-gnu-gcc把编译好的推理程序、rknn模型、待检测图片一起传到板子上板子上运行程序调用NPU做YOLOv5s推理。所以本篇hello的价值不只是让你体验一次“能在板子上打印字符串”的乐趣而是把PC编译工具链和板端执行环境之间的链路全部打通。之后再去编译官方demo你会非常自然地理解整个流程。我还建议你花一点时间把CMake基础用法掌握一下。后续yolov5s推理demo基本都是CMake工程如果你只会命令行gcc遇到多文件、多库时会很吃力。最简示例cmake_minimum_required(VERSION 3.16) project(hello_demo C) set(CMAKE_C_COMPILER aarch64-linux-gnu-gcc) add_executable(hello hello.c)然后把编译方式改成mkdir -p build cd build cmake .. make这个CMakeLists出现在很多官方demo里是一个通用模板。5.3 给新手的时间预算建议按照我的经验前三篇如果你按部就班做环境都已经好了。这一篇交叉编译hello熟练的话五到十分钟就完事。新手如果报错比较频繁建议准备两个小时主要时间不要浪费在工具安装上而是花在理解三个概念aarch64与x86的区别、动态链接与静态链接的区别、file命令如何验证架构。我把整个流程拆成几个检查点每完成一个就标记一下PC上交叉编译hello成功file命令显示aarch64板子上运行uname -a确认系统是aarch64scp传文件成功板子上执行./hello看到完整输出。这四个检查点全部通过你就可以说“交叉编译环境我已经搞定了”。接下来我们会正式走进YOLOv5s模型转换、量化以及NPU推理环节那才是这个系列真正精彩的部分。在写这篇之前我刚用同样的方法给手头的另一块RK3568板子也跑了一遍hello流程几乎一模一样唯一区别是板端系统版本不同动态链接库有细微差异。所以你在其他RK系列板卡上只要复用这套思路基本都不会有大问题。交叉编译这个东西第一次跑通之后后面就是肌肉记忆了。今天的hello虽小它验证的整条工具链就是你以后部署YOLOv5s推理程序的底气。
RELATED

相关推荐

仅退款逼出千里追讨:徐州商家驱车千公里赴沪要回8.59元香菜

仅退款逼出千里追讨:徐州商家驱车千公里赴沪要回8.59元香菜

(知潮网)8.59元,一捆香菜,从江苏徐州到上海,一千多公里。 9月28日,徐州做生鲜买卖的朱先生,干了一件算经济账绝对亏本的事。他开车跑了一千多公里,专程去上海,把已经卖掉…

📅 2026/10/1 14:58:14
树莓派5部署YOLOv5实战:车间视觉检测的六大坑与解决方案

树莓派5部署YOLOv5实战:车间视觉检测的六大坑与解决方案

把一台树莓派5塞进生产车间跑自己训练的YOLOv5模型,听起来是个很酷的落地Demo,真干起来才知道,这活儿比配一台普通Linux服务器麻烦得多。车间里有粉尘、电压波动、没有标准网络环境,设备还得被产线节拍追着跑。前前后后折腾了半个…

📅 2026/10/1 14:58:14
零代码平台能实现什么业务场景?

零代码平台能实现什么业务场景?

企业日常运营中有大量场景需要数据收集、流程审批和业务管理,但又不值得动用庞大的IT开发资源或采购昂贵软件。而这些正是零代码平台擅长的领域。总的来说,几乎能想到的业务场景,零代码应用平台都能完美覆盖。以微加云表单为例,其…

📅 2026/10/1 14:58:14
MORE NEWS

更多资讯

📰

敢于拼搏,敢于面对

毕业之后需要工作经验,想着找个工作混两年,但是闲着也是闲着,学习一门C语言说不准以后还会用得上,也想凭点本事出人头地,让自己也风光一阵。开始学的目标也很模糊,不知道会不会坚持下来,想着拼尽…

📰

3个精选降AI率工具,让你的论文彻底告别AI痕迹[必看]

最近不少同学私信我,说论文明明是自己一个字一个字敲的,用AI帮忙理了理思路,结果学校AIGC检测直接飙到30%以上,整个人都懵了。这事儿还真不是小部分人遇到的,现在查重平台陆续上线AI检测功能,查重AI双重标准…

📰

告别毕设内耗!Paperxie 一站式 AI 论文工具,帮你把时间还给研究本身

前言 临近毕业,很多同学一边实习、备考,一边硬扛毕业论文,时间被切割得七零八落。 想写论文,第一道坎就是文献:外文文献读不懂,中文文献堆成山,梳理研究现状要耗费几周;好不容易写完…

📰

Claude Code 报 model_not_found?把 settings.json 的模型映射改到 TaoToken

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

学生宿舍管理系统|基于java + vue学生宿舍管理系统(源码+数据库+文档)

学生宿舍管理系统 目录 基于springboot vue宿舍管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取: 基于springboot vue学生宿舍管理系统 一、前言 博主介绍&…

📰

超临界水制氢

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬