2、嵌入式Linux开发环境搭建:交叉编译工具链、TFTP/NFS与调试工具
大家好,我是你们的讲师。今天我们来聊聊嵌入式Linux开发环境的搭建。说实话,很多初学者觉得这步就是装个软件、配个路径,没什么技术含量。但我得说,环境搭得好,后面少烦恼。我在项目里见过太多因为工具链版本不对、网络文件系统没配好,白白浪费一两天的情况。
这一章,我们聚焦三个核心:交叉编译工具链(GCC for ARM64)、TFTP/NFS网络文件系统,以及串口终端与调试工具。嗯,一个一个来。
2.1 交叉编译工具链:GCC for ARM64
先问个问题:为什么需要交叉编译?
你想想看,你的开发机是x86架构,而自动驾驶平台用的是ARM64(比如NVIDIA Orin、NXP S32G)。x86上编译出来的程序,ARM64跑不了。反过来,ARM64上直接编译?算力有限,而且开发效率太低。所以,我们得在x86上编译出ARM64能跑的程序——这就是交叉编译。
2.1.1 工具链的选择
我个人习惯用Linaro提供的GCC工具链,稳定且社区活跃。当然,你也可以用芯片厂商提供的定制版,比如NVIDIA的JetPack里就带了。
常用的ARM64交叉编译工具链有:
- aarch64-linux-gnu-gcc:标准GNU工具链,适合通用Linux系统
- aarch64-linux-gnu-g++:C++编译器
- aarch64-linux-gnu-ld:链接器
- aarch64-linux-gnu-objdump:反汇编工具
重要提示:工具链版本必须与目标系统的内核版本、glibc版本匹配。否则,编译出来的程序可能无法运行,或者运行时出现奇怪的段错误。
2.1.2 安装与配置
安装其实很简单。以Ubuntu 20.04为例:
# 安装ARM64交叉编译工具链
sudo apt-get install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
# 验证安装
aarch64-linux-gnu-gcc --version
安装完成后,写个简单的测试程序:
// hello.c
#include <stdio.h>
int main() {
printf("Hello from ARM64!\n");
return 0;
}
# 编译
aarch64-linux-gnu-gcc -o hello hello.c
# 查看文件信息
file hello
# 输出:hello: ELF 64-bit LSB executable, ARM aarch64, ...
看到“ARM aarch64”就对了。我曾经有一次编译完忘了检查,直接拷到板子上跑,结果报“Exec format error”。嗯,当时排查了半天才发现是工具链没配对。
2.1.3 避坑指南:静态链接 vs 动态链接
这里有个坑,我踩过。如果你的目标系统上缺少某些动态库,编译时最好用静态链接:
aarch64-linux-gnu-gcc -static -o hello hello.c
静态链接生成的文件会大一些,但省去了库依赖的麻烦。特别是自动驾驶平台,有时候为了精简系统,很多库都没装全。
我的建议:开发阶段用动态链接,方便调试;发布阶段用静态链接,确保兼容性。
2.2 TFTP/NFS网络文件系统搭建
接下来是网络文件系统。说白了,就是让开发板和主机之间共享文件。为什么要搞这个?
你想想看,每次修改代码都要重新烧写镜像、重启板子,多浪费时间。用NFS,代码直接放在主机上,板子通过网络挂载,改完就能跑。TFTP则常用于网络引导内核。
2.2.1 TFTP服务器搭建
TFTP(Trivial File Transfer Protocol)很简单,就是用来传文件的。我一般用它来下载内核镜像和设备树。
# 安装TFTP服务器
sudo apt-get install tftpd-hpa
# 配置TFTP目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 编辑配置文件 /etc/default/tftpd-hpa
# 内容如下:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"
# 重启服务
sudo systemctl restart tftpd-hpa
测试一下:
# 在主机上创建一个测试文件
echo "Hello TFTP" > /srv/tftp/test.txt
# 在板子上用tftp客户端下载
tftp 192.168.1.100 -c get test.txt
注意:TFTP没有认证机制,所以不要暴露在公网上。我一般只在开发用的局域网里用。
2.2.2 NFS服务器搭建
NFS(Network File System)就强大得多了。它允许板子直接挂载主机上的目录,就像访问本地文件一样。
# 安装NFS服务器
sudo apt-get install nfs-kernel-server
# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
# 编辑 /etc/exports,添加:
/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
# 重启NFS服务
sudo systemctl restart nfs-kernel-server
在板子上挂载:
# 在板子上执行
mount -t nfs -o nolock 192.168.1.100:/srv/nfs/rootfs /mnt
挂载成功后,你在主机上修改文件,板子上立刻就能看到。这对于调试应用程序和内核模块来说,简直是神器。
关键参数说明:
| 参数 | 含义 |
|---|---|
| rw | 读写权限 |
| sync | 同步写入,保证数据一致性 |
| no_subtree_check | 禁用子树检查,提升性能 |
| no_root_squash | 允许root用户保留权限,否则板子上root会被映射成nobody |
我记得有一次,板子挂载NFS后一直报“Permission denied”。查了半天,发现是no_root_squash没加。板子上的root用户被映射成了普通用户,自然没权限写文件。
2.3 串口终端与调试工具
最后,我们聊聊串口调试。自动驾驶平台通常没有显示器、键盘,串口就是你和板子沟通的唯一通道。
2.3.1 Minicom
Minicom是Linux下最经典的串口工具。我个人习惯用它,轻量、稳定。
# 安装
sudo apt-get install minicom
# 配置
sudo minicom -s
进入配置界面后,设置:
- 串口设备:/dev/ttyUSB0(根据实际情况调整)
- 波特率:115200
- 数据位:8
- 停止位:1
- 奇偶校验:无
- 硬件流控:关闭
保存配置为默认,以后直接运行minicom就行。
小技巧:如果板子没反应,先检查串口线是不是交叉线(Null Modem)。我吃过这个亏,焊了根直连线,折腾了一下午。
2.3.2 Putty
如果你在Windows上开发,Putty是首选。虽然它是个图形工具,但配置思路和Minicom一样。
关键设置:
- Connection type: Serial
- Serial line: COM3(根据设备管理器查看)
- Speed: 115200
- Flow control: None
配置好后,点击Open就能连上。Putty还有个好处,可以保存session,下次直接双击打开。
2.3.3 调试技巧
串口调试时,我常用这几个命令:
# 查看内核启动日志
dmesg | tail
# 查看系统信息
cat /proc/cpuinfo
cat /proc/meminfo
# 查看网络状态
ifconfig
ping 192.168.1.100
如果板子启动时串口没输出,先检查:
- 串口线是否接对(TX接RX,RX接TX)
- 波特率是否匹配(常见的是115200或9600)
- 板子是否已经上电
- U-Boot的串口参数是否配置正确
重要提醒:串口调试时,千万不要带电插拔串口线。我烧过一块板子的串口芯片,就是因为手贱。先断电,再接线,这是铁律。
小结
好了,这一章的内容就到这里。我们搭建了交叉编译环境,配好了TFTP和NFS,还学会了用串口和板子对话。这些工具看起来琐碎,但它们是嵌入式Linux开发的基石。
下一章,我们会把这些工具用起来,真正开始移植U-Boot和内核。到时候你会发现,今天搭的环境,就是明天的效率。
有什么问题,欢迎在群里讨论。我们下章见。