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冲突。
下面这张图展示了典型的开发网络结构:
1.3.2 配置步骤
以直连方式为例,我一般这样配:
- 主机端: 设置静态IP
sudo ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
- 板子端(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
- 测试连通性:
# 主机上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根文件系统
这三个都过了,环境就算搭好了。嗯,这里要注意,别急着往下走,环境稳了,后面才顺。
我的习惯: 每次换项目、换板子,我都会重新走一遍这个流程。虽然麻烦,但能避免很多莫名其妙的问题。