news 2026/10/2 12:12:09

香橙派RK3588部署YOLOv5s:交叉编译Hello World实战教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
香橙派RK3588部署YOLOv5s:交叉编译Hello World实战教程

【手把手从头到脚香橙派RK3588yolov5s教程】06交叉编译hello

聊到在香橙派RK3588上部署YOLOv5s,很多朋友第一步就卡在交叉编译上。“交叉编译hello”这几个字,拆开看每一个都认识,合在一起就让不少新手直接熄火。这一期教程把它一次性讲透:为什么要交叉编译、工具链怎么装、Hello World怎么编出来、怎么传到开发板上跑起来,每一步都有完整命令和踩坑记录。

先说清楚背景。RK3588这颗芯片用的是ARM架构,而我们日常开发用的电脑绝大多数是x86_64架构,两者的指令集完全不一样,在x86电脑上直接编译出来的程序,放到ARM板子上根本没法执行。交叉编译的意思,就是在x86主机上使用专门针对ARM64的工具链,编译出能在香橙派上运行的可执行文件。这一步是后续所有部署工作的地基——后面要交叉编译OpenCV、编译各种依赖库,甚至给YOLOv5s的推理程序做ARM版本,统统绕不开这个能力。

这篇教程适合手上有一块香橙派5(RK3588)、打算在上面跑YOLOv5s,但还没搞定交叉编译环境的朋友。跟着实操一遍之后,你不仅能得到一个在开发板上正常运行的Hello World,更重要的是把整套交叉编译的思路、工具链选型和排错方法都理顺。后面再遇到“编译出来的程序上板跑不了”这种问题,你就知道问题出在哪一层了。

1. 在RK3588上部署YOLOv5s,为什么要先做交叉编译

很多人第一反应是:开发板上又不是不能装编译器,直接把源码拷到板子上编不就行了?理论上的确可以,我给你展开讲讲为什么实操中几乎没人这么做。

1.1 架构差异是一切问题的根源

先补一个最基础的概念。CPU有各自的指令集架构,x86和ARM是两套完全不同的指令集。编译器的作用就是把C代码翻译成CPU能认识的机器指令,x86编译器翻译出来的是x86指令,ARM编译器翻译出来的是ARM指令,两者互不通用。

RK3588是ARM64架构,具体来说是AArch64,也就是64位ARM指令集,内核是四颗Cortex-A76加四颗Cortex-A55。你手里的电脑,只要是近几年的x86_64平台,架构就是AMD64。这里就有个很直白的矛盾:在x86电脑上用系统自带的gcc编译,出来的可执行文件是x86格式的,拿到香橙派上一运行,系统直接认不出来。

这个报错长什么样,我后面会贴出来。很多新手第一次看到“Exec format error”完全懵了——文件明明存在,权限也给了,为什么不能执行?本质就是格式不对,拿一张中文报纸让只会读英文的人看,他当然看不懂。

1.2 交叉编译到底在“交”什么

所谓交叉编译,按教科书说法是“在一个平台上生成另一个平台上可执行代码的过程”。说得再直白点:你的电脑是x86,香橙派是ARM,两边语言不通,交叉编译就是你用一台“翻译机”,在x86电脑上把代码翻译成ARM能执行的机器码。

这台“翻译机”就是交叉编译工具链,核心是交叉编译器。它的名字里的“交叉”体现在哪里?比如你安装好后,会看到一串命令叫aarch64-linux-gnu-gcc,这个名字有三个关键部分:

  • aarch64表示目标架构是ARM64位;
  • linux表示目标是Linux系统;
  • gnu表示用的是GNU工具链(也就是GCC那一套)。

看明白这个命名规则,你以后再见到arm-linux-gnueabihf-gcc、aarch64-none-linux-gnu-gcc这类工具链,一眼就能读出它是个什么东西——都是交叉编译器,只是目标架构或C库版本不同。

