2. 开发环境搭建:Linux开发主机配置、交叉编译工具链安装、T113 SDK获取与编译、TFTP/NFS网络启动环境配置

嵌入式Linux驱动开发的第一步是构建一个稳定、可复现的开发环境。本章将指导你从零开始配置全志T113的完整开发栈,包括主机环境、交叉编译工具链、SDK获取与编译,以及用于快速迭代的TFTP/NFS网络启动环境。一个配置正确的开发环境能显著减少后续调试中的“环境问题”干扰,让你专注于驱动逻辑本身。

环境概览: 本课程使用 Ubuntu 22.04 LTS 作为开发主机,全志官方 T113-SDK 基于 Linux 5.4 内核,交叉编译工具链为 arm-linux-gnueabihf- 系列。所有操作均在普通用户权限下完成,仅在必要时使用 sudo。

2.1 Linux开发主机配置

开发主机是驱动开发的“工作台”,需要安装必要的软件包和工具。以下步骤在 Ubuntu 22.04 上验证通过,其他发行版请使用对应的包管理器。

2.1.1 基础软件包安装

# 更新软件源
sudo apt update

# 安装基础开发工具
sudo apt install -y build-essential git vim curl wget \
    libncurses5-dev libssl-dev flex bison \
    u-boot-tools device-tree-compiler \
    python3 python3-pip python3-dev

# 安装网络启动相关服务
sudo apt install -y tftpd-hpa nfs-kernel-server net-tools

# 安装串口调试工具
sudo apt install -y minicom picocom lrzsz
关键包说明:
  • build-essential:包含 gcc、g++、make 等编译核心工具。
  • libncurses5-dev:提供内核 menuconfig 配置界面的依赖。
  • device-tree-compiler:用于编译设备树文件(.dts → .dtb)。
  • tftpd-hpa / nfs-kernel-server:用于搭建网络启动环境,实现内核与根文件系统的远程加载。

2.1.2 主机网络与串口配置

开发主机通常通过以太网与T113目标板连接,同时通过USB转串口线连接目标板的调试串口。建议将主机以太网口配置为静态IP,方便TFTP/NFS服务稳定工作。

# 查看网卡名称(通常为 eth0 或 enpXsY)
ip link show

# 临时配置静态IP(示例:192.168.1.100/24)
sudo ip addr add 192.168.1.100/24 dev eth0
sudo ip link set eth0 up

# 永久配置(编辑 /etc/netplan/ 下的配置文件,以 01-netcfg.yaml 为例)
sudo vim /etc/netplan/01-netcfg.yaml

串口工具推荐使用 picocom,轻量且支持硬件流控关闭(T113调试串口通常无流控):

# 查看串口设备(通常为 /dev/ttyUSB0)
ls -l /dev/ttyUSB*

# 使用 picocom 连接(波特率 115200,8N1,无流控)
sudo picocom -b 115200 -d 8 -p n -s 1 /dev/ttyUSB0

# 退出 picocom:Ctrl+A 然后 Ctrl+X
权限提示: 串口设备默认属于 dialout 组。为避免每次使用 sudo,可将当前用户加入 dialout 组:sudo usermod -aG dialout $USER,然后重新登录生效。

2.2 交叉编译工具链安装

T113 处理器基于 ARM Cortex-A7 架构,需要在 x86 主机上使用交叉编译工具链生成 ARM 目标代码。全志官方 SDK 通常自带工具链,但为了灵活性和版本可控,我们单独安装 Linaro 提供的通用工具链。

2.2.1 工具链选择与下载

工具链名称 目标架构 C库 适用场景
arm-linux-gnueabihf- ARM Cortex-A7 glibc (硬浮点) Linux用户态应用、内核模块
arm-linux-gnueabi- ARM Cortex-A7 glibc (软浮点) 兼容旧版工具链
arm-none-linux-gnueabihf- ARM Cortex-A7 glibc (硬浮点) 裸机或u-boot早期阶段

本课程选用 gcc-arm-10.3-2021.07-x86_64-arm-linux-gnueabihf 版本,支持 C11/C++17 标准,与 Linux 5.4 内核兼容性良好。

# 下载工具链(约 200MB)
wget https://developer.arm.com/-/media/Files/downloads/gnu-a/10.3-2021.07/binrel/gcc-arm-10.3-2021.07-x86_64-arm-linux-gnueabihf.tar.xz

