2. 开发环境搭建:Ubuntu系统安装、交叉编译工具链配置、TFTP/NFS服务搭建

做嵌入式Linux开发,第一步就是把“窝”搭好。我见过不少新手,上来就急着写代码,结果编译报错、烧录失败,折腾半天发现是环境问题。说白了,环境搭不好,后面全是坑。

这一章,咱们就把RK3568的开发环境从头捋一遍。Ubuntu系统怎么装、交叉编译链怎么配、TFTP和NFS服务怎么搭,一步到位。

本章核心目标:在Windows宿主机上通过虚拟机运行Ubuntu 20.04,配置RK3568专用的交叉编译工具链,并搭建TFTP/NFS服务用于内核和根文件系统的网络加载。

2.1 Ubuntu系统安装与基础配置

我个人习惯用Ubuntu 20.04 LTS做开发。为什么?因为瑞芯微官方SDK对这个版本支持最好,踩过的坑最少。你想想看,如果选个太新的版本,库依赖可能不兼容;太老的版本,工具链又跟不上。

2.1.1 虚拟机 vs 双系统

方案 优点 缺点 我的建议
VMware/VirtualBox虚拟机 与Windows无缝切换,快照备份方便 性能有损耗,磁盘IO稍慢 新手首选,省心
WSL2 启动快,资源占用低 USB设备直通麻烦,图形化支持弱 不推荐做驱动开发
双系统 性能最好,硬件直通 切换系统麻烦,容易搞坏引导 有经验后再考虑

嗯,这里要注意:如果你用虚拟机,磁盘空间至少给80GB。RK3568的SDK解压完就20多G,编译一次内核又占不少空间。我曾经因为磁盘不够,编译到一半报错,气得不行。

2.1.2 安装后的基础配置

装完系统后,有几件事必须做:

  1. 更换软件源——用国内的镜像源,比如清华、阿里、中科大。不然下载包能等到你怀疑人生。
  2. 安装基础开发工具——gcc、g++、make、git、vim、ssh等。
  3. 配置静态IP——开发板通过网线直连电脑时,固定IP能省很多麻烦。
# 更换软件源(以清华源为例)
sudo sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
sudo apt update

# 安装基础工具
sudo apt install -y build-essential git vim openssh-server net-tools

# 配置静态IP(以Ubuntu 20.04 netplan为例)
sudo vim /etc/netplan/01-netcfg.yaml
# 内容如下:
network:
  version: 2
  ethernets:
    ens33:
      dhcp4: no
      addresses: [192.168.1.100/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 114.114.114.114]

小技巧:配置完netplan后,执行 sudo netplan apply 生效。如果连不上网,检查一下网卡名称是不是ens33,可以用 ip a 查看。

2.2 交叉编译工具链配置

交叉编译,说白了就是在PC上编译出能在ARM开发板上运行的程序。PC是x86架构,开发板是ARM架构,编译器得“跨”过去。

RK3568是ARMv8架构,64位。所以我们需要aarch64(ARM 64位)的交叉编译工具链。

2.2.1 获取工具链

瑞芯微官方SDK里自带工具链,路径在 prebuilts/gcc/linux-x86/aarch64/ 下。你也可以从Linaro官网下载。

我个人习惯用官方SDK里的,版本匹配,省心。

# 解压工具链(假设SDK在~/rk3568_sdk目录下)
cd ~/rk3568_sdk/prebuilts/gcc/linux-x86/aarch64/
ls -l
# 你会看到类似 gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz 的文件

# 解压
tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz

2.2.2 配置环境变量

解压完,需要把工具链的bin目录加到PATH里。这样你在任何目录下都能直接调用交叉编译器。

# 编辑 ~/.bashrc
vim ~/.bashrc

# 在文件末尾添加:
export PATH=$PATH:~/rk3568_sdk/prebuilts/gcc/linux-x86/aarch64/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu/bin

# 保存退出后,使配置生效
source ~/.bashrc

# 验证是否配置成功
aarch64-none-linux-gnu-gcc --version
# 如果显示版本信息,说明配置成功

避坑指南:我曾经遇到过PATH配置正确,但编译时提示“找不到命令”。后来发现是64位系统缺少32位库。执行 sudo apt install -y lib32z1 lib32ncurses5 解决。

2.2.3 测试交叉编译

写一个简单的Hello World程序,验证工具链是否正常工作。

# 创建测试文件
vim hello.c

#include <stdio.h>

int main() {
    printf("Hello, RK3568!\n");
    return 0;
}

# 交叉编译
aarch64-none-linux-gnu-gcc hello.c -o hello_arm