为什么不直接上板编译?理由很实际。香橙派虽然能装gcc,但ARM版的编译速度远不如x86桌面机,而且板子上编译大项目(比如OpenCV)动辄一两个小时,风扇呼呼转;更重要的是,整个YOLOv5s部署流程中,模型转换、预编译依赖库这些环节本来就在x86主机上做,交叉编译能让你在主机上完成全部编译工作,最后只把成品文件拷到板上。这是嵌入式开发的通行做法,不是谁拍脑袋定的规矩。

1.3 这一步在整个部署流程里的位置

我这套教程是按“从头到脚”的顺序推进的,前几期解决了板子到手、系统烧录、远程登录这些准备工作,这一期讲交叉编译,是在为后面的重头戏铺路。

你可以把YOLOv5s在RK3588上的落地流程想象成一条流水线:先用PyTorch训练好YOLOv5s模型,导出成ONNX,再用RKNN-Toolkit在x86电脑上把ONNX转成RK3588 NPU能识别的rknn格式,最后在板子上部署一段推理程序。这段推理程序如果走C/C++路线,大概率需要交叉编译;路径上还要依赖OpenCV等库,这些库在板子上不一定有现成的ARM版本,要么用预编译包,要么自己交叉编译。所以现在把交叉编译跑通,后面每一步都会顺畅得多。

说白了,这期教程的Hello World就是个“环境自检”:如果连一个小小的Hello World都编不出来、跑不起来,那后续编译OpenCV、集成rknn runtime更是无从谈起。把它当成一块试金石,就知道自己的工具链和环境到底通没通。

2. 交叉编译工具链的选型与安装

工具链选不对,后面全是无用功。这一节我把主流方案摆出来,直接告诉你哪个最省事,以及验证工具链是否可用的具体方法。

2.1 三套主流工具链怎么选

目前社区里常用的是下面这三套,我分别说明它们的优缺点:

方案来源优点缺点适合人群
Ubuntu软件源里的gcc-aarch64-linux-gnu系统自带软件源一条apt命令装完,兼容性好版本跟随系统,可能偏旧绝大多数新手,推荐先用这个
Linaro GCC工具链Linaro官网下载版本新、优化选项多需要手动配置环境变量需要特定编译器版本或做深度优化
瑞芯微SDK自带工具链瑞芯微官方SDK与SDK配套,贴合RK平台包体大、路径要自行配置直接使用官方SDK开发包的场景

我的建议很明确:第一步就用gcc-aarch64-linux-gnu。原因有两个。一是省心,apt会帮你处理依赖,装完就能用,不会出现“下载了工具链却缺库”的情况;二是这套工具链是Debian/Ubuntu官方发布的,质量和兼容性有保障,搞YOLOv5s部署完全够用。等你之后真的碰到性能或版本瓶颈了,再去折腾Linaro也不迟。

2.2 Ubuntu上一条命令安装

我这里默认你是在x86_64的Ubuntu系统上操作,开发板系统则刷好了官方或Debian系的ARM64镜像。执行下面的命令:

sudo apt update sudo apt install -y gcc-aarch64-linux-gnu

安装过程会拉取交叉编译器以及配套的binutils、libc6-dev-arm64-cross等辅助工具。装完之后,在终端里检查一下命令是否存在:

which aarch64-linux-gnu-gcc

能打印出/usr/bin/aarch64-linux-gnu-gcc这类路径,说明装好了。再看一下版本:

aarch64-linux-gnu-gcc --version

输出中会包含 GCC 版本号,比如gcc version 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)。不同Ubuntu版本带的GCC版本不一样,不影响Hello World这步,后面如果遇到需要指定GCC版本的场景,再单独处理。

2.3 装完怎么验证可用

光看版本号还不够,我建议做一个更硬核的验证——交叉编译生成一个空程序,然后用file命令检查它的架构类型。这里其实已经在做“预演”了:

echo 'int main(){return 0;}' > /tmp/test.c aarch64-linux-gnu-gcc /tmp/test.c -o /tmp/test_arm file /tmp/test_arm

预期输出里会出现关键字段:

/tmp/test_arm: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=..., for GNU/Linux 4.1.0, stripped

