3、开发环境搭建:交叉编译工具链安装、SSH远程连接配置、文件传输与同步(rsync)、系统镜像烧录与初始化
说实话,做嵌入式开发这么多年,我踩过最多的坑就是环境搭建。你想想看,代码写得再漂亮,编译不过去、烧录不进去、连不上板子,那都是白搭。这一章咱们就把这些基础活儿干利索,后面才能专心搞模型部署。
3.1 交叉编译工具链安装
交叉编译是什么?说白了就是在你的电脑上编译出能在ARM板子上跑的程序。你的电脑是x86架构,板子是ARM架构,编译器得知道怎么生成ARM的机器码。
我个人习惯用Linaro提供的工具链,稳定且社区支持好。以ARM Cortex-A72为例,咱们装aarch64版本。
核心要点:工具链版本必须与板子内核匹配,否则编译出来的程序可能跑不起来。
3.1.1 下载与解压
# 下载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/
# 重命名方便管理
mv /opt/gcc-linaro-7.5.0-2019.12-x86_64_aarch64-linux-gnu /opt/gcc-aarch64
3.1.2 配置环境变量
嗯,这里要注意。环境变量配不好,每次编译都得写绝对路径,烦得很。
# 编辑~/.bashrc,在末尾添加
export PATH=$PATH:/opt/gcc-aarch64/bin
export CROSS_COMPILE=aarch64-linux-gnu-
export ARCH=arm64
# 使配置生效
source ~/.bashrc
# 验证安装
aarch64-linux-gnu-gcc --version
小技巧:我习惯把工具链路径写到Makefile里,而不是全局环境变量。这样不同项目可以用不同版本的工具链,互不干扰。
3.1.3 测试编译
写个简单的hello world试试水。
// test.c
#include <stdio.h>
int main() {
printf("Hello from ARM board!\n");
return 0;
}
// 编译
aarch64-linux-gnu-gcc test.c -o test_arm
// 查看文件信息
file test_arm
// 输出: ELF 64-bit LSB executable, ARM aarch64, ...
看到"ARM aarch64"就对了。我曾经有一次忘了加静态编译选项,结果板子上缺动态库,程序跑不起来。后来我习惯加个-static,省心。
3.2 SSH远程连接配置
板子一般没有显示器键盘,全靠SSH远程操作。我建议一开始就把SSH配好,后面调试会舒服很多。
3.2.1 板端SSH服务开启
大部分官方系统镜像默认开了SSH。如果没开,手动启动一下:
# 检查SSH服务状态
systemctl status sshd
# 如果没启动
systemctl start sshd
systemctl enable sshd # 开机自启
3.2.2 网络连接方式
两种常见方式:
| 方式 | 优点 | 缺点 |
|---|---|---|
| USB网卡共享 | 不需要路由器,即插即用 | 速度一般,配置稍复杂 |
| 以太网直连 | 速度快,稳定 | 需要网线,IP需手动设置 |
我个人偏爱以太网直连。把板子和电脑用网线连起来,设置同一网段即可。
# 电脑端设置静态IP
sudo ifconfig eth0 192.168.1.100 netmask 255.255.255.0
# 板子端设置静态IP(通过串口或HDMI先登录)
ifconfig eth0 192.168.1.101 netmask 255.255.255.0
# 测试连通性
ping 192.168.1.101
3.2.3 SSH免密登录
每次输密码太烦了。我建议配个密钥对,一劳永逸。
# 电脑端生成密钥对
ssh-keygen -t rsa -b 4096
# 复制公钥到板子
ssh-copy-id root@192.168.1.101
# 测试登录
ssh root@192.168.1.101
注意:板子的root密码默认一般是空或123456。第一次登录后记得改密码,安全第一。
3.3 文件传输与同步(rsync)
做模型部署时,经常要往板子上传模型文件、代码、库文件。scp能用,但每次传整个文件太慢。rsync才是神器。
3.3.1 scp基础用法
# 上传文件
scp model.tflite root@192.168.1.101:/home/
# 下载文件
scp root@192.168.1.101:/home/log.txt ./
3.3.2 rsync增量同步
rsync只传变化的部分,第一次全量,后面就快了。我在项目中经常用它同步代码和模型文件。
# 基本用法
rsync -avz --progress ./deploy/ root@192.168.1.101:/home/deploy/
# 参数说明
# -a: 归档模式,保留权限和时间戳
# -v: 显示详细信息
# -z: 传输时压缩
# --progress: 显示进度
实战经验:我习惯写个同步脚本,每次改完代码直接运行脚本就同步到板子上了,省得手动敲命令。
#!/bin/bash
# sync_to_board.sh
rsync -avz --delete \
--exclude='.git' \
--exclude='__pycache__' \
--exclude='*.o' \
./deploy/ \
root@192.168.1.101:/home/deploy/
echo "同步完成!"
3.3.3 自动同步监控
如果你像我一样懒,可以用inotify实现自动同步。改完代码保存,板子上自动更新。
# 安装inotify-tools
sudo apt-get install inotify-tools
# 监控目录变化并自动同步
while inotifywait -r -e modify,create,delete ./deploy/; do
rsync -avz ./deploy/ root@192.168.1.101:/home/deploy/
done
3.4 系统镜像烧录与初始化
拿到一块新板子,第一件事就是烧系统。不同板子烧录方式不同,但思路差不多。
3.4.1 烧录工具准备
| 板子类型 | 烧录工具 | 镜像格式 |
|---|---|---|
| Raspberry Pi | Raspberry Pi Imager / dd | .img |
| Jetson Nano | SDK Manager / balenaEtcher | .img / .sdimage |
| RK3588系列 | RKDevTool / rkdeveloptool | .img / .raw |
3.4.2 以树莓派为例烧录
# 查看SD卡设备名
lsblk
# 假设SD卡是/dev/sdb
# 使用dd命令烧录(注意:这会清空SD卡所有数据)
sudo dd if=raspios-arm64.img of=/dev/sdb bs=4M status=progress
# 同步缓存
sync
# 烧录完成后,拔卡插到板子上启动
警告:dd命令一定要确认设备名正确。我曾经手滑把电脑硬盘当成SD卡写了,那叫一个酸爽。建议用balenaEtcher这种带图形界面的工具,安全很多。
3.4.3 系统初始化配置
系统第一次启动后,建议做这几件事:
- 扩展文件系统:让系统用满SD卡全部空间
- 设置时区:避免日志时间对不上
- 配置网络:WiFi或以太网
- 更新软件源:apt update && apt upgrade
- 安装常用工具:vim, htop, git, cmake等
# 扩展文件系统(树莓派)
sudo raspi-config --expand-rootfs
# 设置时区
sudo timedatectl set-timezone Asia/Shanghai
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装常用工具
sudo apt install -y vim htop git cmake build-essential
3.4.4 验证环境
最后跑个简单的测试,确认环境没问题。
# 查看系统信息
uname -a
cat /proc/cpuinfo | grep "model name"
# 测试交叉编译的程序
# 在电脑上编译,传到板子上运行
aarch64-linux-gnu-gcc -static test.c -o test_arm
scp test_arm root@192.168.1.101:/home/
ssh root@192.168.1.101 "./test_arm"
# 输出: Hello from ARM board!
我的习惯:每次拿到新板子,我都会写一个初始化脚本,把上面这些步骤自动化。下次换板子或者重装系统,跑一遍脚本就完事了。
好了,环境搭建这块就到这儿。工具链能编译了,SSH能连上了,文件能同步了,系统也跑起来了。下一章咱们开始搞真正的模型部署,到时候这些基础工作就派上用场了。