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

做嵌入式Linux开发,环境搭建是绕不开的第一道坎。我见过不少新手,一上来就急着写代码,结果编译报错、烧录失败,折腾半天才发现是环境没配好。说白了,开发环境就是你的“作战基地”,基地没建好,仗就没法打。

这一章,我会带你一步步把Ubuntu虚拟机、交叉编译工具链、TFTP和NFS服务都搭起来。这些都是我这些年反复用、反复踩坑后总结出来的经验,跟着走,能省不少时间。

2.1 Ubuntu虚拟机安装

为什么选虚拟机?因为方便。你可以在Windows或macOS上直接跑Linux,不用双系统切换,也不用担心搞坏宿主机。我个人习惯用VMware Workstation,当然VirtualBox也行,看个人喜好。

2.1.1 下载与安装VMware

  • 去VMware官网下载Workstation Pro(有30天试用期)
  • 或者用VMware Workstation Player(免费版,功能够用)
  • 安装过程一路Next就行,没什么特别的

2.1.2 创建Ubuntu虚拟机

我建议用Ubuntu 20.04 LTS或22.04 LTS,这两个版本对嵌入式开发支持最好,软件源也稳定。

  1. 打开VMware,点击“创建新的虚拟机”
  2. 选择“典型(推荐)”
  3. 选择“稍后安装操作系统”
  4. 客户机操作系统选“Linux”,版本选“Ubuntu 64位”
  5. 虚拟机名称随便起,位置选个磁盘空间大的盘
  6. 磁盘大小建议给80GB以上,选“将虚拟磁盘存储为单个文件”
  7. 点击“自定义硬件”,内存给8GB以上,处理器至少2核
  8. 网络适配器选“NAT模式”(方便上网)

小提示: 我给虚拟机分配了16GB内存和4核CPU,编译内核时明显快很多。如果你宿主机内存够大,尽量多给点。

2.1.3 安装Ubuntu系统

挂载你下载好的Ubuntu ISO镜像,启动虚拟机,按提示安装就行。这里说几个关键点:

  • 分区时选“清除整个磁盘并安装Ubuntu”(虚拟机里无所谓)
  • 用户名和密码记好,后面SSH、sudo都要用
  • 安装完成后先执行sudo apt update && sudo apt upgrade -y更新系统

2.2 交叉编译工具链配置

交叉编译,说白了就是在PC上编译出能在ARM板子上运行的程序。为什么不能直接在板子上编译?因为板子性能太弱,编译个内核可能要几个小时,PC上几分钟就搞定了。

2.2.1 什么是交叉编译工具链

工具链包含编译器、链接器、库文件等。比如针对ARM架构的,常用的有:

工具链名称 目标架构 适用场景
gcc-arm-linux-gnueabihf ARM 32位 老款ARM板子(如Cortex-A8/A9)
aarch64-linux-gnu-gcc ARM 64位 新款ARM板子(如Cortex-A53/A72)
arm-none-eabi-gcc ARM裸机 无操作系统的裸机程序

我项目中用的最多的是gcc-arm-linux-gnueabihf,因为手头的i.MX6ULL和STM32MP157都是32位ARM。

2.2.2 安装交叉编译工具链

有两种方式:

方式一:apt安装(推荐)

sudo apt install gcc-arm-linux-gnueabihf

安装完成后验证:

arm-linux-gnueabihf-gcc --version

方式二:下载Linaro工具链

如果apt源里的版本太老,可以去Linaro官网下载最新版:

wget https://releases.linaro.org/components/toolchain/binaries/latest-7/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
tar -xvf gcc-linaro-*.tar.xz
sudo mv gcc-linaro-* /opt/

然后配置环境变量:

export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin

注意: 我曾经因为工具链版本不匹配,编译出来的内核在板子上跑不起来,折腾了两天才发现是gcc版本太新,内核代码不兼容。建议用Linaro 7.x或8.x版本,比较稳定。

