第2章:开发环境搭建——Ubuntu 22.04配置、交叉编译工具链与TFTP/NFS服务

做嵌入式Linux开发,环境搭建是第一步。这一步要是没走稳,后面全是坑。我见过不少新手,花了一周时间调驱动,最后发现是交叉编译工具链版本不对——这种冤枉路,咱们不走。

这一章,我会带你从零搭建一套完整的Rockchip开发环境。咱们用Ubuntu 22.04,配gcc-arm-10.3交叉编译器,再搭好TFTP和NFS服务。说白了,就是让你的PC能编译ARM代码,能让开发板通过网络加载内核和设备树,还能把根文件系统挂载到开发板上。

本章核心目标: 完成一套可复用的嵌入式开发环境,后续所有驱动实验都基于此环境运行。

2.1 Ubuntu 22.04 基础配置

我个人习惯用Ubuntu 22.04 LTS作为开发主机。为什么选这个版本?因为它的软件源稳定,对ARM交叉编译工具链的支持最友好。你如果还在用18.04,建议升级——有些新版本的GCC和工具链在旧系统上编译会报奇奇怪怪的错。

2.1.1 系统更新与基础软件包

装好系统后,第一件事就是更新软件源。别跳过这步,我遇到过有人直接装工具链,结果依赖库版本不对,折腾了两天。

sudo apt update
sudo apt upgrade -y
sudo apt install -y build-essential git vim curl wget \
    net-tools openssh-server nfs-kernel-server tftpd-hpa \
    python3 python3-pip device-tree-compiler \
    libncurses5-dev libssl-dev flex bison

这里面有几个关键包:

  • build-essential:编译必备,gcc、make都在里面
  • device-tree-compiler:编译设备树用的dtc工具
  • nfs-kernel-server 和 tftpd-hpa:后面要搭的服务
  • libncurses5-dev:内核menuconfig配置界面需要它

小技巧: 我习惯装完系统先做个快照。万一后面装坏了,直接回滚,不用重装系统。

2.1.2 配置SSH与静态IP

开发板跟PC之间频繁通信,静态IP是必须的。我一般这样配:

# 编辑网络配置文件
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]

# 应用配置
sudo netplan apply

配完以后,用 ip addr 确认IP生效。然后开启SSH服务,这样你就能从笔记本远程连到开发主机了。

sudo systemctl enable ssh
sudo systemctl start ssh

2.2 交叉编译工具链安装(gcc-arm-10.3)

交叉编译,说白了就是在x86的PC上编译出ARM架构能跑的代码。你想想看,开发板那点算力,编译个内核得等到天荒地老。所以咱们用PC来干这活。

2.2.1 下载与解压

Rockchip官方推荐用gcc-arm-10.3-2021.07版本。我试过好几个版本,这个对RK3568/RK3588的支持最稳。

# 下载(如果网速慢,可以用国内镜像)
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz

# 解压到 /opt 目录
sudo tar -xvf gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu.tar.xz -C /opt/

# 重命名(方便记忆)
sudo mv /opt/gcc-arm-10.3-2021.07-x86_64-aarch64-none-linux-gnu /opt/gcc-arm-10.3

2.2.2 配置环境变量

解压完不算完,你得让系统能找到这些工具。我习惯把环境变量写到 ~/.bashrc 里:

vim ~/.bashrc

# 在文件末尾添加
export PATH=$PATH:/opt/gcc-arm-10.3/bin
export CROSS_COMPILE=aarch64-none-linux-gnu-
export ARCH=arm64

# 使配置生效
source ~/.bashrc

验证一下是否装好了:

aarch64-none-linux-gnu-gcc --version

# 输出应该类似:
# aarch64-none-linux-gnu-gcc (GNU Toolchain for the A-profile architecture 10.3-2021.07) 10.3.1 20210621
# Copyright (C) 2020 Free Software Foundation, Inc.

注意: 如果你用的是RK3288或RK3399这类32位兼容的芯片,编译32位代码时需要用 arm-none-linux-gnueabihf- 前缀。别搞混了,我见过有人用64位工具链编译32位内核,链接阶段报一堆错。

2.2.3 测试编译

写个简单的测试程序,确认工具链能正常工作:

# 创建测试文件
cat > hello.c << EOF
#include <stdio.h>

