2、开发环境搭建:交叉编译工具链安装、目标板连接与调试、必备工具(ADB、SSH、串口)

好,咱们正式开始动手了。

这一章,说白了就是“把家伙事儿备齐”。你想想看,做嵌入式AI推理,代码是在PC上写,但跑是在开发板上跑。这中间差着十万八千里呢。怎么让PC上的代码变成板子能跑的东西?怎么跟板子说话?怎么把模型塞进去?这些就是本章要解决的问题。

我个人习惯,先把环境搭得干干净净再写代码。否则后面出个bug,你都不知道是代码问题还是工具链问题,那才叫一个头两个大。

2.1 交叉编译工具链:让PC为ARM打工

咱们的PC通常是x86架构,而目标板(比如树莓派、RK3588、Jetson Orin)大多是ARM架构。x86的二进制文件,ARM不认识。反过来也一样。

所以我们需要一个“翻译官”——交叉编译工具链。它运行在PC上,但生成的目标代码是ARM的。

2.1.1 工具链的选择

市面上工具链很多,我列几个常用的:

目标架构 推荐工具链 备注
ARMv7 (32位) arm-linux-gnueabihf- 老派板子,比如树莓派3B
ARMv8 (64位) aarch64-linux-gnu- 主流,RK3588、树莓派4/5
ARM Cortex-M arm-none-eabi- 裸机或RTOS,不带Linux

我个人建议,新手直接选 aarch64-linux-gnu-。为什么?因为现在64位ARM是主流,你买个新板子基本都是这个架构。我在项目中遇到过,有人图省事装了32位工具链,结果板子是64位的,编译出来的程序一运行就报错,折腾了半天。

2.1.2 安装步骤(以Ubuntu为例)

其实很简单,一条命令的事:

sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu

装完之后,验证一下:

aarch64-linux-gnu-gcc --version

看到版本号,就说明装好了。

小提示: 如果你用的是Docker环境,记得拉取带交叉编译工具的镜像。比如 arm64v8/ubuntu 系列。我习惯在Docker里搞一套干净的环境,避免污染宿主机。

2.1.3 第一个交叉编译程序

写个最简单的hello world:

// hello.c
#include <stdio.h>

int main() {
    printf("Hello from ARM!\n");
    return 0;
}

编译:

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

file 命令看看:

file hello
# 输出: ELF 64-bit LSB executable, ARM aarch64, ...

嗯,看到“ARM aarch64”就对了。这个文件在PC上跑不了,得扔到板子上跑。

注意: 千万别在PC上直接运行交叉编译出来的程序!我刚开始学的时候犯过这个傻,结果报错“Exec format error”。后来才明白,架构不同,跑不了的。

2.2 目标板连接与调试:怎么跟板子“说话”

工具链装好了,代码也编译了。怎么把程序弄到板子上?怎么调试?

这里我介绍三种方式:SSH、ADB、串口。它们各有各的用处。

2.2.1 SSH:最常用的远程登录

SSH是嵌入式开发中最常用的方式。只要板子和PC在同一个局域网,就能用。

首先,确保板子开了SSH服务。一般Linux板子默认都开了,没开的话:

sudo systemctl start sshd
sudo systemctl enable sshd

然后,在PC上连接:

ssh username@板子IP地址

比如:

ssh root@192.168.1.100

输入密码,就连上了。之后你就可以像操作本地终端一样操作板子。

小技巧: 我习惯配置SSH免密登录。生成密钥对,把公钥扔到板子的 ~/.ssh/authorized_keys 里。这样每次连接就不用输密码了,省事。

2.2.2 ADB:Android板子的好帮手

如果你的板子跑的是Android系统(比如一些带屏幕的开发板),那ADB是首选。

安装ADB:

sudo apt-get install adb

连接板子(通过USB线):

adb devices

看到设备列表,就说明连上了。然后可以:

  • adb shell — 进入板子的shell
  • adb push 本地文件 板子路径 — 把文件推到板子上
  • adb pull 板子路径 本地文件 — 从板子拉文件

我曾经在一个Android电视盒子上做AI推理,就是用ADB把模型和程序推上去的。比SSH还方便,因为不需要配网络。

2.2.3 串口:最后的救命稻草

串口是嵌入式开发中最原始、也最可靠的方式。当板子网络不通、系统起不来的时候,串口是你唯一的希望。

你需要一根USB转串口线(比如CH340、CP2102)。接线方式:

  • 板子的TX接串口线的RX
  • 板子的RX接串口线的TX
  • GND接GND

然后在PC上安装串口工具:

sudo apt-get install minicom

或者用 screen

sudo screen /dev/ttyUSB0 115200

这里的 /dev/ttyUSB0 是串口设备名,115200 是波特率。具体数值看你的板子手册。

注意: 串口接线最容易犯的错误是TX和RX接反。我刚开始做的时候,接反了怎么都连不上,还以为是板子坏了。后来才发现,TX接TX,RX接RX,那是错的。记住:交叉连接!

2.3 必备工具:ADB、SSH、串口的使用场景

这三个工具各有千秋,我总结一下:

工具 适用场景 优点 缺点
SSH Linux板子,网络正常 方便,支持文件传输 依赖网络
ADB Android板子,USB连接 不需要网络,功能强大 只支持Android
串口 所有板子,底层调试 最可靠,不依赖任何上层 速度慢,只能传文本

我个人习惯,平时用SSH。如果板子没网,就用ADB。如果板子连系统都起不来,那就只能上串口了。

2.4 实战:把交叉编译的程序传到板子上

好,咱们来走一遍完整流程。

假设你已经在PC上交叉编译好了 hello 这个程序。现在要把它传到板子上并运行。

方法一:通过SSH

scp hello username@板子IP:/home/username/
ssh username@板子IP
./hello

方法二:通过ADB

adb push hello /data/local/tmp/
adb shell
cd /data/local/tmp
./hello

方法三:通过串口

串口传文件比较麻烦,一般用 rzsz 命令。但说实话,我很少用串口传文件,太慢了。串口主要用来调试系统启动。

核心要点: 交叉编译 + 文件传输 + 远程执行,这三步构成了嵌入式开发的基本循环。把这个循环跑通了,后面的工作就顺了。

2.5 避坑指南

最后,分享几个我踩过的坑:

  • 工具链版本不匹配: 板子的glibc版本和工具链的glibc版本不一致,会导致程序运行时报错。解决办法:用板子自带的工具链,或者用静态编译。
  • 权限问题: 传到板子上的程序没有执行权限。记得 chmod +x
  • 路径问题: 板子的文件系统和PC不一样。别把PC的绝对路径硬编码到程序里。

嗯,环境搭建就到这里。下一章,咱们开始真正接触AI推理框架。准备好了吗?