3. Linux BSP基础概念

在嵌入式Linux开发中,BSP(Board Support Package,板级支持包)是连接通用Linux内核与具体硬件板卡之间的“适配层”。对于全志T507这类ARM64 SoC平台,BSP并不是单一文件,而是一整套源码、配置、脚本与文档的集合,它决定了系统能否在目标板上正确启动、外设能否被识别、驱动能否加载。理解BSP的定义、启动流程以及U-Boot、Kernel、Rootfs三者关系,是后续进行驱动移植和系统裁剪的前提。

一、BSP的定义与组成

BSP可以理解为“让Linux跑在这块板子上”所需的最小软硬件适配集合。它通常包含以下内容:

  • 引导加载程序:如U-Boot,负责初始化DDR、时钟、串口,加载内核。
  • Linux内核:包含SoC平台代码、设备树、外设驱动。
  • 根文件系统:提供init、shell、库和应用程序。
  • 编译工具链与构建脚本:如交叉编译器、buildroot/Yocto配置、打包脚本。
  • 板级配置文件:如defconfig、dts、分区表、环境变量。

在全志T507的BSP中,常见目录结构会围绕longan或tina SDK组织,包含brandy(U-Boot)、kernel、rootfs、device等目录。BSP的质量直接决定了板卡启动成功率和外设稳定性。

BSP ≠ 驱动。BSP是“板级适配包”,驱动只是其中一部分;BSP还包含启动链、配置、分区、打包和烧录逻辑。

二、T507典型启动流程

全志T507上电后,启动流程遵循ARM SoC常见的多阶段引导。可以概括为:BootROM → SPL/BL2 → U-Boot → Kernel → Rootfs → init。每一阶段都有明确职责:

  1. BootROM:芯片内部固化代码,根据启动介质(eMMC、SD卡、SPI Flash)加载第一级引导。
  2. SPL/BL2:初始化DDR、时钟等关键硬件,为加载完整U-Boot做准备。
  3. U-Boot:提供命令行、环境变量、网络/存储加载能力,最终引导内核。
  4. Kernel:解压并启动内核,解析设备树,初始化驱动,挂载根文件系统。
  5. Rootfs + init:执行/sbin/init或systemd,进入用户空间。

下面这张SVG图展示了T507从加电到用户空间的启动链路,以及U-Boot、Kernel、Rootfs之间的依赖关系。

全志T507 Linux BSP 启动链路与三大部分关系 T507 SoC 硬件平台 CPU / DDR / eMMC / SD / UART / Ethernet / Display / USB BootROM 芯片固化引导 SPL / BL2 DDR/时钟初始化 U-Boot 引导内核 / 环境变量 Linux Kernel 设备树 / 驱动初始化 Rootfs 根文件系统 /sbin/init · systemd · BusyBox · 库 · 应用 挂载点:/ · 分区:rootfs / userdata 挂载 root= bootargs / bootcmd 设备树 Device Tree .dts / .dtsi / .dtb 描述硬件资源:寄存器、中断、时钟、引脚 内核解析DTB Linux 驱动模型:platform_bus · device · driver · probe 设备树节点 → platform_device → 匹配 driver → probe() → 注册字符/块/网络设备 常见子系统:GPIO · I2C · SPI · PWM · USB · Display · Audio · Ethernet 驱动操作硬件

三、U-Boot、Kernel、Rootfs三者关系

三者不是并列关系,而是接力关系。U-Boot是“搬运工”,负责把内核和设备树从存储介质搬到DDR并跳转执行;Kernel是“管理者”,负责初始化硬件、挂载根文件系统、启动第一个用户进程;Rootfs是“生活空间”,提供init程序、shell、库和业务应用。没有Rootfs,内核启动后会因找不到init而panic;没有正确的bootargs,内核可能挂载错误的根分区。

组成部分 核心职责 关键产物 常见问题
U-Boot 硬件初始化、加载内核、传递参数 u-boot.bin、boot.scr、env DDR参数错误、bootcmd错误
Kernel 驱动初始化、内存管理、进程调度 Image、dtb、modules 设备树不匹配、驱动未编入
Rootfs 提供用户空间、init、库、应用 rootfs.tar.gz、ext4镜像 init缺失、库版本不兼容

四、设备树与驱动模型的配合

在T507 BSP中,设备树是“硬件描述文件”,驱动是“硬件操作代码”。内核启动时解析.dtb,将每个节点转换为platform_device或其他总线设备,再与注册的driver进行匹配。匹配成功后调用probe(),完成寄存器映射、中断申请、时钟使能等操作。例如,一个I2C触摸屏在设备树中描述为i2c节点下的子节点,驱动通过of_match_table匹配compatible字符串,最终在probe中注册input设备。

/* 设备树片段:T507 I2C触摸屏 */
&i2c1 {
    status = "okay";
    gt911: touch@5d {
        compatible = "goodix,gt911";
        reg = <0x5d>;
        interrupt-parent = &pio;
        interrupts = <7 8>;   /* PH7, 下降沿 */
        reset-gpios = <&pio 7 9 GPIO_ACTIVE_LOW>;
    };
};

/* 驱动匹配表 */
static const struct of_device_id gt911_of_match[] = {
    { .compatible = "goodix,gt911" },
    { }
};
调试驱动时,优先确认三件事:设备树节点是否status="okay"、compatible是否与驱动一致、probe是否被调用。可用dmesg | grep -i gt911快速定位。

五、常见误区与复盘

  • 误区一:只改内核不改设备树。 T507外设资源多由设备树描述,内核配置正确但设备树未使能,驱动依然不会probe。
  • 误区二:U-Boot能启动就认为BSP没问题。 U-Boot只完成引导,Rootfs挂载失败、驱动缺失仍会导致系统不可用。
  • 误区三:忽略bootargs与分区表。 root=/dev/mmcblk0p2、console=ttyS0,115200等参数错误会直接导致启动失败。
  • 误区四:驱动编成模块但Rootfs中没有。 模块未放入/lib/modules对应目录,modprobe会失败。
排查启动问题时,建议按“BootROM→SPL→U-Boot→Kernel→Rootfs”顺序逐级确认串口日志。不要一上来就改内核配置,先看卡在哪一级。

掌握BSP定义、启动流程以及U-Boot/Kernel/Rootfs三者关系后,后续进行T507的U-Boot移植、内核裁剪、设备树修改和根文件系统制作时,就能明确每一步改动影响启动链的哪个环节,从而快速定位问题、提高开发效率。