2. 开发环境搭建:交叉编译工具链安装、TFTP/NFS网络引导配置、Ubuntu 22.04开发机准备
说实话,嵌入式Linux开发的第一步,往往是最磨人的。我记得刚入行那会儿,光搭环境就折腾了两天,最后发现是路径写错了。嗯,这节课咱们就把这些坑提前填上。
2.1 Ubuntu 22.04 开发机准备
我建议你直接用 Ubuntu 22.04 LTS,别问为什么不用20.04或者24.04。22.04的软件源最稳,交叉编译工具链的兼容性也最好。我在项目中试过24.04,有些老版本的库直接报错,折腾半天不值得。
硬件建议:
- CPU:4核以上,编译内核时能省一半时间
- 内存:至少8GB,16GB更舒服
- 硬盘:预留80GB以上,一个完整的SDK解压下来就20多GB
装好系统后,第一件事就是换源。你想想看,从国内连国外源下载包,速度能急死人。
# 备份原源
sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak
# 替换为清华源
sudo sed -i 's/archive.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
sudo sed -i 's/security.ubuntu.com/mirrors.tuna.tsinghua.edu.cn/g' /etc/apt/sources.list
# 更新
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 \
xinetd u-boot-tools device-tree-compiler
小技巧:装完系统后,建议把SSH服务开起来。这样你可以在Windows上用MobaXterm或者Xshell连过来,不用一直蹲在Ubuntu主机前操作。
2.2 交叉编译工具链安装
交叉编译,说白了就是在你的x86电脑上编译出ARM架构能跑的程序。我刚开始做的时候总觉得这事很玄乎,其实原理很简单——编译器本身跑在x86上,但它生成的目标代码是ARM指令集。
这里我推荐两种方式,你根据实际情况选一个。
方式一:使用Linaro官方工具链(推荐)
Linaro的工具链最干净,没有厂商定制的那堆乱七八糟的东西。我在项目里一直用这个,从来没出过兼容性问题。
# 下载ARM 32位工具链
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
# 解压到/opt目录
sudo tar -xf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz -C /opt/
# 配置环境变量
echo 'export PATH=$PATH:/opt/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf/bin' >> ~/.bashrc
source ~/.bashrc
# 验证安装
arm-linux-gnueabihf-gcc --version
方式二:使用厂商SDK
如果你用的是NXP i.MX系列或者TI AM系列,厂商会提供完整的SDK。我建议你直接用厂商的,因为里面包含了板级支持包和驱动源码。
# 以NXP i.MX8M为例
# 从NXP官网下载L5.15.52_2.1.0 SDK
chmod +x fsl-imx-xwayland-glibc-x86_64-imx-image-core-cortexa53-crypto-toolchain-5.15-kirkstone.sh
./fsl-imx-xwayland-glibc-x86_64-imx-image-core-cortexa53-crypto-toolchain-5.15-kirkstone.sh
# 安装后source环境
source /opt/fsl-imx-xwayland/5.15-kirkstone/environment-setup-cortexa53-crypto-poky-linux
注意:交叉编译工具链的版本必须与内核版本匹配。我曾经在一个项目里用了高版本的gcc编译老内核,结果编译出来的驱动模块加载时直接panic。血的教训啊。
2.3 TFTP服务器配置
TFTP这玩意儿,说白了就是个极简版的FTP。它用来在U-Boot启动时通过网络下载内核和设备树。为什么不用U盘?因为调试阶段你一天可能要烧写几十次内核,插拔U盘能把你逼疯。
配置步骤其实很简单:
# 修改TFTP配置文件
sudo vim /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 -p /tftpboot
sudo chmod 777 /tftpboot
# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa
测试一下:
# 在/tftpboot下放一个测试文件
echo "Hello TFTP" | sudo tee /tftpboot/test.txt
# 在本机测试
tftp localhost
tftp> get test.txt
tftp> quit
# 查看是否下载成功
cat test.txt
避坑指南:防火墙一定要关掉,或者开放69端口。我曾经在客户现场调试,死活连不上TFTP,查了半天发现是ufw在作怪。
2.4 NFS服务器配置
NFS的作用是让开发板通过网络挂载你的开发机目录。这样你编译好的程序直接放在共享目录里,开发板上就能跑,不用每次都烧写文件系统。
配置步骤:
# 创建NFS共享目录
sudo mkdir -p /srv/nfs/rootfs
# 修改exports文件
sudo vim /etc/exports
# 添加以下内容(根据你的网段调整)
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
# 验证
sudo exportfs -v
然后在U-Boot中设置启动参数:
# U-Boot命令行
setenv serverip 192.168.1.100 # 开发机IP
setenv ipaddr 192.168.1.200 # 开发板IP
setenv nfsroot /srv/nfs/rootfs
setenv bootargs console=ttymxc0,115200 root=/dev/nfs nfsroot=${serverip}:${nfsroot},v3,tcp ip=${ipaddr}:${serverip}:::eth0:off
saveenv
boot
关键点:
- 开发板和开发机必须在同一个网段
- no_root_squash选项必须加,否则开发板上的root用户没有写权限
- NFS版本建议用v3,v4在某些老内核上会有兼容问题
2.5 整体架构图
下面这张图展示了开发环境的核心工作流程。你仔细看,其实就三个角色:开发机、网络服务、目标板。
2.6 环境验证清单
搭完环境后,我建议你按这个清单逐项检查,少走弯路。
| 检查项 | 验证命令 | 预期结果 |
|---|---|---|
| 交叉编译器 | arm-linux-gnueabihf-gcc --version |
显示版本号,无报错 |
| TFTP服务 | systemctl status tftpd-hpa |
active (running) |
| NFS服务 | systemctl status nfs-kernel-server |
active (exited) |
| NFS共享 | showmount -e localhost |
显示共享目录列表 |
| TFTP下载 | tftp localhost -c get test.txt |
成功下载文件 |
| NFS挂载 | sudo mount -t nfs localhost:/srv/nfs/rootfs /mnt |
挂载成功,可读写 |
常见问题排查:
- TFTP连接超时:检查防火墙,确认69端口开放
- NFS挂载报错"Permission denied":检查exports文件中的no_root_squash选项
- 交叉编译报错"cannot execute binary file":确认你用的是正确的架构版本(arm vs aarch64)