看到ELF 64-bit LSB pie executable, ARM aarch64这一行,就说明交叉编译器真的在干活了,编译出来的是ARM64格式而不是x86格式。这个file命令是交叉编译里的“照妖镜”,后面每次编译完都跑一下,能避免你把x86产物误当成ARM产物传到板子上,然后又一脸懵地找原因。

提示:如果你在Windows上开发,可以用WSL2运行Ubuntu,或者装个虚拟机。交叉编译本身是Linux生态的玩法,Windows原生环境玩起来非常别扭,别硬刚。

2.4 补充:Linaro工具链与官方SDK工具链

如果之后确实需要换工具链,有一个口碑很好的老牌方案:Linaro提供的预编译GCC工具链,包名类似gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz,下载解压后,把bin目录加进PATH即可:

export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin:$PATH

直接进终端敲命令设环境变量重启就失效,建议写进~/.bashrc。另外瑞芯微SDK自带的工具链一般位于SDK的prebuilts目录,路径结构更复杂,适合跟着官方SDK工程走的朋友,这里不展开,遇到再用到时自然就明白了。

3. 手把手写出并编译第一个ARM版Hello World

环境就绪,接下来就是正式的Hello World实操。这一节会细致到每一步命令和每个输出字段,照着做就能跑通。

3.1 源码怎么写才不会被后面的坑埋雷

写一个Hello World,看起来闭着眼都能写,但有几个细节值得注意。先建个项目目录,保持习惯:

mkdir -p ~/cross_hello && cd ~/cross_hello vim hello.c

代码内容:

#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello from Orange Pi RK3588!\n"); printf("Cross compile demo: %s\n", argv[0]); return 0; }

我故意加了一行打印argv[0],这样你在板子上运行时能直接看到可执行文件的名字,直观感受到“程序真的是从板子上跑起来的”。源码本身没什么特别,但有两个习惯值得从现在就养起来。

第一,main函数建议带参数。嵌入式开发后面经常要用命令行参数控制程序行为,现在把架子搭好,后面扩展直接改就行。第二,记得加return 0;,这是程序正常结束的标志,也能避免一些奇怪的运行时告警。

3.2 编译命令与产物信息检查

编译命令如下:

aarch64-linux-gnu-gcc hello.c -o hello_arm

如果没报错,会在当前目录生成一个hello_arm文件。接下来必须做的一件事是检查产物格式:

file hello_arm

正常输出:

hello_arm: ELF 64-bit LSB pie executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1, BuildID[sha1]=..., for GNU/Linux 4.1.0, not stripped

看到ARM aarch64就说明编译目标对了。这份文件的几个关键信息我解释一下,你以后排查问题时经常会用到:

  • dynamically linked:动态链接,意味着程序运行时依赖共享库;
  • interpreter /lib/ld-linux-aarch64.so.1:指定了动态链接器的路径,这是ARM64系统上的标准路径;
  • not stripped:二进制里还带着符号表,调试用得上,正式发布时可以用strip命令瘦身。

再分享一个进阶检查手法,用readelf看ELF头,能确认更多细节:

aarch64-linux-gnu-readelf -h hello_arm

输出里重点看Machine: AArch64这一行,如果显示的是Advanced Micro Devices X86-64,说明你的编译产物根本不是ARM的,赶紧回查工具链。

3.3 动态编译还是静态编译,怎么选

这是交叉编译里最容易踩坑也是引起最多困惑的一个选择。前面那个dynamically linked意味着程序运行时需要到共享库里面找printf等函数的实现。在x86主机上跑没问题,因为主机的动态库齐全;但一旦拷到香橙派上,如果板子里缺少对应的libc.so.6,程序就会罢工。

验证方法很简单,先在电脑上看一下依赖:

aarch64-linux-gnu-readelf -d hello_arm | grep NEEDED

你会看到类似libc.so.6这样的共享库条目。这时候就面临一个问题:香橙派系统镜像是否带了这个库?只要你的板子系统是完整的Ubuntu/Debian ARM64镜像,libc.so.6基本都在,动态编译没问题。但如果你用的是一个精简rootfs,或者打算把程序塞进initramfs这类极简环境,那就必须静态编译。

静态编译命令:

