2. 开发环境搭建:交叉编译工具链安装、SDK获取与编译、TFTP/NFS网络文件系统配置
说实话,很多做AI部署的同学,模型跑不起来的第一反应是去调算法。但我个人的经验是——八成的问题出在环境上。工具链版本不对、SDK编译选项没开、文件系统挂载不上,这些基础问题没搞定,后面调NPU驱动就是空中楼阁。
这一章,咱们就把地基打牢。我会带着你一步步把交叉编译工具链、SDK、TFTP/NFS这三样东西配好。嗯,都是我在项目里踩过坑之后总结出来的“最优路径”。
2.1 交叉编译工具链安装
交叉编译,说白了就是在X86的PC上编译出ARM架构能跑的二进制文件。你想想看,目标板那点算力,编译个Linux内核得等到天荒地老。所以这事儿必须在PC上干。
工具链的选择,我建议直接跟芯片原厂走。Rockchip用gcc-arm-10.3-2021.07,全志用gcc-linaro-7.5.0,NXP用gcc-arm-none-eabi。别自己去Linaro官网随便下,版本不对会出一些很诡异的链接错误。
安装步骤其实就三步:
- 下载解压:拿到原厂提供的
gcc-arm-xxx.tar.xz,解压到/opt/目录 - 配置环境变量:把工具链的bin目录加到
PATH里 - 验证安装:跑一下
aarch64-linux-gnu-gcc -v,看到版本号就对了
~/.bashrc 里加一行 export PATH=/opt/gcc-arm-10.3-2021.07/bin:$PATH,然后 source ~/.bashrc。这样每次开终端都能直接用,不用重复export。
这里有个坑——64位和32位工具链别搞混。我见过有人用aarch64的工具链去编译32位的ARM程序,链接阶段报一堆“relocation truncated to fit”。嗯,检查一下你目标板的内核是32位还是64位,选对应的工具链。
| 目标架构 | 工具链前缀 | 常见芯片 |
|---|---|---|
| ARMv7 (32位) | arm-linux-gnueabihf- | 全志V3s、NXP i.MX6ULL |
| ARMv8 (64位) | aarch64-linux-gnu- | Rockchip RK3588、瑞芯微RV1126 |
| RISC-V (64位) | riscv64-linux-gnu- | 全志D1、算能SG2042 |
2.2 SDK获取与编译
拿到SDK之后,第一件事不是急着编译,而是检查README。真的,我每次接手新项目都会先看一遍SDK根目录下的README或者Wiki链接。里面通常会写明依赖的软件包版本、编译步骤、已知问题。
SDK的目录结构,不同厂家大同小异。以Rockchip的Linux SDK为例:
sdk/
├── u-boot/ # 引导程序
├── kernel/ # Linux内核 + 设备树
├── device/ # 板级配置
├── external/ # 第三方库(NPU驱动、多媒体库等)
├── buildroot/ # 根文件系统构建
└── docs/ # 文档
编译流程,我一般按这个顺序来:
- 配置编译环境:
source build/envsetup.sh,选择对应的板型 - 编译U-Boot:
./build.sh uboot,生成idbloader.img和uboot.img - 编译Kernel:
./build.sh kernel,生成boot.img(内含内核+设备树) - 编译根文件系统:
./build.sh rootfs,生成rootfs.img - 打包固件:
./build.sh firmware,生成完整烧写镜像
./build.sh 会自动下载一些依赖包。确保你的PC能访问外网,或者提前配置好本地源。我曾经在客户现场,网络受限,SDK编译到一半卡在下载阶段,折腾了半天才搞定离线包。
编译过程中如果报错,别慌。90%的错误都是缺少依赖包。常见的依赖有:libncurses5-dev、flex、bison、openssl、device-tree-compiler。用apt-get install装一下就好。
2.3 TFTP/NFS网络文件系统配置
为什么要配TFTP和NFS?因为开发阶段你不可能每次改个驱动就重新烧写一次固件。TFTP用来快速加载内核和设备树,NFS用来共享根文件系统。这样你改完代码,编译完,重启目标板就能看到效果。
2.3.1 TFTP服务器配置
TFTP说白了就是一个极简的文件传输协议,只支持从服务器往客户端传文件。配置步骤:
- 安装TFTP服务:
sudo apt-get install tftpd-hpa - 创建TFTP根目录:
sudo mkdir -p /srv/tftp,并设置权限sudo chmod 777 /srv/tftp - 修改配置文件:编辑
/etc/default/tftpd-hpa,指定根目录为/srv/tftp - 重启服务:
sudo systemctl restart tftpd-hpa
验证方法:在/srv/tftp下放一个测试文件,然后在目标板的U-Boot里执行tftp 0x02000000 test.txt,能下载成功就说明配好了。
sudo ufw allow 69/udp 就能解决。
2.3.2 NFS服务器配置
NFS比TFTP复杂一点,但功能更强。它允许目标板把PC上的一个目录挂载为自己的根文件系统。配置步骤:
- 安装NFS服务:
sudo apt-get install nfs-kernel-server - 创建共享目录:
sudo mkdir -p /srv/nfs/rootfs - 导出根文件系统:把编译好的
rootfs目录内容复制到/srv/nfs/rootfs - 修改exports文件:编辑
/etc/exports,添加一行/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash) - 重启NFS服务:
sudo systemctl restart nfs-kernel-server
目标板启动时,在U-Boot里设置内核启动参数:
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs rw ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
这里192.168.1.100是PC的IP,192.168.1.101是目标板的IP。记得把网线插好,IP别配错。
| 参数 | 说明 | 示例值 |
|---|---|---|
| root=/dev/nfs | 指定根文件系统来自NFS | 固定写法 |
| nfsroot | NFS服务器IP和共享路径 | 192.168.1.100:/srv/nfs/rootfs |
| ip | 目标板IP:服务器IP:网关:掩码 | 192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0 |
no_root_squash 这个选项一定要加。不加的话,目标板上的root用户会被映射成nobody,导致很多系统命令无法执行。我刚开始搞NFS时没加这个,结果目标板上连 ls 都报权限错误,排查了半天才发现是这个问题。
2.4 环境验证:跑通第一个Hello World
环境搭好了,咱们验证一下。写一个简单的C程序:
#include <stdio.h>
int main() {
printf("Hello Edge AI!\n");
return 0;
}
用交叉编译器编译:
aarch64-linux-gnu-gcc -o hello hello.c
把编译好的hello文件放到NFS共享目录里,然后在目标板上执行:
./hello
看到Hello Edge AI!输出,就说明你的开发环境完全打通了。从PC编译到目标板运行,整个链路都是通的。