2. 开发环境搭建:交叉编译工具链安装、TFTP/NFS服务器配置、串口终端与Minicom使用

做嵌入式开发,环境搭建是绕不开的第一道坎。很多人觉得这事简单,装个编译器、配个网络服务就行了。但我在带团队时发现,80% 的调试问题都出在环境配置上——不是工具链版本不对,就是网络服务没跑起来。这一章,我把这些年踩过的坑和总结的经验都摊开来讲。

本章核心目标:搭建一套完整的 ARM 交叉开发环境,让 PC 能编译 ARM 代码、通过网络加载镜像、用串口与目标板通信。这三件事缺一不可。

2.1 交叉编译工具链安装

交叉编译,说白了就是在 x86 的 PC 上编译出能在 ARM 上跑的程序。为什么不用 ARM 板直接编译?你想想看,ARM 板的 CPU 主频通常只有几百兆,内存 256M 算大的了,编译一个 Linux 内核要几个小时。而 PC 上几分钟搞定。

2.1.1 工具链的选择

市面上 ARM 交叉编译工具链很多,我列几个常用的:

工具链名称 适用场景 我的评价
gcc-arm-linux-gnueabihf ARM 32位,Cortex-A系列 最稳定,Ubuntu 源直接装
aarch64-linux-gnu ARM 64位,Cortex-A53/A72 新项目首选,性能好
arm-none-eabi 裸机程序、Bootloader 无操作系统依赖,轻量
Linaro GCC 企业级项目 优化好,但需要手动下载

我个人习惯用 gcc-arm-linux-gnueabihf 做教学和原型验证。为什么?因为 apt 一行命令就能装,省去手动配置环境变量的麻烦。

2.1.2 安装步骤

以 Ubuntu 22.04 为例,安装命令如下:

# 安装 ARM 32位交叉编译工具链
sudo apt update
sudo apt install gcc-arm-linux-gnueabihf

# 安装 ARM 64位交叉编译工具链
sudo apt install gcc-aarch64-linux-gnu

# 验证安装
arm-linux-gnueabihf-gcc --version
aarch64-linux-gnu-gcc --version

装完后,写个简单的 C 程序测试一下:

// test.c
#include <stdio.h>

int main() {
    printf("Hello ARM World!\n");
    return 0;
}

// 编译
arm-linux-gnueabihf-gcc -o test_arm test.c

// 查看文件信息
file test_arm
// 输出: test_arm: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)

小技巧:用 file 命令查看编译产物,确认是 ARM 格式。我见过有人编译了半天,结果发现还是 x86 的——因为没装交叉编译器,系统默认用了 gcc。

2.1.3 避坑指南

我曾经在一个项目里折腾了两天,就是因为工具链版本不匹配。内核用 4.19,工具链却是 Linaro 2014 的,编译出来的内核启动就崩溃。后来换成 Linaro 7.5 才搞定。

这里有几个原则:

  • 工具链版本不要比内核老太多——差两三个大版本以内比较安全
  • glibc 版本要匹配——目标板上的 libc 版本不能比工具链的低
  • 硬浮点 vs 软浮点——ARM 板支持硬浮点就用 gnueabihf,性能差 30% 以上

2.2 TFTP/NFS 服务器配置

Bootloader 调试时,最烦的就是每次修改代码都要重新烧写 Flash。用 TFTP 和 NFS 可以解决这个问题——镜像放在 PC 上,目标板通过网络加载,改完代码重新编译,重启板子就能看到效果。

2.2.1 TFTP 服务器

TFTP 用于传输内核镜像和设备树文件。配置很简单:

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

# 配置文件 /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"        # 文件存放目录
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"

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

# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa

测试方法:在 /srv/tftp 下放一个文件,然后在开发板上用 U-Boot 的 tftp 命令下载:

# U-Boot 中执行
setenv serverip 192.168.1.100    # PC 的 IP
setenv ipaddr 192.168.1.10       # 板子的 IP
tftp 0x82000000 zImage           # 下载内核到内存 0x82000000

注意:防火墙要放行 UDP 69 端口。我遇到过好几次服务配好了,但防火墙没关,tftp 一直超时。检查方法:sudo ufw status,如果开启就 sudo ufw allow 69/udp。

2.2.2 NFS 服务器

