2. 开发环境搭建:交叉编译工具链安装、SDK源码获取与编译、TFTP/NFS网络调试环境配置
做嵌入式Linux驱动开发,第一步就是把开发环境搭好。这一步要是没弄利索,后面调试起来会非常痛苦。我见过不少新手,花了一周时间在环境问题上打转,最后发现只是工具链版本不对。
这一章,我会把Rockchip平台开发环境的搭建过程拆开揉碎了讲。你跟着做就行,不用自己瞎琢磨。
2.1 交叉编译工具链安装
交叉编译,说白了就是在你的x86电脑上编译出能在ARM芯片上跑的程序。Rockchip官方推荐用Linaro提供的GCC工具链,我个人也一直用这个,稳定。
2.1.1 工具链版本选择
不同的Rockchip芯片,对应的工具链版本不太一样。我整理了一张表,你对着选就行。
| 芯片型号 | 架构 | 推荐工具链 | GCC版本 |
|---|---|---|---|
| RK3566/RK3568 | ARMv8-A (64-bit) | aarch64-linux-gnu | 10.3-2021.07 |
| RK3399 | ARMv8-A (64-bit) | aarch64-linux-gnu | 9.2-2019.12 |
| RK3288 | ARMv7-A (32-bit) | arm-linux-gnueabihf | 8.3-2019.03 |
| RV1126/RV1109 | ARMv7-A (32-bit) | arm-linux-gnueabihf | 10.3-2021.07 |
2.1.2 安装步骤
以RK3568为例,我习惯把工具链放在 /opt/toolchains/ 目录下。
# 下载工具链
wget https://releases.linaro.org/components/toolchain/binaries/10.3-2021.07/aarch64-linux-gnu/gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu.tar.xz
# 解压到指定目录
sudo tar -xvf gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu.tar.xz -C /opt/toolchains/
# 添加环境变量
echo 'export PATH=$PATH:/opt/toolchains/gcc-linaro-10.3.1-2021.07-x86_64_aarch64-linux-gnu/bin' >> ~/.bashrc
source ~/.bashrc
# 验证安装
aarch64-linux-gnu-gcc --version
~/.bashrc 里加上 export ARCH=arm64 和 export CROSS_COMPILE=aarch64-linux-gnu-。这样每次编译内核时就不用重复敲这两个参数了。
2.2 SDK源码获取与编译
Rockchip的SDK结构比较复杂,里面包含了U-Boot、Linux内核、Buildroot/ Yocto构建系统。我第一次接触时也懵了,后来摸清了门道就好办了。
2.2.1 获取SDK
Rockchip官方SDK托管在GitHub上,但完整源码需要从他们的repo仓库同步。我建议你用 repo 工具来管理,方便后续更新。
# 安装repo工具
sudo apt-get install repo
# 初始化SDK(以RK3568为例)
mkdir rk3568_sdk
cd rk3568_sdk
repo init -u https://github.com/rockchip-linux/manifests -b master -m rk3568_linux_release.xml
# 同步源码
repo sync -j4
同步时间取决于网络状况,我这边大概需要30-60分钟。你可以趁这个时间泡杯咖啡。
2.2.2 SDK目录结构
同步完成后,你会看到这样的目录结构:
rk3568_sdk/
├── u-boot/ # U-Boot引导程序
├── kernel/ # Linux内核源码
├── buildroot/ # Buildroot构建系统
├── device/ # 设备相关配置
├── external/ # 第三方库
├── prebuilts/ # 预编译工具
└── rockdev/ # 打包脚本和镜像
核心知识点: 驱动开发主要关注 kernel/ 目录下的 drivers/ 子目录。你的驱动代码就放在这里。U-Boot和Buildroot一般不需要频繁修改。
2.2.3 编译内核
编译内核是驱动开发的基本功。我习惯先编译一次完整的内核,确保环境没问题。
# 进入内核目录
cd kernel
# 配置内核(使用Rockchip默认配置)
make ARCH=arm64 rockchip_linux_defconfig
# 编译内核
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc)
# 编译设备树
make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- dtbs
编译完成后,你会得到 arch/arm64/boot/Image 和 arch/arm64/boot/dts/rockchip/ 下的设备树文件。
scripts/sign-file.c:25: fatal error: openssl/opensslv.h: No such file or directory 错误,安装 libssl-dev 即可解决。我刚开始时被这个坑过,折腾了半天。
2.3 TFTP/NFS网络调试环境配置
驱动开发最烦的就是反复烧写镜像。用TFTP和NFS可以省去这个步骤,直接在网络加载内核和文件系统。我个人觉得这是嵌入式开发效率提升最大的一个技巧。
2.3.1 网络调试架构
先看一张整体架构图,理解数据是怎么流动的。
2.3.2 TFTP服务器配置
TFTP用来传输内核镜像和设备树。配置很简单,几步搞定。
# 安装TFTP服务器
sudo apt-get install tftp-hpa
# 创建TFTP根目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 配置TFTP服务
sudo vim /etc/default/tftpd-hpa
配置文件内容如下:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure -c -s"
# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa
然后把编译好的内核镜像和设备树复制到TFTP目录:
sudo cp arch/arm64/boot/Image /srv/tftp/
sudo cp arch/arm64/boot/dts/rockchip/rk3568-evb1-v10.dtb /srv/tftp/
2.3.3 NFS服务器配置
NFS用来挂载根文件系统。我一般用Buildroot生成的根文件系统,你也可以用Ubuntu base。
# 安装NFS服务器
sudo apt-get install nfs-kernel-server
# 创建NFS共享目录
sudo mkdir -p /srv/nfs/rootfs
# 解压根文件系统(以Buildroot为例)
sudo tar -xvf output/images/rootfs.tar -C /srv/nfs/rootfs/
# 配置NFS导出
sudo vim /etc/exports
在 /etc/exports 中添加:
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
sudo exportfs -a
no_root_squash 这个选项很重要。不加的话,目标板上的root用户会被映射成nobody,导致很多操作权限不足。我刚开始调试时,就因为这个问题折腾了一下午。
2.3.4 U-Boot启动参数设置
最后一步,配置U-Boot从TFTP和NFS启动。在目标板的U-Boot命令行中执行:
setenv serverip 192.168.1.100 # 开发主机IP
setenv ipaddr 192.168.1.10 # 目标板IP
setenv netmask 255.255.255.0
setenv gatewayip 192.168.1.1
setenv bootargs 'console=ttyS2,1500000 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs rw ip=192.168.1.10:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'
setenv bootcmd 'tftp 0x00a00000 Image; tftp 0x00f00000 rk3568-evb1-v10.dtb; booti 0x00a00000 - 0x00f00000'
saveenv
boot
执行 boot 后,你会看到内核通过TFTP加载,然后挂载NFS根文件系统。整个过程大概10-20秒,比烧写eMMC快多了。
效率提升: 用上TFTP/NFS后,每次修改驱动只需要重新编译内核模块,然后复制到NFS目录,重启目标板即可。整个过程不超过1分钟。相比之前每次烧写要5-10分钟,效率提升了5倍以上。
2.4 环境验证
环境搭好了,怎么确认没问题?我一般做三个检查:
- 工具链验证: 编译一个简单的hello world程序,用
file命令确认是ARM架构。 - 内核编译验证: 确保
make能完整编译通过,没有报错。 - 网络启动验证: 目标板能通过TFTP加载内核,NFS挂载根文件系统后能正常进入shell。
这三个检查都过了,你的开发环境就算搭建完成了。后面写驱动、调试,都会顺畅很多。