第二章 开发环境搭建:工欲善其事,必先利其器
做嵌入式开发,尤其是RK平台这种级别的SoC,环境搭建是第一道坎。很多人觉得不就是装个编译器、下个代码嘛,结果一上手就卡在莫名其妙的地方。我见过太多人花了两三天才把网络环境调通,最后发现是网线没插好——嗯,真事。
这一章,我把环境搭建的流程拆成三块:交叉编译工具链、源码获取、网络调试环境。每块都有我踩过的坑,你跟着走一遍,基本不会出大问题。
2.1 交叉编译工具链配置
交叉编译,说白了就是在你的x86电脑上编译出ARM能跑的二进制。RK平台官方推荐用gcc-arm-8.3-2019.03,但我个人习惯用Linaro的版本,更新快,社区支持好。
核心原则:工具链版本必须与内核版本匹配。RK3288用4.4内核时,gcc 6.x就够了;RK3588用5.10内核,建议gcc 8.x以上。
2.1.1 下载与安装
# 下载Linaro gcc 7.5(适用于RK3399/RK3288)
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
# 解压到/opt目录
sudo tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 配置环境变量(建议写入~/.bashrc)
export PATH=/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin:$PATH
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabihf-
小技巧:我习惯在项目根目录下放一个 setenv.sh 脚本,每次开新终端直接 source setenv.sh,省得反复写环境变量。
2.1.2 验证工具链
# 检查版本
arm-linux-gnueabihf-gcc --version
# 编译一个测试程序
echo 'int main(){return 0;}' > test.c
arm-linux-gnueabihf-gcc -o test test.c
file test
# 输出应为:ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)
如果 file 命令显示的是x86格式,说明你还在用本地gcc。我曾经有个同事搞了一整天,最后发现 CROSS_COMPILE 变量名拼错了——少了个字母。
注意:RK平台有32位和64位之分。RK3288是ARMv7,用 arm-linux-gnueabihf-;RK3399/RK3588是ARMv8,用 aarch64-linux-gnu-。别搞混了,否则编译出来的内核起不来。
2.2 Uboot与内核源码获取
源码获取这件事,看似简单,但版本选错了后面全是坑。RK官方在GitHub上有完整的仓库,但分支多、tag乱,新手容易迷失。
2.2.1 官方仓库地址
| 组件 | GitHub仓库 | 推荐分支 |
|---|---|---|
| U-Boot | rockchip-linux/u-boot | next-dev(开发板)或 2017.09(稳定) |
| Kernel | rockchip-linux/kernel | rk-5.10(RK3588)或 rk-4.4(RK3288) |
| RKBin | rockchip-linux/rkbin | master |
2.2.2 克隆与切换分支
# 克隆内核(以RK3588为例)
git clone https://github.com/rockchip-linux/kernel.git -b rk-5.10 --depth=1
# 克隆U-Boot
git clone https://github.com/rockchip-linux/u-boot.git -b next-dev --depth=1
# 克隆rkbin(包含DDR初始化、ATF等二进制)
git clone https://github.com/rockchip-linux/rkbin.git --depth=1
--depth=1 只拉最新代码,省时间省硬盘。我刚开始做RK3588时没加这个参数,拉了3个多G,结果发现大部分历史commit根本用不上。
我的习惯:在 /work/rk3588/ 下建三个目录:src/(放源码)、out/(放编译产物)、tools/(放烧录工具和脚本)。这样项目结构清晰,不会乱。
2.3 TFTP/NFS网络调试环境搭建
网络调试是嵌入式开发的加速器。没有它,每次改代码都要插拔SD卡或USB线,效率极低。TFTP用来传内核和设备树,NFS用来挂载根文件系统——这两个配合好,开发体验直接起飞。
2.3.1 整体架构
先看一张图,理清数据流:
2.3.2 搭建TFTP服务器
# 安装tftp-hpa
sudo apt-get install tftp-hpa tftpd-hpa
# 创建TFTP根目录
sudo mkdir -p /tftpboot
sudo chmod 777 /tftpboot
# 修改配置文件 /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"
# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa
验证方法:在 /tftpboot 下放一个测试文件,然后在另一台机器上执行 tftp 192.168.1.100 -c get test.txt。能下载就说明通了。
2.3.3 搭建NFS服务器
# 安装nfs-kernel-server
sudo apt-get install nfs-kernel-server
# 创建NFS共享目录(存放根文件系统)
sudo mkdir -p /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs
# 解压根文件系统到共享目录
sudo tar -xvf buildroot-rootfs.tar.gz -C /srv/nfs/rootfs/
# 编辑 /etc/exports,添加共享配置
/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
sudo exportfs -av
关键点:no_root_squash 必须加。不加的话,目标板上的root用户会被映射成nobody,很多操作会报权限错误。我曾经因为这个排查了整整一个下午,最后发现是少了个参数。
2.3.4 U-Boot端网络启动配置
在U-Boot命令行中设置环境变量:
# 设置IP地址
setenv ipaddr 192.168.1.101
setenv serverip 192.168.1.100
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
# 设置TFTP启动参数
setenv bootcmd 'tftp 0x02000000 zImage; tftp 0x06000000 rk3588-evb1.dtb; bootz 0x02000000 - 0x06000000'
# 设置NFS根文件系统参数
setenv bootargs 'console=ttyS2,1500000 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs,v3,tcp ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
# 保存环境变量
saveenv
# 启动
boot
这里有个坑:bootz 命令只支持ARM32内核。如果你用的是RK3588这种64位平台,得用 booti。我刚开始移植时没注意这个,内核死活起不来,打印停在"Starting kernel ..."就不动了。
2.3.5 常见故障排查
| 现象 | 可能原因 | 解决方法 |
|---|---|---|
| TFTP超时 | 防火墙阻挡或网线问题 | sudo ufw disable 或检查网线 |
| NFS挂载失败 | 缺少 no_root_squash |
检查 /etc/exports 配置 |
| 内核启动后卡住 | DTB与内核版本不匹配 | 确保DTB来自同一份内核源码 |
| 网络不通 | PHY驱动未初始化 | U-Boot中执行 mdio list 检查PHY |
我的经验:网络调试环境第一次搭好之后,把U-Boot的环境变量导出保存到文件。下次换板子或重刷固件时,直接 source 进去,省得重新敲一遍。我曾经有个项目换了三块不同版本的RK3588板子,每次都要重新配IP,后来学乖了,写了个脚本一键配置。
2.4 本章小结
环境搭建这件事,说难不难,说简单也不简单。工具链版本选对、源码分支选对、网络服务配好,后面30章的实战才能跑得起来。如果你按照上面的步骤走一遍,应该半小时内就能搭好。