aarch64-linux-gnu-gcc -static hello.c -o hello_arm_static file hello_arm_static

输出中会出现statically linked字样,说明所有依赖的库都打包进了这个文件,体积会明显变大(从十几KB变成700多KB),但好处是随便拷到哪个ARM64 Linux环境都能跑,不依赖任何共享库。

我的建议是:调试阶段用动态编译,方便定位问题;正式部署到板子上的时候,如果目标环境库齐全,动态没问题,如果不确定,直接用静态版,省心。YOLOv5s部署时涉及大量依赖库,到时候会单独讲每个库的处理方式,但“静态还是动态”这个判断模型,你现在就应该建立起来。

注意:千万别把静态编译理解成“一切都静态就好”。静态版体积大、启动稍慢,有些库也不支持静态链接,后续编译OpenCV时你就体会到了。这里记住“默认动态、必要时静态”的原则就够了。

4. 把Hello World部署到香橙派上跑起来

编译出了ARM64的可执行文件,下一步就是传到板子、运行验证。我实测过几种方式,直接把经验拿来给你参考。

4.1 三种传文件的方式实测对比

先用ifconfig或hostname -I在香橙派上查一下IP地址,假设开发板IP是192.168.31.118,用户名是默认的orangepi。然后选一种方式传文件。

方式一:scp,Linux/macOS和Windows下都能用,命令行解决,我最常用。

scp hello_arm orangepi@192.168.31.118:~/

会提示输入密码,默认密码一般是orangepi。传完后文件就在板子的home目录下。

方式二:Windows下用WinSCP或MobaXterm的SFTP面板,图形化操作,双击拖拽就能传。适合不习惯敲命令行的情况。MobaXterm还能顺便当终端用,一举两得。

方式三:U盘拷。适合哈希冲突、网络不通的极端情况,但效率最低,只作为备用方案。

三种方式里,我推荐优先掌握scp,原因很简单:后面反复调库、传模型文件时你会不停地用,而scp一条命令搞定,还能配合脚本自动化。Windows用户装个OpenSSH客户端就有了scp,无脑可用。

4.2 在开发板上运行并确认结果

传完之后,通过SSH登录香橙派:

ssh orangepi@192.168.31.118

然后执行:

cd ~ ls -l hello_arm chmod +x hello_arm ./hello_arm

如果你之前用的是scp,文件权限一般是-rw-r--r--,没有执行权限,所以必须先chmod +x,不然直接运行会报Permission denied。补上权限后再运行,预期输出:

Hello from Orange Pi RK3588! Cross compile demo: ./hello_arm

看到这两行,恭喜你,整条交叉编译链路已经全通了——x86主机上编译,ARM板子上执行,这个“Hello World”证明了你已经具备了后续在香橙派上部署任何原生程序的基础能力。

4.3 别忘了在板上自查架构信息

运行成功后,建议顺手在板子上执行几个自查命令,把“知己知彼”这件事做扎实:

uname -m

输出应该是aarch64。再执行:

cat /etc/os-release

看看系统版本,记下来,后续装依赖库时,这个系统和架构信息就是你的“配货清单”。最后,如果你想直观感受交叉编译的意义,可以在板子上也跑一次file ~/hello_arm,如果没装file就先apt install file,输出应该和你电脑上看到的一致——都是ARM aarch64的ELF文件。

这里还有个小实验,属于我的课外加分题:在x86主机上随手写个临时文件,编译一个原生程序传上去跑一下,比如:

gcc hello.c -o hello_x86 scp hello_x86 orangepi@192.168.31.118:~/

然后在板子上运行./hello_x86,你会看到cannot execute binary file: Exec format error。亲身撞一次这个报错,比看十遍文档都管用,你会从骨子里理解“指令集不通用”到底是什么意思。

5. 交叉编译Hello的常见报错排查实录

这一节内容是很多教程不会写的,但恰恰是新手最需要的。我把实际操作中遇到频率最高的几个报错整理成档,每个都附上排查思路和解决方案。

5.1 Exec format error:十有八九是编错了平台

报错长这样:

-bash: ./hello_x86: cannot execute binary file: Exec format error

