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
注意: 防火墙要放行UDP 69端口。我曾经在客户现场配了半天,TFTP就是连不上,最后发现是防火墙没关。命令: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
避坑指南: 如果你看到乱码,先检查波特率。U-Boot默认115200,内核可能用其他值。我曾经遇到过U-Boot正常,内核启动后乱码,最后发现是内核的console参数写错了。

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 整体环境验证

所有服务配好后,我们来个「全家桶」测试:

  1. 开发板上电,串口终端看到U-Boot启动信息
  2. 在U-Boot中通过TFTP下载内核:tftp 0x42000000 zImage
  3. 设置内核启动参数,通过NFS挂载根文件系统
  4. 开发板启动进入Linux,串口终端出现登录提示符

如果以上四步都走通了,恭喜你,开发环境搭建完成。后面的事情,就是写代码、编译、下载、调试的循环了。

一句话总结: 交叉编译器让你能在PC上编译ARM代码,TFTP/NFS让你不用插拔卡就能更新程序,串口终端是你和开发板对话的唯一窗口。这三样配齐了,你才算真正「上车」了。

开发环境搭建核心流程 开发主机(x86) 交叉编译器 arm-linux-gnueabihf-gcc TFTP服务器 传输内核/设备树 NFS服务器 共享根文件系统 串口终端 screen / minicom 目标开发板(ARM) U-Boot 通过TFTP加载内核 Linux内核 zImage + 设备树 根文件系统 通过NFS挂载 串口输出 启动日志 / 控制台 TFTP传输 NFS挂载 串口双向通信 交叉编译 → TFTP/NFS传输 → 串口调试,三位一体