第二章:部署环境搭建——交叉编译工具链安装、目标板系统烧录、SSH与串口连接配置、文件传输与远程调试环境搭建
各位同学,欢迎来到第二章。上一章我们聊了边缘AI芯片的整体选型思路,今天咱们要动真格的了——把开发环境真正搭起来。
说实话,我见过太多工程师,算法模型写得漂漂亮亮,一到部署环节就卡在环境搭建上。工具链装不上、系统烧录失败、串口没反应……这些坑我几乎都踩过。今天我就把这几年的实战经验掰开揉碎,带你一步步搞定。
本章核心目标:在宿主机(你的PC/服务器)上搭建完整的交叉编译环境,让目标板(边缘AI设备)能跑起来,并且能通过SSH和串口与你愉快地通信。
2.1 交叉编译工具链安装——为什么不能直接在目标板上编译?
你可能会问:为什么不在目标板上直接编译?原因很简单——目标板的算力太弱了。你想想看,一个Cortex-A53的CPU,编译一个Linux内核可能要几个小时,而你的PC几分钟就搞定了。
交叉编译,说白了就是在你的PC上生成目标板能运行的二进制文件。这里的关键是工具链的选择。
2.1.1 工具链的三种获取方式
| 方式 | 适用场景 | 我的建议 |
|---|---|---|
| 芯片厂商官方SDK自带 | 大部分商业芯片(瑞芯微、全志、海思等) | 首选,兼容性最好 |
| Linaro预编译工具链 | ARM架构通用开发 | 适合开源板卡(树莓派、Jetson Nano等) |
| Buildroot/Yocto自行构建 | 深度定制系统 | 高手向,新手慎入 |
我个人习惯用官方SDK自带的工具链。为什么?因为芯片厂商对自己的硬件最了解,他们提供的工具链往往做了针对性优化。我曾经在某个项目里用Linaro通用工具链编译了一个神经网络推理库,结果在目标板上跑起来总是段错误,折腾了两天,换成官方工具链后一次通过。
2.1.2 安装步骤(以瑞芯微RK3588为例)
嗯,这里我以瑞芯微的RK3588为例,其他芯片流程大同小异。
# 1. 下载官方SDK(通常包含工具链)
wget https://example.com/rk3588_sdk.tar.gz
tar -xzf rk3588_sdk.tar.gz
# 2. 找到工具链路径
cd rk3588_sdk/prebuilts/gcc/linux-x86/aarch64/
ls -la
# 你会看到类似 gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu 的目录
# 3. 设置环境变量(建议写入 ~/.bashrc)
export PATH=$PATH:/path/to/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=arm64
# 4. 验证安装
aarch64-none-linux-gnu-gcc --version
# 输出类似:aarch64-none-linux-gnu-gcc (GCC) 10.3.0
小技巧:我习惯在 ~/.bashrc 里加一个函数,方便切换不同工具链:
function set_toolchain() {
export PATH=$1/bin:$PATH
export CROSS_COMPILE=$2
echo "Toolchain set: $2"
}
# 使用:set_toolchain /opt/gcc-arm-10.3 aarch64-none-linux-gnu-
2.2 目标板系统烧录——SDK/固件的正确打开方式
工具链装好了,接下来得让目标板跑起来。系统烧录这一步,说白了就是把操作系统写到目标板的存储介质里(eMMC、SD卡、NAND Flash等)。
不同的芯片,烧录方式天差地别。我整理了一个表格,你对照着看:
| 芯片类型 | 烧录工具 | 烧录方式 | 注意事项 |
|---|---|---|---|
| 瑞芯微(RK系列) | RKDevTool | USB线刷(Loader模式) | 按住RECOVERY键上电 |
| 全志(Allwinner) | PhoenixCard / PhoenixSuit | SD卡烧录 / USB线刷 | 注意FEL模式进入方式 |
| 海思(HiSilicon) | HiTool | 网口烧录 / 串口烧录 | 需要配置TFTP服务器 |
| NVIDIA Jetson | SDK Manager | Host PC通过USB直连 | 需要NVIDIA账号 |
2.2.1 以RK3588为例的烧录实战
我记得第一次烧录RK3588时,卡在Loader模式进不去,折腾了半小时才发现是USB线的问题。这里给你避坑指南:
- 准备工作:下载官方固件(通常是一个 .img 文件),安装驱动(DriverAssitant)
- 进入Loader模式:按住板子上的RECOVERY键不放,再按一下RESET键,然后松开RECOVERY键
- 检查连接:在PC上执行
lsusb,应该能看到2207:350a类似的设备ID - 开始烧录:打开RKDevTool,选择固件,点击「执行」
警告:烧录过程中千万不要拔掉USB线!我曾经有一次手贱,烧到一半拔了线,结果板子变砖了。后来用短接Flash引脚才救回来。烧录时建议用带屏蔽的USB线,数据线越长越容易出问题。
2.3 SSH与串口连接配置——远程调试的左右手
系统烧好了,板子跑起来了,接下来怎么跟它交流?两个途径:SSH(网络)和串口(物理连接)。
我个人的习惯是:串口用来救急,SSH用来干活。为什么?串口稳定可靠,哪怕网络没配好也能用;SSH效率高,能传文件、能开多个终端。
2.3.1 串口连接——最后的救命稻草
串口连接其实很简单,但很多人第一步就错了——波特率没设对。常见的边缘AI板子,串口波特率一般是115200或1500000。
# 1. 安装串口工具(以minicom为例)
sudo apt-get install minicom
# 2. 查看串口设备
ls /dev/ttyUSB* # USB转串口
ls /dev/ttyACM* # 原生串口
# 3. 配置minicom
sudo minicom -s
# 进入配置菜单:
# - 串口设备:/dev/ttyUSB0
# - 波特率:115200
# - 数据位:8
# - 停止位:1
# - 无校验
# 4. 连接(更推荐用screen,更轻量)
sudo screen /dev/ttyUSB0 115200
避坑指南:我曾经遇到过串口只输出乱码的情况。排查步骤:
- 检查波特率是否匹配(最常见原因)
- 检查TX/RX是否接反(交叉连接)
- 检查地线是否连接(GND必须接)
- 检查电平是否匹配(3.3V vs 1.8V)
2.3.2 SSH配置——远程工作的标配
板子连上网络后,第一件事就是配SSH。这里我建议你配成静态IP,不然每次重启IP变了,你还要去接串口查。
# 在目标板上执行(通过串口或已连接的SSH)
# 1. 配置静态IP(以Ubuntu/Debian为例)
sudo vim /etc/netplan/01-netcfg.yaml
# 内容如下:
network:
version: 2
ethernets:
eth0:
dhcp4: no
addresses:
- 192.168.1.100/24
gateway4: 192.168.1.1
nameservers:
addresses: [8.8.8.8, 114.114.114.114]
# 2. 应用配置
sudo netplan apply
# 3. 启动SSH服务
sudo systemctl enable ssh
sudo systemctl start ssh
# 4. 在PC上测试连接
ssh root@192.168.1.100
重要:第一次SSH连接时,如果提示「Host key verification failed」,那是因为板子系统重刷过,密钥变了。执行 ssh-keygen -R 192.168.1.100 清除旧密钥即可。
2.4 文件传输与远程调试环境搭建——让开发效率翻倍
环境搭好了,怎么把编译好的程序传到板子上?怎么在PC上调试板子上的程序?这里我分享几个我常用的方案。
2.4.1 文件传输三板斧
| 工具 | 适用场景 | 命令示例 |
|---|---|---|
| scp | 小文件、偶尔传输 | scp test_app root@192.168.1.100:/home/ |
| rsync | 大文件、增量同步 | rsync -avz --progress ./build/ root@192.168.1.100:/app/ |
| nfs | 开发阶段频繁修改 | 挂载PC目录到板子,实时同步 |
我个人最推荐 rsync。为什么?因为它只传变化的部分。我有个项目,每次编译完要传200MB的库文件到板子上,用scp要等2分钟,换成rsync后,如果只改了几个源文件,传输时间缩短到5秒以内。
2.4.2 NFS挂载——真正的远程调试体验
如果你像我一样,一天要修改几十次代码然后测试,那NFS挂载是终极方案。说白了,就是把PC上的一个目录直接挂到板子上,板子运行的就是PC上的文件,改完代码重新编译,板子上立刻生效。
# 在PC上(作为NFS服务器)
# 1. 安装NFS服务器
sudo apt-get install nfs-kernel-server
# 2. 配置共享目录
sudo vim /etc/exports
# 添加一行:
/home/user/project/build 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
# 3. 重启NFS服务
sudo systemctl restart nfs-kernel-server
# 在目标板上(作为NFS客户端)
# 1. 安装NFS客户端
apt-get install nfs-common
# 2. 挂载
mount -t nfs 192.168.1.10:/home/user/project/build /mnt/nfs
# 3. 验证
ls /mnt/nfs
# 应该能看到PC上的文件
注意:NFS挂载时,no_root_squash 这个选项很重要。如果不加,板子上的root用户对挂载目录没有写权限。我曾经因为这个选项,调试了整整一个下午才发现问题。
2.4.3 GDB远程调试——断点跟踪的利器
文件能传了,但程序跑起来出错了怎么办?打日志?太慢了。我建议你直接用GDB远程调试。
# 在目标板上启动gdbserver
gdbserver :2345 ./test_app
# 在PC上连接(交叉编译版本的gdb)
aarch64-none-linux-gnu-gdb test_app
(gdb) target remote 192.168.1.100:2345
(gdb) b main
(gdb) c
# 程序会在main函数处停下
(gdb) n # 单步执行
(gdb) p variable_name # 打印变量值
小技巧:如果你觉得命令行GDB不好用,可以用VS Code的Remote Development插件。配置好SSH后,直接在VS Code里打开板子上的代码,设置断点,就像在本地调试一样。我现在的项目基本都是这么干的。
2.5 本章知识体系总览
说了这么多,我画了一张图帮你理清思路。这张图展示了从宿主机到目标板的完整工具链和数据流:
这张图把今天讲的内容串起来了。你看,宿主机这边负责编译、存储、调试控制,目标板那边负责运行、挂载、响应。中间的连接方式根据场景灵活选择——烧录是一次性的,SSH和串口是常开的,NFS和GDB是开发调试时用的。
好了,环境搭建这部分就讲到这里。你按照这个流程走一遍,应该不会出大问题。如果遇到什么奇怪的错误,先别慌,检查一下我提到的那些坑——波特率对不对?USB线好不好?权限够不够?八成就是这些细节问题。