前面已经演示过如何触发它:把x86编译的二进制拿到ARM板子上执行。解决办法只有一个:用交叉编译器重新编译。如果确定自己用的是aarch64-linux-gnu-gcc但还是遇到这个错,那就要检查工具链是否真的生效了,比如你在Windows上装了某个ARM编译器的exe版本,生成的产物格式可能是MinGW格式而不是真正的Linux ARM ELF,这时候就得回到file命令检查产物。

5.2 “No such file or directory”其实最坑

这个报错最具迷惑性。你明明在执行一个存在且可见的文件:

-bash: ./hello_arm: No such file or directory

程序文件就在目录里,ls也能看到,但系统就是“找不到”。这个问题的本质是动态链接器缺失。前面提到interpreter /lib/ld-linux-aarch64.so.1,当程序启动时,系统会先找这个动态链接器,如果板子的系统里没有对应路径或者版本不对,就会抛出这个假象般的错误。

排查方法:

  1. 在板子上检查动态链接器是否存在:ls /lib/ld-linux-aarch64.so.1,如果不存在说明系统缺libc;
  2. 解决方式有两种:apt install libc6-arm64-cross(在板子上重新安装)或者干脆改用静态编译。

你的板子系统如果当初刷的是厂商的完整镜像,一般不会缺这个文件;如果用的是精简rootfs或厂商裁剪过的系统,就容易撞上。遇到这个报错时先冷静,用ls看看/lib下的东西,十有八九能定位问题。

5.3 Permission denied与运行环境依赖

这个就比较好理解了:

-bash: ./hello_arm: Permission denied

检查文件权限:

ls -l hello_arm

如果权限是-rw-r--r--,缺x权限,执行chmod +x hello_arm即可。这是小问题,但很多人传完文件后忘了这一步,在群里问半天。提前说一句:用scp传过去的文件普遍没有执行权限,养成“传完就 chmod”的习惯。

还有一种情况是文件系统挂载选项导致的,比如挂在noexec的目录下,可执行文件也会被拒绝运行。如果程序放在/data或者SD卡挂载点下遇到权限问题,检查一下挂载参数:

mount | grep noexec

把程序挪到home目录下即可绕开。

5.4 一张速查表解决大多数问题

把我这些年积累的交叉编译报错经验整理成对照表,遇到问题直接查:

报错信息可能原因排查与解决
Exec format error二进制架构不对用file检查目标文件,确认是ARM aarch64
No such file or directory动态链接器缺失或损坏检查/lib/ld-linux-aarch64.so.1,必要时静态编译
Permission denied无执行权限chmod +x,或检查挂载选项是否含noexec
symbol lookup error共享库版本不匹配检查LD_LIBRARY_PATH,比对库的版本
Segmentation fault代码或运行环境问题先用gdb调试,检查内存相关调用
编译期大量undefined reference头文件或链接库缺失检查依赖库是否安装,链接顺序是否正确

这表里后几项在你做YOLOv5s相关编译时会高频出现,现在存个档,到时候翻出来对照就行。

经验:遇到任何交叉编译问题,第一个动作永远是执行file 可执行文件和readelf -h 可执行文件,把格式、架构、链接方式这三个要素先搞清楚。90%的问题在这个步骤里就暴露了。

6. 交叉编译Hello和YOLOv5s之间还隔着什么

跑通了Hello World后,很多人会问:接下来呢?这一步和最终在RK3588上跑起YOLOv5s,中间还隔着一大段路,我给你把地图画清楚。

6.1 打通这条路的实际意义

先别小看这个Hello World,它验证的不只是“会编译”,而是一整套技术链路的可行性:x86主机上安装交叉工具链、编译出ARM64二进制、通过网络部署到板子、在ARM Linux上正常运行。这个链路就是你后续所有工作的主线,后续做模型推理、图像处理,走的都是同一条路,只是换成了更复杂的源码和库。

具体到YOLOv5s项目,交叉编译Hello World只是开胃菜,后面你至少会遇到这样几个场景。