# 解压到 /opt 目录
sudo tar -xvf gcc-arm-10.3-2021.07-x86_64-arm-linux-gnueabihf.tar.xz -C /opt/

# 添加环境变量(写入 ~/.bashrc 或 ~/.zshrc)
echo 'export PATH=$PATH:/opt/gcc-arm-10.3-2021.07-x86_64-arm-linux-gnueabihf/bin' >> ~/.bashrc
source ~/.bashrc

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

2.2.2 工具链验证与测试

编写一个简单的 C 程序,交叉编译后在主机上检查文件类型,确认生成了 ARM 架构的可执行文件。

# 创建测试文件
echo '#include <stdio.h>
int main() { printf("Hello T113!\n"); return 0; }' > test.c

# 交叉编译
arm-linux-gnueabihf-gcc -o test_arm test.c

# 检查文件类型
file test_arm
# 输出应包含:ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)
工具链路径提示: 如果后续编译 SDK 时提示找不到编译器,请确保 arm-linux-gnueabihf-gcc 在 PATH 中,或者通过 SDK 的 build/envsetup.sh 脚本自动设置交叉编译环境。

2.3 T113 SDK获取与编译

全志T113官方SDK基于 Linux 5.4 内核,集成了U-Boot、内核、设备树及基础文件系统。SDK通常通过全志官方客户渠道或合作伙伴获取,本课程假设你已获得 t113-sdk-v1.0.tar.gz 压缩包。

2.3.1 SDK目录结构

解压后,SDK的典型目录结构如下:

t113-sdk/
├── build/               # 编译脚本与配置文件
│   ├── envsetup.sh      # 环境设置脚本
│   ├── mkernel.sh       # 内核编译脚本
│   └── target/          # 板级配置
├── kernel/              # Linux 5.4 内核源码
│   ├── arch/arm/        # ARM 架构相关代码
│   ├── drivers/         # 驱动源码(UART、DMA等)
│   └── ...
├── u-boot/              # U-Boot 引导程序
├── device/              # 设备树源文件(.dts)
│   └── config/          # 板级配置
├── out/                 # 编译输出目录
└── toolchain/           # 内置交叉工具链(可选)

2.3.2 SDK编译流程

编译SDK分为三个主要阶段:环境初始化、内核配置、全量编译。以下步骤以默认配置为例:

# 1. 解压SDK
tar -xzf t113-sdk-v1.0.tar.gz
cd t113-sdk

# 2. 设置编译环境
source build/envsetup.sh
# 选择板级配置(通常为 t113_evb1_config)
lunch

# 3. 配置内核(可选,默认配置已包含UART和DMA支持)
make kernel_menuconfig
# 进入 Device Drivers → Character devices → Serial drivers
# 确认 CONFIG_SERIAL_8250 和 CONFIG_SERIAL_8250_DMA 已开启

# 4. 全量编译(内核、U-Boot、设备树、文件系统)
make -j$(nproc)

# 5. 编译输出位于 out/ 目录
ls out/
# 输出包含:boot.img、rootfs.ext4、u-boot-sunxi-with-spl.bin 等
编译加速技巧:
  • 使用 make -j$(nproc) 并行编译,充分利用多核CPU。
  • 首次编译后,后续仅修改驱动时可单独编译内核模块:make modules -j$(nproc)。
  • 如果修改了设备树,只需重新编译设备树:make dtbs。

2.3.3 编译输出产物说明

产物文件 说明 启动阶段
u-boot-sunxi-with-spl.bin U-Boot引导程序(含SPL) 第一阶段引导
boot.img 内核镜像 + 设备树 + ramdisk 内核启动
rootfs.ext4 根文件系统镜像(ext4格式) 文件系统挂载
*.dtb 编译后的设备树二进制文件 内核解析硬件信息
*.ko 内核模块(驱动) 动态加载

2.4 TFTP/NFS网络启动环境配置

在驱动开发阶段,频繁烧写Flash会严重拖慢迭代速度。通过TFTP/NFS网络启动,可以让T113目标板从网络加载内核和设备树(TFTP),并将根文件系统挂载到主机共享目录(NFS),实现“修改主机文件 → 重启目标板 → 立即生效”的高效工作流。

2.4.1 网络启动架构

下图展示了TFTP/NFS网络启动的整体数据流:

TFTP/NFS 网络启动架构图 开发主机 (Ubuntu) IP: 192.168.1.100 TFTP 服务 /srv/tftp/ NFS 服务 /srv/nfs/rootfs/ 以太网 (100Mbps) T113 目标板 IP: 192.168.1.200 U-Boot TFTP 加载内核+dtb Linux 内核 NFS 挂载根文件系统 流程:目标板上电 → U-Boot通过TFTP获取内核和设备树 → 内核启动后通过NFS挂载根文件系统

2.4.2 TFTP服务配置

TFTP用于传输内核镜像(zImage)和设备树文件(.dtb)。配置步骤如下:

# 1. 创建TFTP根目录
sudo mkdir -p /srv/tftp
sudo chmod 777 /srv/tftp

# 2. 复制编译产物到TFTP目录
sudo cp out/boot.img /srv/tftp/
sudo cp out/*.dtb /srv/tftp/

# 3. 配置TFTP服务(编辑 /etc/default/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"
# 4. 重启TFTP服务
sudo systemctl restart tftpd-hpa
sudo systemctl enable tftpd-hpa

# 5. 验证TFTP服务(本机测试)
echo "test" > /srv/tftp/test.txt
tftp 127.0.0.1 -c get test.txt
cat test.txt

2.4.3 NFS服务配置

NFS用于共享根文件系统,使目标板启动后直接使用主机上的文件系统目录。

# 1. 创建NFS共享目录
sudo mkdir -p /srv/nfs/rootfs
sudo chmod 777 /srv/nfs/rootfs

# 2. 解压或复制根文件系统到共享目录
# 如果SDK编译生成了rootfs.ext4,可挂载后复制内容
sudo mount -o loop out/rootfs.ext4 /mnt
sudo cp -a /mnt/* /srv/nfs/rootfs/
sudo umount /mnt

# 3. 配置NFS导出(编辑 /etc/exports)
sudo vim /etc/exports

在 /etc/exports 中添加:

/srv/nfs/rootfs 192.168.1.0/24(rw,sync,no_subtree_check,no_root_squash)
# 4. 重启NFS服务
sudo systemctl restart nfs-kernel-server
sudo exportfs -av

# 5. 验证NFS挂载(本机测试)
sudo mount -t nfs 127.0.0.1:/srv/nfs/rootfs /mnt
ls /mnt
sudo umount /mnt
安全注意: no_root_squash 选项允许目标板以 root 权限访问共享目录,在开发环境中方便调试,但生产环境应禁用此选项。

2.4.4 U-Boot网络启动参数设置

在T113目标板的U-Boot命令行中,设置以下环境变量实现网络启动:

# 进入U-Boot命令行(上电后按任意键)
# 设置网络参数
setenv ipaddr 192.168.1.200
setenv serverip 192.168.1.100
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0

# 设置TFTP加载命令
setenv loadkernel 'tftp 0x42000000 boot.img'
setenv loaddtb 'tftp 0x43000000 sun8i-t113-evboard.dtb'

# 设置NFS根文件系统启动参数
setenv bootargs 'console=ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.100:/srv/nfs/rootfs,vers=3 rw ip=192.168.1.200:192.168.1.100:192.168.1.1:255.255.255.0::eth0:off'

# 设置完整启动命令
setenv bootcmd 'run loadkernel; run loaddtb; bootm 0x42000000 - 0x43000000'

# 保存环境变量
saveenv

# 执行网络启动
boot
调试技巧: 如果网络启动失败,可在U-Boot中先执行 ping 192.168.1.100 测试网络连通性。如果ping不通,检查网线连接、主机防火墙(sudo ufw disable)以及TFTP/NFS服务状态。

2.5 环境验证清单

完成上述配置后,使用以下清单逐项验证环境是否就绪:

验证项 验证方法 预期结果
交叉编译工具链 arm-linux-gnueabihf-gcc --version 显示版本号(如 10.3.1)
SDK编译 make -j$(nproc) 编译成功,out/ 目录生成镜像文件
TFTP服务 本机 tftp 127.0.0.1 -c get boot.img 成功下载文件
NFS服务 本机 mount -t nfs 127.0.0.1:/srv/nfs/rootfs /mnt 挂载成功,可看到根文件系统内容
串口通信 picocom -b 115200 /dev/ttyUSB0 目标板上电后看到U-Boot启动日志
网络启动 目标板执行 boot 命令 内核启动,最终进入shell提示符