int main(void)
{
    printf("Rockchip Embedded Linux!\n");
    return 0;
}
EOF

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

# 查看生成的文件类型
file hello

# 输出:hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV)

看到 ARM aarch64 就对了。这个程序在x86的PC上跑不了,得放到开发板上执行。

2.3 TFTP服务搭建

TFTP这玩意儿,说白了就是一个极简的文件传输协议。开发板在uboot阶段,网卡驱动已经初始化了,但文件系统还没挂载。这时候想从PC上拿内核镜像、设备树文件,就得靠TFTP。

2.3.1 安装与配置

# 安装tftp服务端
sudo apt install tftpd-hpa -y

# 创建tftp根目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp

# 修改配置文件
sudo vim /etc/default/tftpd-hpa

配置文件内容如下:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"

注意那个 --create 选项,加上它之后,开发板才能通过TFTP往PC上传文件。调试的时候很有用。

2.3.2 启动与测试

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

# 放一个测试文件
echo "TFTP Test" > /srv/tftp/test.txt

# 本地测试(安装tftp客户端)
sudo apt install tftp -y
tftp localhost
tftp> get test.txt
tftp> quit

# 查看是否下载成功
cat test.txt

避坑指南: 我曾经在RK3568的板子上,uboot死活从TFTP下载不了内核。查了半天,发现是防火墙把69端口封了。执行 sudo ufw allow 69/udp 就解决了。

2.4 NFS服务搭建

NFS的作用跟TFTP正好互补。TFTP用于uboot阶段传小文件,NFS用于内核启动后挂载根文件系统。开发阶段,你不需要每次修改都烧写根文件系统到开发板的Flash里,直接通过网络挂载PC上的目录就行了。

2.4.1 安装与配置

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

# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs

# 编辑导出配置文件
sudo vim /etc/exports

在文件末尾添加:

/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

参数说明:

参数 含义
rw 读写权限
sync 同步写入,保证数据一致性
no_subtree_check 关闭子树检查,提升性能
no_root_squash 允许开发板以root权限访问,这个很重要

2.4.2 启动与挂载测试

# 导出共享目录
sudo exportfs -a

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

# 本地挂载测试
sudo mount -t nfs 192.168.1.100:/srv/nfs/rootfs /mnt

# 写入测试文件
echo "NFS Test" | sudo tee /mnt/nfs_test.txt

# 卸载
sudo umount /mnt

注意: 开发板通过NFS挂载根文件系统时,uboot的bootargs里要传 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs。IP地址要跟你PC的静态IP一致。我刚开始做的时候,IP写错了,板子启动到一半就卡住了。

2.5 本章知识体系总览

下面这张图,把整个开发环境的结构画清楚了。你可以对照着检查自己配到哪一步了。

Rockchip 嵌入式开发环境架构图 开发主机 (Ubuntu 22.04) 交叉编译工具链 Linux内核源码 TFTP服务 NFS服务 目标开发板 (Rockchip) U-Boot引导 Linux内核 设备树(DTB) 根文件系统 TFTP: 内核/DTB NFS: 根文件系统 串口(115200 8N1): 调试控制台 开发调试流程 ① PC端编译内核 → 生成Image + DTB ② 将Image/DTB放入 /srv/tftp 目录 ③ 开发板uboot通过TFTP下载内核启动 ④ 内核启动后通过NFS挂载根文件系统 ⑤ 串口终端查看日志,调试驱动

2.6 环境验证清单

配完环境别急着往下走。我列了个检查清单,每项都过一遍,确保后面不出幺蛾子。

检查项 验证方法 预期结果
交叉编译器 aarch64-none-linux-gnu-gcc --version 显示10.3.1版本信息
TFTP服务 systemctl status tftpd-hpa active (running)
TFTP传输 本地tftp get测试文件 成功下载文件
NFS服务 systemctl status nfs-kernel-server active (exited)
NFS挂载 本地mount测试 成功挂载并读写文件
SSH服务 ssh localhost 成功登录
静态IP ip addr IP为配置的静态地址

我的经验: 环境搭建这一步,宁可多花一小时验证,也别省。我见过有人TFTP配错了路径,uboot下载内核时一直报"File not found",查了三天才发现是目录权限问题。嗯,这种坑踩过一次就记住了。