# 查看生成的文件信息
file hello_arm
# 输出应该包含:ELF 64-bit LSB executable, ARM aarch64

看到“ARM aarch64”字样,说明编译成功。这个程序不能在PC上直接运行,得放到开发板上跑。

2.3 TFTP/NFS服务搭建

驱动开发过程中,需要频繁地把内核镜像、设备树、根文件系统传到开发板上。用U盘拷?太慢了。用串口传?更慢。

TFTP和NFS就是干这个的。TFTP用来传内核和设备树,NFS用来挂载根文件系统。两者配合,开发效率翻倍。

2.3.1 TFTP服务搭建

TFTP(Trivial File Transfer Protocol)是个轻量级的文件传输协议。说白了,就是让开发板能从PC上下载文件。

# 安装TFTP服务
sudo apt install -y tftpd-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="-l -c -s"

# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa

# 测试:在/srv/tftp目录下放一个文件,然后在开发板上用tftp命令下载
echo "test file" | sudo tee /srv/tftp/test.txt

小技巧:TFTP默认端口是69。如果开发板连不上,检查防火墙:sudo ufw allow 69/udp。我在项目中遇到过好几次防火墙没关导致TFTP超时的情况。

2.3.2 NFS服务搭建

NFS(Network File System)能让开发板把PC上的一个目录挂载成自己的根文件系统。这样你修改PC上的文件,开发板上立即可见,不用反复烧录。

# 安装NFS服务
sudo apt install -y nfs-kernel-server

# 创建NFS共享目录(存放根文件系统)
sudo mkdir -p /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs

# 配置NFS导出
sudo vim /etc/exports

# 添加以下内容:
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)

# 参数说明:
# *          :允许所有IP访问(开发环境用,生产环境要限制)
# rw         :读写权限
# sync       :同步写入
# no_root_squash:允许root用户操作(重要!)

# 重启NFS服务
sudo systemctl restart nfs-kernel-server
sudo systemctl enable nfs-kernel-server

# 验证NFS是否正常工作
showmount -e localhost
# 应该显示:/srv/nfs/rootfs *

避坑指南:no_root_squash 这个参数一定要加。如果不加,开发板上的root用户会被映射成nobody,导致无法创建文件。我曾经因为这个参数,调试了整整一个下午。

2.3.3 开发板端配置

在U-Boot启动时,设置从TFTP下载内核,并用NFS挂载根文件系统。

# 在U-Boot命令行中设置环境变量
setenv serverip 192.168.1.100    # PC的IP
setenv ipaddr 192.168.1.101      # 开发板的IP
setenv netmask 255.255.255.0

# 从TFTP下载内核和设备树
tftp 0x02000000 Image
tftp 0x06000000 rk3568-evb.dtb

# 设置NFS根文件系统
setenv bootargs "root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs,v3,tcp rw ip=192.168.1.101:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off"

# 启动内核
booti 0x02000000 - 0x06000000

2.4 本章知识体系

下面这张图,把本章的核心内容串起来了。你一看就明白各个组件之间的关系。

开发环境搭建核心架构 宿主机(Windows + VMware) Ubuntu 20.04 虚拟机 交叉编译工具链 aarch64-none-linux-gnu-gcc TFTP服务 传输内核/设备树 NFS服务 挂载根文件系统 目标板(RK3568) U-Boot 网络启动配置 Linux内核 从TFTP加载 设备树(DTB) 从TFTP加载 根文件系统 通过NFS挂载 TFTP传输 NFS挂载 网络连接:PC与开发板通过网线直连,IP在同一网段(如192.168.1.x)

2.5 常见问题与排查

搭建环境时,总会遇到各种问题。我把最常见的几个列出来,你遇到了直接对照排查。

问题现象 可能原因 解决方法
交叉编译器找不到 PATH未配置或配置错误 检查 ~/.bashrc 中的PATH路径是否正确,执行 source ~/.bashrc
TFTP下载超时 防火墙未放行69端口 sudo ufw allow 69/udp 或关闭防火墙
NFS挂载失败 缺少 no_root_squash 参数 检查 /etc/exports 配置,重启NFS服务
开发板ping不通PC IP不在同一网段或网线问题 检查IP配置,确认网线是直连(非交叉线)
编译报错:无法找到头文件 工具链版本与内核不匹配 使用SDK自带的工具链,不要混用版本

总结一下:环境搭建是嵌入式开发的第一步,也是最容易出问题的一步。别急,按照上面的步骤一步步来。遇到问题先看日志,再看网络,最后看权限。这三板斧能解决90%的问题。