4. 板级适配概述
好,咱们进入第四章。这一章说白了,就是给你的开发主机装上「武器」和「弹药」。没有这些,你手里的开发板就是一块砖头。
我刚开始做BSP的时候,最头疼的不是写代码,而是环境搭了三天还没跑通。后来发现,很多坑其实是可以提前避开的。今天我就把这些经验掰开揉碎了讲给你听。
4.1 交叉编译工具链:让PC替ARM干活
你的电脑是x86架构,开发板是ARM架构。x86的编译器编译出来的程序,ARM跑不了。怎么办?用交叉编译器。
交叉编译器运行在x86上,但它生成的目标代码是ARM的。说白了,就是让PC当翻译官,替ARM把C代码翻译成ARM能懂的机器码。
4.1.1 工具链的选择
市面上工具链很多,我列个表,你对照着选:
| 工具链名称 | 适用架构 | C库 | 我的建议 |
|---|---|---|---|
| gcc-arm-none-eabi | ARM Cortex-M/R | newlib | 裸机或RTOS首选 |
| gcc-arm-linux-gnueabihf | ARM Cortex-A | glibc | Linux系统标配 |
| aarch64-linux-gnu | ARMv8 64位 | glibc | 树莓派3B+之后都用这个 |
| buildroot / yocto | 自定义 | 可选 | 生产环境推荐 |
我个人习惯用Linaro提供的预编译工具链,省事。你如果自己从源码编译,那得等一两个小时,还不一定成功。
4.1.2 安装步骤(以Ubuntu 22.04为例)
别怕,就几条命令:
# 下载ARM 32位工具链
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
# 解压到 /opt
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
/opt 下,别放 /usr/local。为什么?因为不同项目可能需要不同版本的工具链,放 /opt 方便切换。我曾经因为版本混用,浪费了一整天排查一个莫名其妙的段错误。
4.1.3 验证工具链是否可用
写个最简单的hello world,交叉编译一下:
// hello.c
#include <stdio.h>
int main(void) {
printf("Hello, Board!\n");
return 0;
}
// 编译
arm-linux-gnueabihf-gcc -o hello hello.c
// 查看文件类型
file hello
// 输出:hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV)
看到「ARM」字样,说明工具链工作正常。这个文件不能在PC上直接运行,得拷到开发板上跑。
4.2 TFTP/NFS服务:让开发板「吃」到文件
开发板没有硬盘,内核和文件系统放哪?要么放SD卡,要么通过网络从PC加载。TFTP和NFS就是干这个的。
TFTP传内核镜像,NFS挂载根文件系统。这两个服务配好了,你改完代码,编译,重启开发板,新程序就自动跑起来了。不用插拔SD卡,不用反复烧写。
4.2.1 TFTP服务配置
TFTP是个极简的文件传输协议,没有认证,没有目录浏览。但正因为它简单,U-Boot和内核都喜欢用它。
# 安装TFTP服务器
sudo apt-get install tftpd-hpa
# 配置
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 mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp
# 重启服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa
sudo ufw allow 69/udp
测试一下:
# 在/srv/tftp下放一个文件
echo "test" > /srv/tftp/test.txt
# 从本机获取
tftp localhost
tftp> get test.txt
tftp> quit
# 或者用命令行
tftp localhost -c get test.txt
4.2.2 NFS服务配置
NFS比TFTP复杂一点,但它能让开发板直接访问PC上的目录,就像访问本地硬盘一样。调试阶段,我强烈建议用NFS挂载根文件系统。
# 安装NFS服务器
sudo apt-get install nfs-kernel-server
# 创建共享目录
sudo mkdir -p /srv/nfs/rootfs
# 配置导出
sudo vim /etc/exports
# 添加一行(假设开发板IP为192.168.1.100)
/srv/nfs/rootfs 192.168.1.100(rw,sync,no_subtree_check,no_root_squash)
# 重启服务
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
rw:读写权限sync:同步写入,保证数据一致性no_root_squash:允许开发板以root身份操作文件。这个很重要,不然你连创建设备节点都会报错
测试挂载:
# 在开发板的U-Boot或Linux中执行
mount -t nfs -o nolock 192.168.1.10:/srv/nfs/rootfs /mnt
4.3 串口终端工具:你和开发板的「电话线」
开发板没有显示器,没有键盘。你怎么跟它交流?串口。串口是嵌入式开发者的「第三只手」。
我见过有人用USB转串口线,结果驱动没装好,折腾半天。也见过有人波特率设错了,看到一堆乱码还以为板子坏了。这些坑,咱们一个个填。
4.3.1 硬件连接
先确认你的开发板串口引脚:
- TXD:发送(接PC的RXD)
- RXD:接收(接PC的TXD)
- GND:地线(必须接)
别接反了。接反了没输出,但不会烧设备。我刚开始就犯过这个错,还以为是板子坏了。
4.3.2 常用工具对比
| 工具 | 平台 | 特点 | 推荐场景 |
|---|---|---|---|
| minicom | Linux | 命令行,轻量 | 服务器环境 |
| screen | Linux/macOS | 自带,无需安装 | 快速调试 |
| putty | Windows | 图形界面,功能全 | Windows用户首选 |
| MobaXterm | Windows | 集成X11,多标签 | 重度用户 |
我个人习惯用screen,因为它几乎每个Linux发行版都自带。但注意,screen的滚动查看不太方便,需要配合Ctrl+A, [进入复制模式。
4.3.3 使用screen连接串口
# 查看串口设备
ls /dev/ttyUSB* # USB转串口
ls /dev/ttyACM* # 原生串口
# 连接(波特率115200,8N1)
sudo screen /dev/ttyUSB0 115200
# 退出:Ctrl+A, 然后按 :quit
4.3.4 使用minicom
# 安装
sudo apt-get install minicom
# 配置
sudo minicom -s
# 进入配置菜单后:
# 1. 选择「Serial port setup」
# 2. 按A修改串口设备:/dev/ttyUSB0
# 3. 按E修改波特率:115200
# 4. 按F关闭硬件流控
# 5. 保存为默认配置
# 启动
sudo minicom
4.4 整体环境验证
所有服务配好后,我们来个「全家桶」测试:
- 开发板上电,串口终端看到U-Boot启动信息
- 在U-Boot中通过TFTP下载内核:
tftp 0x42000000 zImage - 设置内核启动参数,通过NFS挂载根文件系统
- 开发板启动进入Linux,串口终端出现登录提示符
如果以上四步都走通了,恭喜你,开发环境搭建完成。后面的事情,就是写代码、编译、下载、调试的循环了。
一句话总结: 交叉编译器让你能在PC上编译ARM代码,TFTP/NFS让你不用插拔卡就能更新程序,串口终端是你和开发板对话的唯一窗口。这三样配齐了,你才算真正「上车」了。