第一,可能在板子上跑Python版的rknn推理,那就不需要交叉编译太多东西,但你需要确认板子上的Python、numpy、opencv-python这些依赖都装好了,这个反而更简单,直接装预编译包就行。

第二,如果走C/C++推理路线,用rknn-toolkit2在x86主机上把YOLOv5s的ONNX模型转成rknn格式,然后在板子上用librknnrt.so写推理程序。这段推理程序如果是自己C++写的,一般直接在板子上本地编译也行(板子上装了gcc的话),或者交叉编译后传上去。到这一步,你现在掌握的交叉编译能力就派上用场了。

第三,OpenCV是绕不开的硬骨头。YOLOv5s推理前后要做图像缩放、颜色转换、画框,OpenCV几乎是标配。ARM版OpenCV要么从源码在板子上编(慢),要么交叉编译(复杂),要么用预编译包(省心)。我建议先用预编译包,后续再按需深究。

6.2 后续几步怎么规划

按我的经验,接下来的节奏应该是这样安排。

先做模型侧工作:在x86主机上跑通YOLOv5s的推理,导出成ONNX,再用rknn-toolkit2转成rknn格式,在主机上先用模拟器验证模型能正常推理。这一步不涉及开发板,风险低、反馈快。

然后做板侧环境准备:确认香橙派上的系统、Python环境、rknn runtime库都装好,用官方的rknn自带的demo跑通,确保NPU能正常调用。瑞芯微官方提供的rknn_model_zoo里就有YOLOv5相关的demo,先把它跑起来。

最后再做定制化:把自己的模型替换进去,修改预处理和后处理的逻辑,加入自己的业务代码。这时候如果发现官方demo不满足需求,再考虑自己写C++推理程序,就需要组合你现在学的交叉编译、后面的OpenCV交叉编译能力。

这一路走过来,你会发现自己已经不再是“照着教程敲命令”的状态,而是真的理解了嵌入式Linux部署的完整逻辑。交叉编译Hello World就是这个理解过程的第一块基石,看似朴素,实际上撑起了后面所有的复杂工作。

我个人在实际操作中的体会是,交叉编译这件事,难的不是命令本身,而是对“架构”“工具链”“链接方式”这些抽象概念建立直观感知。如果你跟着这篇教程亲手撞过一两次报错,又亲手把问题定位清楚,那这个感知就已经建立起来了。后面碰到再复杂的问题,你都敢动手拆,这比会粘贴几行命令重要得多。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 12:11:56

Simulink AUTOSAR冗余数据类型根因与三步治理法

1. 项目概述&#xff1a;为什么“冗余数据类型”在AUTOSAR代码生成中会顽固出现&#xff1f;Simulink AUTOSAR工作流里&#xff0c;最让人头皮发紧的不是模型跑不通&#xff0c;也不是编译报错&#xff0c;而是生成的C代码里反复冒出不该存在的冗余数据类型——比如明明只用了一…

作者头像 李华
网站建设 2026/10/2 12:11:43

AI Coding 资讯 2025-09-17:把 Cursor Base URL 改到 TaoToken 的配置记录

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

作者头像 李华
网站建设 2026/10/2 12:11:22

标签化推送与已读统计怎么做?一次通知链路的工程复盘

一、一条通知&#xff0c;两万条记录去年汛期的一次强降雨预警&#xff0c;镇里要求在半小时内把撤离提示发到全镇八个村。我们照着老办法做了一次全量推送&#xff0c;触达常住人口两万三千人&#xff0c;其中党员六百四十人、帮扶对象三百一十二人。事后统计发现&#xff0c;…

作者头像 李华
网站建设 2026/10/2 12:11:04

树莓派5车间部署实战:供电散热与YOLOv5稳定运行指南

这台树莓派5&#xff0c;我在工位上跑得好好的。跑YOLOv5推理、刷Ubuntu、连屏调参&#xff0c;手感丝滑。结果真把它装进车间设备柜&#xff0c;连续踩了一整天的坑。重启、掉帧、断连、掉系统&#xff0c;每一步都卡得人头疼。这篇文章就把我在车间里被卡住的六件事完整写一遍…

作者头像 李华