2.2.3 测试工具链

写个简单的hello.c测试一下:

#include <stdio.h>

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

编译:

arm-linux-gnueabihf-gcc -o hello hello.c
file hello

如果输出显示ELF 32-bit LSB executable, ARM,说明工具链工作正常。

2.3 TFTP/NFS服务搭建

这两个服务是嵌入式开发中的“快递员”和“共享文件夹”。TFTP用来把编译好的内核、设备树传到板子上,NFS让板子直接挂载PC上的文件系统,方便调试。

2.3.1 TFTP服务搭建

TFTP(Trivial File Transfer Protocol)是个轻量级的文件传输协议,常用于网络启动时下载内核。

安装TFTP服务器:

sudo apt install tftpd-hpa

配置TFTP:

编辑配置文件/etc/default/tftpd-hpa:

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="-l -c -s"

创建TFTP根目录并设置权限:

sudo mkdir /tftpboot
sudo chmod 777 /tftpboot

重启服务:

sudo systemctl restart tftpd-hpa

小提示: 我把所有编译好的内核镜像、设备树文件都放在/tftpboot下,板子通过uboot的tftp命令就能直接下载,非常方便。

2.3.2 NFS服务搭建

NFS(Network File System)让板子通过网络挂载PC上的目录,这样板子就能直接运行PC上的文件系统,不用每次修改都重新烧录。

安装NFS服务器:

sudo apt install nfs-kernel-server

配置NFS导出目录:

编辑/etc/exports文件,添加:

/nfsroot *(rw,sync,no_subtree_check,no_root_squash)

创建NFS根目录:

sudo mkdir /nfsroot
sudo chmod 777 /nfsroot

重启NFS服务:

sudo systemctl restart nfs-kernel-server

注意: no_root_squash这个选项很重要。如果不加,板子上的root用户会被映射成nobody,导致很多操作权限不足。我曾经因为这个,调试驱动时发现设备节点创建不了,查了半天才发现是NFS权限问题。

2.4 环境验证

搭建完所有服务后,最好做个整体验证,确保每个环节都通。

2.4.1 验证TFTP

在/tftpboot下放个测试文件,然后在板子的uboot中执行:

tftp 0x80800000 test.txt

如果能成功下载,说明TFTP正常。

2.4.2 验证NFS

在板子的Linux系统中执行:

mount -t nfs -o nolock 192.168.1.100:/nfsroot /mnt

如果挂载成功,/mnt下能看到PC上/nfsroot目录的内容。

2.5 本章小结

环境搭建看起来步骤多,但做一遍之后后面就一劳永逸了。我个人习惯把虚拟机、工具链、TFTP、NFS的配置写成脚本,换电脑时直接跑一遍就行。

嗯,这里要注意:虚拟机的网络模式一定要和板子在同一个网段。我一般用桥接模式,让虚拟机和板子都连到路由器上,这样通信最稳定。

核心要点:

  • Ubuntu虚拟机建议20.04/22.04 LTS,内存8GB+
  • 交叉编译工具链用Linaro 7.x/8.x,注意架构匹配
  • TFTP用于传输内核和设备树,NFS用于挂载文件系统
  • 所有服务搭建完成后务必做整体验证
嵌入式Linux开发环境架构图 宿主机 Windows / macOS VMware Workstation 虚拟机管理 Ubuntu 20.04 LTS 开发环境 交叉编译工具链 arm-linux-gnueabihf-gcc TFTP服务 /tftpboot → 内核/设备树 NFS服务 /nfsroot → 文件系统 目标板(ARM开发板) i.MX6ULL / STM32MP157 tftp下载内核 mount挂载文件系统 说明:宿主机通过VMware运行Ubuntu,Ubuntu内配置交叉编译工具链、TFTP和NFS服务, 目标板通过网络从Ubuntu获取内核镜像和文件系统,实现快速开发与调试。