NFS 用于挂载根文件系统。调试内核时,把根文件系统放在 PC 上,板子通过网络挂载,这样修改文件系统内容不需要重新烧写。

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

# 配置文件 /etc/exports
/nfsroot 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)

# 创建根文件系统目录
sudo mkdir -p /nfsroot
sudo chmod 777 /nfsroot

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

在 U-Boot 中设置内核启动参数:

setenv bootargs 'console=ttyAMA0,115200 root=/dev/nfs nfsroot=192.168.1.100:/nfsroot ip=192.168.1.10'
服务 用途 传输协议 典型端口
TFTP 传输内核、dtb、Bootloader UDP 69
NFS 挂载根文件系统 TCP/UDP 2049

2.3 串口终端与 Minicom 使用

串口是嵌入式开发的生命线。没有显示器、没有键盘,串口就是你和板子沟通的唯一通道。我见过有人用 USB 转串口线,结果驱动没装好,折腾半天连不上——其实大部分问题都是线序和波特率不对。

2.3.1 硬件连接

ARM 开发板通常带一个 3.3V 的 UART 接口,用 USB 转串口模块连接:

  • TXD(板子发送)→ RXD(模块接收)
  • RXD(板子接收)→ TXD(模块发送)
  • GND → GND

经验之谈:VCC 不要接!很多 USB 转串口模块会输出 5V,而 ARM 板是 3.3V 电平,接上去可能烧坏串口。我刚开始做的时候烧过一块板子,从那以后 VCC 引脚我都是悬空的。

2.3.2 Minicom 配置

Minicom 是 Linux 下最常用的串口工具。安装和配置:

# 安装
sudo apt install minicom

# 启动配置
sudo minicom -s

# 进入配置菜单后设置:
# Serial port setup → A: Serial Device = /dev/ttyUSB0
#                    E: Bps/Par/Bits = 115200 8N1
#                    F: Hardware Flow Control = No
#                    G: Software Flow Control = No

# 保存为默认配置
# Save setup as dfl

常用快捷键:

快捷键 功能
Ctrl+A → Z 帮助菜单
Ctrl+A → X 退出 Minicom
Ctrl+A → L 捕获日志到文件
Ctrl+A → W 换行开关

2.3.3 替代工具

除了 Minicom,还有几个工具我也常用:

  • screen:轻量级,screen /dev/ttyUSB0 115200 一行搞定
  • picocom:更现代,支持彩色输出
  • putty:Windows 下首选,支持串口和 SSH

我个人调试 Bootloader 时喜欢用 Minicom,因为它日志功能强。调试内核时用 screen,启动快、不占资源。

2.4 环境验证与常见问题

环境搭好了,怎么确认没问题?我一般按这个顺序验证:

  1. 串口通:板子上电,Minicom 能看到 U-Boot 启动信息
  2. 网络通:板子上 ping PC 的 IP,确认物理连接正常
  3. TFTP 通:U-Boot 中用 tftp 下载文件,看速度是否正常
  4. NFS 通:内核启动后能挂载根文件系统,进入 shell

常见问题:

  • 串口乱码 → 检查波特率,大部分板子是 115200,但也有用 57600 的
  • tftp 超时 → 检查防火墙、IP 地址、文件路径
  • NFS 挂载失败 → 检查 /etc/exports 语法,确认 no_root_squash 已设置
  • 编译报错 → 检查工具链路径,用 which arm-linux-gnueabihf-gcc 确认

2.5 本章知识体系

下面这张图把本章的核心内容串起来了:

开发环境搭建知识体系 开发环境搭建核心流程 交叉编译工具链 TFTP / NFS 服务 串口终端 / Minicom gcc-arm-linux-gnueabihf aarch64-linux-gnu arm-none-eabi TFTP: UDP 69 端口 NFS: TCP 2049 端口 传输内核 / 挂载根文件系统 Minicom 配置 screen / picocom 波特率 115200 8N1 验证流程:串口通 → 网络通 → TFTP通 → NFS通

环境搭建这件事,说难不难,说简单也不简单。关键是要理解每个工具的作用,以及它们之间的配合关系。我建议你按照上面的验证流程一步步来,每完成一步就确认一下,不要等到最后才发现问题。

嗯,这一章的内容就到这里。工具链装好了、网络服务跑起来了、串口也能用了,接下来就可以正式开始 Bootloader 的调试工作了。