2. CI基础概念

说实话,做BSP开发,环境搭不好,后面全是坑。我见过太多新手,代码写得挺溜,结果卡在环境配置上好几天。这一章,咱们就把这些基础工作一次性搞定。

你想想看,咱们要在PC上开发,代码最终要跑到ARM架构的TI Jacinto芯片上。这中间需要一套完整的工具链和通信链路。我习惯把整个环境拆成四个部分:宿主系统(Ubuntu虚拟机)、编译工具(交叉编译器)、文件传输(TFTP/NFS)、调试终端(串口)。

核心逻辑: 在x86的Ubuntu上,用交叉编译器生成ARM可执行文件,通过TFTP/NFS把文件送到开发板,再用串口观察运行结果。缺一环,调试就卡壳。

嵌入式Linux开发环境知识体系 嵌入式Linux开发环境核心组件 Ubuntu 22.04 虚拟机 GCC Linaro 交叉编译链 TFTP / NFS 服务器 Minicom / 串口终端 TI Jacinto 开发板 宿主机(编译) → 网络(传输) → 目标板(运行) 串口(调试) 贯穿始终

2.1 Ubuntu虚拟机安装:别小看这一步

我个人习惯用 Ubuntu 22.04 LTS。为什么?因为TI官方的SDK和Processor SDK Linux在这个版本上验证得最充分。你用20.04也行,但有些新工具链的依赖包需要手动补,麻烦。

虚拟机软件我推荐 VMware Workstation Pro 或者 VirtualBox。如果你问我,我会选VMware,它的USB设备穿透和网络配置更稳定。我在项目中遇到过VirtualBox在挂载NFS时偶尔丢包的情况,排查了半天,最后换VMware就没事了。

配置要点:

  • 内存: 至少8GB,建议16GB。编译内核时,4GB内存会直接卡死。
  • CPU: 分配4核以上。交叉编译是并行任务,核越多越快。
  • 磁盘: 至少80GB。一个完整的内核源码树加上编译产物,轻松吃掉30-40GB。
  • 网络: 选择桥接模式。这样开发板和虚拟机在同一个网段,TFTP/NFS才能正常工作。

注意: 不要用NAT模式!NAT模式下,开发板无法直接访问虚拟机,TFTP和NFS都会失败。我曾经有个学员折腾了两天,最后发现是网络模式选错了。

2.2 交叉编译工具链配置:GCC Linaro

交叉编译,说白了就是在x86电脑上编译出ARM芯片能跑的程序。你直接在Ubuntu里gcc编译出来的东西,开发板是跑不了的——指令集都不一样。

TI Jacinto平台用的是 ARM Cortex-A72/A53 核心,所以我们需要 aarch64-linux-gnu 的交叉编译器。我推荐用 Linaro GCC,它是ARM官方推荐的优化版本。

安装步骤:

  1. 下载Linaro GCC 7.5或更高版本(建议用 gcc-arm-9.2-2019.12-x86_64-aarch64-linux-gnu)。
  2. 解压到 /opt/toolchains/ 目录。
  3. 配置环境变量,把工具链的bin目录加入PATH。

具体命令:

# 解压
sudo mkdir -p /opt/toolchains
sudo tar xvf gcc-arm-9.2-2019.12-x86_64-aarch64-linux-gnu.tar.xz -C /opt/toolchains/

# 配置环境变量(写入 ~/.bashrc)
export PATH=/opt/toolchains/gcc-arm-9.2-2019.12-x86_64-aarch64-linux-gnu/bin:$PATH
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-

# 使生效
source ~/.bashrc

# 验证
aarch64-linux-gnu-gcc --version

验证成功的话,你会看到类似这样的输出:

aarch64-linux-gnu-gcc (GCC) 9.2.1 20191025
Copyright (C) 2019 Free Software Foundation, Inc.

小技巧: 我习惯把 ARCH 和 CROSS_COMPILE 也写进 ~/.bashrc。这样每次打开终端,编译内核或驱动时就不用再手动指定了。省事。

2.3 TFTP/NFS服务器搭建:文件传输的命脉

开发板启动后,怎么把编译好的内核、设备树、根文件系统传过去?两个办法:TFTP 和 NFS。

  • TFTP: 用于传输内核镜像(Image)和设备树(.dtb)。U-Boot启动时,通过TFTP从虚拟机拉取这些文件。
  • NFS: 用于挂载根文件系统。开发板通过网络,把虚拟机上共享的目录当作自己的硬盘来用。这样你修改了文件系统,开发板重启就能生效,不用反复烧写。

2.3.1 安装和配置TFTP服务器

# 安装
sudo apt update
sudo apt 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

2.3.2 安装和配置NFS服务器

# 安装
sudo apt install nfs-kernel-server

# 创建共享目录(比如放根文件系统)
sudo mkdir -p /srv/nfs/rootfs

# 配置导出
sudo vim /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,导致无法写入文件系统。我曾经因为这个,调试一个驱动时发现日志写不进去,查了半天才发现是NFS权限问题。

2.4 Minicom/串口终端配置:调试的窗口

开发板没有显示器,你怎么看它打印的信息?怎么输入命令?全靠串口。串口就是BSP工程师的“眼睛”和“手”。

我推荐用 Minicom,轻量、稳定。当然你也可以用 screen 或 putty,但Minicom的配置更直观。

安装和配置:

# 安装
sudo apt install minicom

# 配置(第一次运行)
sudo minicom -s

进入配置菜单后,选择 Serial port setup,设置以下参数:

参数 值 说明
Serial Device /dev/ttyUSB0 根据实际设备节点调整,可能是ttyUSB1或ttyACM0
Bps/Par/Bits 115200 8N1 TI Jacinto默认的串口波特率
Hardware Flow Control No 关闭硬件流控,否则可能无法输入
Software Flow Control No 同上

配置完成后,选择 Save setup as dfl 保存为默认配置。以后直接运行 sudo minicom 就能连上开发板。

小技巧: 如果插上USB转串口线后,/dev/ttyUSB0 不存在,先检查驱动:lsmod | grep usb_serial。如果没有,安装 sudo apt install linux-image-extra-virtual。另外,记得把用户加入 dialout 组,这样就不用每次都sudo了:sudo usermod -aG dialout $USER。

2.5 环境验证:跑通第一个Hello World

环境搭好了,怎么知道对不对?写个简单的C程序,交叉编译,然后放到开发板上跑一下。

在虚拟机上:

# 编写测试程序
echo '#include <stdio.h>
int main() {
    printf("Hello from TI Jacinto!\n");
    return 0;
}' > hello.c

# 交叉编译
aarch64-linux-gnu-gcc -o hello hello.c

# 检查文件类型
file hello

输出应该是:

hello: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-aarch64.so.1

看到 ARM aarch64 就对了。然后把 hello 文件复制到TFTP目录:

cp hello /srv/tftp/

在开发板的串口终端里,通过U-Boot加载并运行:

# 在U-Boot中
tftp 0x80000000 hello
go 0x80000000

如果串口打印出 Hello from TI Jacinto!,恭喜你,整个环境全部打通了。

总结一下: 虚拟机是工作台,交叉编译器是工具,TFTP/NFS是传送带,串口是观察窗。这四个东西配合好,后面的驱动开发才能顺畅。别嫌麻烦,这一步值得花时间彻底搞定。