1. 嵌入式Linux开发环境搭建

做嵌入式Linux开发,第一步就是搭环境。这事儿看着简单,但我在项目里见过太多人卡在这一步——交叉编译链版本不对、TFTP传不了文件、NFS挂不上根文件系统。说白了,环境没搭好,后面全是坑。

这一章,我把这些年积累的搭建经验拆开揉碎,带你一步步搞定。

1.1 交叉编译工具链安装

交叉编译,就是在PC上编译出能在ARM板子上跑的程序。你想想看,板子那点资源,跑个gcc都费劲,更别说编译整个内核了。

1.1.1 工具链的选择

我个人习惯用Linaro提供的工具链,稳定、更新及时。当然,你也可以用芯片厂商提供的版本,比如NXP的、TI的。这里有个对比:

工具链来源 适用平台 优点 缺点
Linaro GCC ARM Cortex-A系列 通用性强,社区活跃 对特定芯片优化不够
芯片厂商SDK 特定SoC 针对性优化,BSP配套好 版本更新慢
Buildroot/Yocto 自定义系统 可定制,一键生成 学习曲线陡
我的建议: 初学者先用Linaro的arm-linux-gnueabihf版本,等熟悉了再换厂商的。

1.1.2 安装步骤

以Linaro GCC 7.5为例,我一般这样装:

# 下载工具链
wget https://releases.linaro.org/components/toolchain/binaries/7.5-2019.12/arm-linux-gnueabihf/gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz

# 解压到指定目录
sudo tar -xvf 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
注意: 我曾经遇到过PATH路径写错,结果调用了宿主机的gcc,编译出来的东西在板子上跑不起来。检查一下:which arm-linux-gnueabihf-gcc,确保指向你刚装的那个。

1.2 TFTP/NFS服务器配置

开发阶段,你不可能每次改个驱动都重新烧写整个镜像。TFTP用来传内核和设备树,NFS用来挂载根文件系统。这两个服务配好了,开发效率翻倍。

1.2.1 TFTP服务器

TFTP说白了就是个极简的文件传输协议。U-Boot里用它来加载内核镜像。

# 安装TFTP服务器
sudo apt-get install tftpd-hpa

# 配置
sudo vim /etc/default/tftpd-hpa

# 内容如下:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/tftpboot"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

# 创建目录并设置权限
sudo mkdir -p /tftpboot
sudo chmod 777 /tftpboot

# 重启服务
sudo systemctl restart tftpd-hpa
避坑指南: 防火墙记得放行UDP 69端口。我有一回折腾了半天,最后发现是防火墙把包丢了。sudo ufw allow 69/udp 搞定。

1.2.2 NFS服务器

NFS用来共享根文件系统。板子启动后,直接从主机挂载根文件系统,改代码、调试都方便。

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

# 配置导出目录
sudo vim /etc/exports

# 添加一行(假设你的根文件系统在 /home/rootfs)
/home/rootfs *(rw,sync,no_subtree_check,no_root_squash)

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

# 验证
showmount -e localhost
注意: no_root_squash 这个选项很重要。不加的话,板子上的root用户会被映射成nobody,写文件会报权限错误。我刚开始做项目时就踩过这个坑。

1.3 开发板与主机网络连接

网络连接是开发的基础。板子连不上主机,后面什么都干不了。

1.3.1 网络拓扑

我一般用两种方式:

  • 直连: 板子和主机用网线直接连。简单,但需要手动配IP。
  • 通过路由器: 都连到同一个路由器。方便,但要注意IP冲突。

下面这张图展示了典型的开发网络结构:

嵌入式Linux开发网络拓扑 开发主机 IP: 192.168.1.100 TFTP/NFS服务器 路由器/交换机 网关: 192.168.1.1 DHCP分配IP 目标开发板 IP: 192.168.1.101 U-Boot/内核 网络配置要点 1. 主机和板子必须在同一网段(如192.168.1.x) 2. 板子IP建议固定,避免DHCP每次分配不同 3. 直连时用交叉线,通过交换机用直通线 4. 测试连通性:ping 192.168.1.101

1.3.2 配置步骤

以直连方式为例,我一般这样配:

  1. 主机端: 设置静态IP
sudo ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
  1. 板子端(U-Boot中):
setenv ipaddr 192.168.1.101
setenv serverip 192.168.1.100
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
saveenv
  1. 测试连通性:
# 主机上ping板子
ping 192.168.1.101

# 板子上ping主机(U-Boot中)
ping 192.168.1.100
关键点: 如果ping不通,先检查网线指示灯。灯不亮,说明物理连接有问题。灯亮了还ping不通,多半是IP配置问题。

1.4 验证环境

环境搭好了,怎么知道对不对?我一般做三个验证:

  • 验证交叉编译链: 写个hello world,编译后放到板子上跑
  • 验证TFTP: 在U-Boot中用tftp命令下载一个文件
  • 验证NFS: 板子启动时挂载NFS根文件系统

这三个都过了,环境就算搭好了。嗯,这里要注意,别急着往下走,环境稳了,后面才顺。

我的习惯: 每次换项目、换板子,我都会重新走一遍这个流程。虽然麻烦,但能避免很多莫名其妙的问题。