2. 嵌入式开发环境搭建:交叉编译工具链安装、嵌入式Linux系统烧录、SSH与串口调试
说实话,嵌入式AI算法工程化这件事,第一步往往不是写代码,而是先把开发环境伺候好。我见过太多新手,算法模型在PC上跑得飞起,一上板子就懵了——连个helloworld都编译不过。嗯,这章我们就来把这几个基础环节捋清楚。
2.1 交叉编译工具链:为什么非得“交叉”?
你想想看,你的开发电脑是x86架构,而目标板子通常是ARM或RISC-V。x86上编译出来的二进制,ARM根本认不了。这时候就需要交叉编译工具链——说白了,就是在你的PC上,生成能在目标芯片上跑的程序。
我个人习惯用Linaro提供的GCC工具链,稳定且社区活跃。以ARM Cortex-A72为例,安装步骤其实很简单:
# 下载工具链(以aarch64为例)
wget https://releases.linaro.org/components/toolchain/binaries/latest-7/aarch64-linux-gnu/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz
# 解压到指定目录
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu.tar.xz -C /opt/
# 配置环境变量
export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu/bin
~/.bashrc 里,不然每次开终端都得重新 export。我刚开始就吃过这个亏,折腾了半天才发现是环境变量没生效。
验证是否安装成功,跑一下这个命令:
aarch64-linux-gnu-gcc --version
如果能看到版本号,恭喜你,工具链已经就绪。
2.2 嵌入式Linux系统烧录:把系统“灌”进板子
交叉编译环境搭好了,接下来得让板子跑起来。嵌入式Linux系统烧录,说白了就是把bootloader、内核、根文件系统这些玩意儿写到板子的存储介质里(比如eMMC、SD卡、NAND Flash)。
我项目中用得最多的是SD卡烧录方式,因为调试方便。以Rockchip RK3588平台为例,烧录工具是 rkdeveloptool:
# 进入Loader模式(按住板子上的RECOVERY键,再上电)
sudo rkdeveloptool db rk3588_loader.bin
sudo rkdeveloptool wl 0x0 uboot.img
sudo rkdeveloptool wl 0x4000 boot.img
sudo rkdeveloptool wl 0x8000 rootfs.img
sudo rkdeveloptool rd
如果你用的是树莓派这类通用板子,用 dd 命令直接写SD卡更省事:
sudo dd if=ubuntu-22.04-preinstalled-server-arm64.img of=/dev/sdb bs=4M status=progress
sync
嗯,这里要注意,/dev/sdb 是你的SD卡设备名,千万别写成系统盘,否则后果你懂的。
2.3 SSH与串口调试:板子跑起来后怎么跟它“说话”?
系统烧录完,板子启动后,你总得跟它交互吧?两种方式:SSH(网络)和串口(物理线缆)。
2.3.1 SSH调试
SSH是最常用的方式,前提是板子和PC在同一个局域网。我一般这样操作:
- 板子通过网线连到路由器,或者用USB转网口共享PC网络
- 查看板子IP(可以在路由器管理界面找,或者用串口先登录进去
ifconfig) - PC端执行:
ssh root@192.168.1.100
第一次连接会提示确认指纹,输入 yes 就行。默认密码通常是 root 或 admin,具体看你的系统镜像。
systemctl stop ufw 就好了。另外,如果板子没有SSH服务,记得先 apt install openssh-server。
2.3.2 串口调试
串口是最后的保底手段。哪怕板子网络没配好、系统起不来,只要bootloader还在,串口就能给你输出信息。我习惯用USB转TTL模块,三根线:TX、RX、GND。
接线方式:
- 板子的TX → 模块的RX
- 板子的RX → 模块的TX
- 板子的GND → 模块的GND
PC端用 screen 或 minicom 连接:
# 查看串口设备
ls /dev/ttyUSB*
# 用screen连接(波特率通常115200)
sudo screen /dev/ttyUSB0 115200
串口还有一个妙用——查看内核启动日志。当系统起不来时,串口输出的log能告诉你到底是哪里卡住了。比如常见的 Kernel panic - not syncing: VFS: Unable to mount root fs,说明根文件系统没挂载成功,可能是烧录时分区写错了。
2.4 环境验证:跑一个简单的AI推理程序
环境搭好了,总得验证一下。我习惯写一个最简单的TensorFlow Lite程序,在板子上跑个分类任务:
# 交叉编译一个TFLite示例
aarch64-linux-gnu-g++ -o label_image label_image.cc \
-I/opt/tensorflow -L/opt/tensorflow/lite/tools/make/gen/linux_aarch64/lib \
-ltensorflow-lite -lpthread -ldl
# 把可执行文件和模型推送到板子
scp label_image root@192.168.1.100:/root/
scp mobilenet_v1_1.0_224.tflite root@192.168.1.100:/root/
# SSH登录板子执行
ssh root@192.168.1.100
./label_image -i cat.jpg -m mobilenet_v1_1.0_224.tflite
如果能看到输出 tabby cat: 0.875 之类的结果,说明整个环境——交叉编译、系统烧录、SSH调试——全部打通了。
1. 让PC能编译ARM代码(交叉工具链)
2. 让板子能跑系统(烧录)
3. 让PC和板子能通信(SSH/串口)
这三件事搞定了,后面的事情就顺了。
嗯,这一章的内容就到这里。下一章我们会深入嵌入式Linux内核的裁剪与编译,到时候会用到今天搭好的环境。记得把工具链和烧录流程练熟,后面很多操作都依赖这些基础。