3. 开发环境搭建:交叉编译工具链安装、TFTP与NFS服务器配置、串口终端工具设置
做嵌入式开发,第一件事就是把开发环境搭好。这步要是没弄利索,后面调试起来会非常痛苦。我见过不少新手,花了一周时间在环境问题上打转,最后发现只是工具链版本不对。
这一章,我把环境搭建拆成三块:交叉编译工具链、TFTP/NFS服务器、串口终端工具。每块我都会给出具体操作步骤,还有我踩过的坑。
核心原则:开发环境要「一次配好,到处可用」。建议用虚拟机或独立开发机,别在主力工作机上乱装。
3.1 交叉编译工具链安装
交叉编译,说白了就是在PC上编译出能在ARM板子上跑的程序。你想想看,板子上的CPU跑不动GCC,所以得靠PC代劳。
3.1.1 工具链的选择
我个人习惯用Linaro GCC,它针对ARM架构做了优化,稳定性和性能都不错。当然,你也可以用芯片厂商提供的工具链,比如NXP的、TI的。但要注意版本匹配。
| 工具链类型 | 适用场景 | 前缀示例 |
|---|---|---|
| arm-linux-gnueabihf | ARM Cortex-A系列,硬件浮点 | arm-linux-gnueabihf-gcc |
| aarch64-linux-gnu | ARMv8 64位平台 | aarch64-linux-gnu-gcc |
| arm-none-eabi | 裸机程序(无操作系统) | arm-none-eabi-gcc |
注意:U-Boot移植必须用arm-linux-gnueabihf-前缀的工具链。别用arm-none-eabi,那个是给裸机用的,链接脚本不一样。
3.1.2 安装步骤
以Ubuntu 20.04为例,我推荐用apt安装,省事。但如果你需要特定版本,就去Linaro官网下载。
# 方法一:apt安装(推荐)
sudo apt update
sudo apt install gcc-arm-linux-gnueabihf
# 方法二:下载Linaro工具链
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
tar -xvf gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf.tar.xz
sudo mv gcc-linaro-7.5.0-2019.12-x86_64_arm-linux-gnueabihf /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
如果看到版本信息,说明工具链装好了。
小技巧:我习惯在/opt下建一个toolchains目录,把所有工具链都放里面。这样方便管理,也方便切换版本。
3.1.3 避坑指南
我曾经在项目里遇到过工具链版本不匹配的问题。U-Boot 2020.04用gcc 7.5编译没问题,但换成gcc 9.4就报了一堆警告。后来查了U-Boot的文档,发现它对GCC版本有明确要求。
- 版本匹配:U-Boot官方推荐GCC 7.x或8.x,别用太新的。
- 32位库:如果你用的是64位系统,可能需要安装32位兼容库:
sudo apt install lib32z1 lib32ncurses5 - 路径不要有中文:工具链路径里别出现中文或空格,否则编译会报一些莫名其妙的错误。
3.2 TFTP与NFS服务器配置
这两个服务是调试U-Boot和内核的利器。TFTP用来下载镜像,NFS用来挂载根文件系统。配合起来用,调试效率能提升好几倍。
3.2.1 TFTP服务器
TFTP是个轻量级的文件传输协议,U-Boot用它从PC上下载内核和设备树。配置起来很简单。
# 安装TFTP服务器
sudo apt install tftpd-hpa
# 配置TFTP目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 修改配置文件
sudo vim /etc/default/tftpd-hpa
配置文件内容:
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure --create"
重启服务:
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa
测试方法:在/srv/tftp下放一个测试文件,然后在板子的U-Boot命令行里执行tftp 0x80800000 test.bin。如果能下载成功,说明TFTP配置没问题。
3.2.2 NFS服务器
NFS用来共享根文件系统。调试内核时,你不需要每次都烧写根文件系统到板子上,直接通过网络挂载就行。
# 安装NFS服务器
sudo apt install nfs-kernel-server
# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs
# 配置导出
sudo vim /etc/exports
在/etc/exports中添加:
/srv/nfs/rootfs *(rw,sync,no_subtree_check,no_root_squash)
重启服务:
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
注意:no_root_squash这个选项很重要。如果不加,板子上的root用户会被映射成nobody,导致权限问题。我曾经因为这个选项,折腾了一下午才找到原因。
3.2.3 网络拓扑
为了让TFTP和NFS正常工作,你需要把PC和板子连在同一个网段。我一般用路由器或者交换机,PC的IP设为192.168.1.100,板子的IP设为192.168.1.200。
3.3 串口终端工具设置
串口是嵌入式开发中最常用的调试接口。U-Boot的启动信息、内核的打印日志,都靠它输出。我推荐两个工具:minicom和picocom。
3.3.1 minicom
minicom是老牌工具,功能强大,但配置稍微复杂一点。
# 安装minicom
sudo apt install minicom
# 配置minicom
sudo minicom -s
进入配置界面后,选择Serial port setup,设置以下参数:
| 参数 | 值 | 说明 |
|---|---|---|
| Serial Device | /dev/ttyUSB0 | 串口设备文件,根据实际情况修改 |
| Bps/Par/Bits | 115200 8N1 | 波特率115200,8数据位,无校验,1停止位 |
| Hardware Flow Control | No | 关闭硬件流控 |
| Software Flow Control | No | 关闭软件流控 |
配置完成后,选择Save setup as dfl保存为默认配置,然后退出。
小技巧:如果minicom启动后屏幕是黑的,按Ctrl+A然后按Z,可以调出帮助菜单。按O进入配置,按X退出。
3.3.2 picocom
picocom更轻量,配置也简单。我个人更喜欢用picocom,因为它启动快,参数直接写在命令行里。
# 安装picocom
sudo apt install picocom
# 启动picocom
picocom -b 115200 -d 8 -p n -s 1 /dev/ttyUSB0
# 参数说明:
# -b 115200 : 波特率
# -d 8 : 数据位
# -p n : 无校验
# -s 1 : 停止位
退出picocom:按Ctrl+A然后按Ctrl+X。
3.3.3 权限问题
串口设备默认只有root用户能访问。如果你不想每次都加sudo,可以把当前用户加入dialout组。
sudo usermod -a -G dialout $USER
然后注销重新登录,或者执行newgrp dialout使组权限生效。
注意:如果你用的是USB转串口模块,比如CH340或CP2102,需要先安装驱动。Ubuntu一般自带驱动,插上就能识别。如果识别不到,检查一下lsusb和dmesg的输出。
3.4 环境验证
环境搭好了,怎么验证?我一般会写一个简单的测试程序,交叉编译后通过TFTP下载到板子上运行。
// test.c
#include <stdio.h>
int main(void)
{
printf("Hello, Embedded Linux!\n");
return 0;
}
交叉编译:
arm-linux-gnueabihf-gcc -o test test.c
把编译好的test文件放到TFTP目录:
cp test /srv/tftp/
然后在板子的U-Boot命令行里:
tftp 0x80800000 test
go 0x80800000
如果串口输出Hello, Embedded Linux!,说明整个环境都通了。
总结一下:开发环境搭建看似琐碎,但每一步都很关键。工具链决定了你能不能编译,TFTP/NFS决定了你能不能高效调试,串口决定了你能不能看到输出。这三样配好了,后面的移植工作才能顺利推进。