Bootloader 与 BCT 深度解析:架构、特点、差异与实战示例


📺 B站视频讲解(Bilibili)https://www.bilibili.com/video/BV1k1C9BYEAB/

📘 《Yocto项目实战教程》京东购买链接Yocto项目实战教程


Bootloader 与 BCT 深度解析:架构、特点、差异与实战示例

本文系统讲解 Jetson 平台 Bootloader 的核心机制与 BCT(Boot Configuration Table)体系,包括其由何而来、为何存在、与行业其他平台的差异、实际开发中如何修改,以及使用示例。全文结构客观、逻辑清晰,适合书籍章节输出(约 4000 字)。


在这里插入图片描述

一、Bootloader 的角色与边缘 AI SoC 的启动需求

在几乎所有嵌入式系统中,Bootloader 承担着系统从上电到操作系统运行之间的关键任务。然而,不同 SoC 的启动难度差异巨大。例如:

  • NXP i.MX 平台的 Bootloader 主要负责 DDR 初始化与启动 U-Boot;
  • Rockchip 平台由闭源 DDR Bin 完成内存初始化,再启动 U-Boot;
  • Allwinner、Amlogic 平台结构较简单,多由单阶段或双阶段 Bootloader 完成基本工作;
  • NVIDIA Jetson 的启动体系最为复杂,由 BootROM → MB1 → MB2 → UEFI(或 CBoot)组成完整固件链,并需要在 Linux Kernel 启动前完成大量“深度硬件初始化”。

Jetson 的启动难度远超普通 SoC,原因在于其硬件结构中包含:

  • 多个协处理器(BPMP、RCE、SCE、DCE 等)
  • 多媒体硬件(ISP、NVCSI、NVENC/NVDEC)
  • 高速接口(PCIe/SATA/USB3)
  • 复杂的 UPHY Lane 复用
  • 大规模 GPU 初始化要求
  • PMIC 与电源轨严格时序

因此 Jetson 平台必须在 Kernel 启动前,通过 Bootloader 完成一次完整的“硬件自检与初始化”,并确保 GPU、ISP 等硬件在用户态立即可用。

为了管理如此庞大的启动配置,Jetson 引入了其他平台完全没有的 BCT(Boot Configuration Table)体系


二、什么是 BCT?为什么它不是设备树?

1. 准确定义

BCT(Boot Configuration Table)是 Jetson 启动链中 BootROM、MB1、MB2 使用的一组二进制配置表,用于描述启动所需的所有硬件参数。其本质是一种“结构化二进制数据”,并非文本文件,也不是 Linux 设备树(Device Tree)。

2. BCT = Bootloader 的“硬件初始化说明书”

它包含:

  • 电源与 PMIC 的电压配置
  • DDR 初始化参数(SDRAM 配置)
  • UPHY Lane 复用(PCIe/USB/SATA)
  • 存储设备参数(QSPI/UFS/SDMMC)
  • 引脚复用(Pinmux/GPIO)
  • Carveout(BPMP/DCE/ISP 等固件空间)
  • BootROM 安全相关字段(UFUSE、Ratchet 等)

这些参数在 BootROM/MB1 解析后,决定 Jetson 是否能成功启动。

3. 为什么它不像其他平台的设备树?

对比项Linux Device Tree (DTB)BCT (Boot Configuration Table)
使用者Linux KernelBootROM / MB1 / MB2
内容设备拓扑与驱动结构启动所需硬件初始化参数
修改方式DTS 文本 → dtbDTS 文本 → dtb → BCT bin
作用阶段Kernel 运行时上电到 Kernel 之前
是否可以热更新不可不可,必须刷入 QSPI/Bootloader 镜像

因此:

BCT ≠ Device Tree。
它只是使用了 DTS 格式作为“源文件”,最终生成的是 Bootloader 固件使用的二进制表。

4. 为什么 T23x(AGX Orin)开始引入 DTS 格式?

官方给出的理由:

  • DTS 为树形结构,表达能力强
  • 支持 include/override
  • 开发者更容易阅读
  • 可复用 Linux 设备树工具链(dtc)

但这并不改变 BCT 的本质:

Bootloader 解析的是二进制 BCT,而不是 DTS/DTB。


三、Jetson 中的四类 BCT 结构(核心内容)

Jetson 启动链中包含多个阶段,不同阶段解析不同的 BCT 文件。

1. BR-BCT(BootROM-BCT)

BootROM 在冷启动时从 QSPI/闪存读取 BR-BCT,它定义:

  • 启动设备类型(UFS / QSPI / SDMMC)
  • 存储访问参数
  • BootROM 安全配置(Ratchet/KDK/SBK 等)

常见启动失败症状:黑屏、不进入 RCM、没有串口输出。


2. MB1-BCT(最复杂、开发者最常修改)

由 MB1 解析,包含:

  • Pinmux 与 GPIO 配置
  • PMIC Rail 与电源时序
  • UPHY Lane 配置(PCIe/USB/SATA 复用)
  • 存储设备参数(SD/UFS)
  • BootROM Reset PMIC 操作
  • 通用控制器产品配置(Prod Config)

MB1-BCT 是最容易影响自定义载板能否启动的关键。


3. Mem-BCT(DDR/EMC 参数)

包含:

  • EMC / MC(内存控制器)
  • DDR Timing(Training 参数)
  • DRAM-ECC 配置
  • carveout 空间(BPMP/RCE/ISP 固件)

常见症状:
没有串口输出 → DDR 初始化失败 → Mem-BCT 参数错误。


4. MB2-BCT

由 MB2 使用,内容包括:

  • GPIO interrupt mapping
  • 安全配置
  • 固件加载次序(bpmpfw/dcefw/rcefw)
  • 额外的 boot 参数

错误可能导致:摄像头双核固件加载失败,ISP 不工作等。


四、实战示例:修改 Pinmux 并生成新的 BCT

以下示例演示如何在自定义 Carrier Board 上修改某个 GPIO 为输出模式,并正确生成新 BCT。

1. 编辑 MB1-BCT DTS 配置

示例文件:tegra234-mb1-pinmux.dtsi

pinmux@2430000 {
    gpio_pz0_ps4 {
        nvidia,pins = "gpio_pz0";
        nvidia,function = "gpio";
        nvidia,pull = <0>;
        nvidia,enable-input = <0>;   // 输出
        nvidia,io-high-voltage = <1>;
    };
};

2. 编译 DTS → DTB

dtc -I dts -O dtb -o mb1-pinmux.dtb mb1-pinmux.dtsi

3. 使用 NVIDIA 工具生成 BCT(二进制)

tegrabct_v2 --chip 0x23 --bct mb1-pinmux.dtb --bct_out mb1-pinmux.bct

4. 将 BCT 包含到 Bootloader 镜像中

flash.sh -r -k MB1_BCT mb1-pinmux.bct

完成后,设备将使用新 pinmux 配置启动。


五、与其他 SoC 的本质区别(行业对比)

下面用最直观的表格总结 Jetson 与其他平台在 Bootloader 配置方式上的差异:

功能项Jetson(Tegra)NXP i.MX8RockchipAllwinnerAmlogic
BootROM 是否读取硬件配置表?✔(BR-BCT)
是否需要在 Bootloader 完成 GPU/ISP 初始化?
DDR 初始化方式Mem-BCTSPLDDR BinBoot0BL2
UPHY lane 配置MB1-BCTDTS(Kernel)DTS少量DTS
是否支持多固件协处理器?✔(BPMP/RCE/DCE)部分
Boot 配置文件格式DTS → DTB → BCTCFG/TXTDTSDTSDTS
是否有强 OTA(A/B + Capsule)

结论非常明显:

BCT 是 Jetson 启动链特有的固件机制,其他平台均未采用类似结构。


六、为什么 BCT 不能替代设备树(DTB)?

因为两者用于完全不同的目的。

1. BCT 做的是“硬件初始化”

包括:

  • DDR 时序训练
  • 电源 Rail 设置
  • UPHY lane 配置
  • 多媒体 ISP/GPU 提前初始化

2. 设备树(Device Tree)做的是“驱动注册与资源描述”

包括:

  • I2C/SPI/UART 节点
  • 摄像头端点(endpoint)拓扑
  • PCIe/USB 控制器属性
  • GPIO 编号与触发方式

一句话:

BCT 决定能否点亮板子;DTB 决定内核如何驱动板子。


七、Bootloader BCT 的调试技巧(实战经验总结)

技巧 1:启动卡死,没有串口输出 → 极有可能是 Mem-BCT 错误

  • DDR 参数不正确
  • Carveout 设置过大
  • ECC 设置错误

技巧 2:上电即关机 → PMIC Rail 的 MB1-BCT 错误

  • Rail 配置不匹配实际硬件
  • 电压过高/过低被 PMIC 保护
  • Power-good 信号没有按时序到达

技巧 3:USB/PCIe 无法工作 → UPHY Lane 错误

Tegra 的 UPHY 复用十分复杂,USB3/PCIe 共享同一 PHY,Lane 配置错误会导致控制器完全无法枚举。

技巧 4:使用 flash.sh 调试单一 BCT 文件

flash.sh -r -k MB1_BCT custom-mb1-bct.bct

允许快速测试 BCT 修改,无需完整刷机。


八、Bootloader 与 BCT 的整体流程图(完整理解)

上电
  │
  ▼
BootROM
  │读取 BR-BCT(二进制)
  ▼
MB1
  │读取 MB1-BCT
  │初始化:PMIC / Pinmux / UPHY / 时钟 / DDR
  ▼
Mem-BCT(DDR Training)
  │
  ▼
MB2
  │读取 MB2-BCT
  │加载固件(bpmpfw/rcefw/dcefw)
  ▼
UEFI / CBoot
  │合并设备树 Overlay
  │加载 Kernel
  ▼
Linux Kernel
  │解析 DTB
  ▼
用户空间

此图清晰地展示:

Bootloader 阶段大量依赖 BCT;Kernel 阶段依赖的是 Device Tree(DTB)。


九、总结:为什么学习 BCT 是开发 Jetson BSP 的关键?

因为:

  • BCT 决定了 Jetson 能不能启动
  • 是自定义载板最核心的差异适配点
  • 是 PMIC/DDR/UPHY 这些关键硬件的初始化入口
  • 是所有驱动与应用正常工作的前提

一句话总结:

BCT 是 Jetson Bootloader 的基础,是理解自定义硬件、适配载板、解决启动问题的必修内容。

对于任何基于 Jetson 的产品化开发,理解 BCT = 理解整个启动链路。


十、BCT 实战强化:以自定义载板为例的完整操作流程

下面通过真实代码二进制编译过程刷写验证方法,展示 BCT 在工程中的真实作用与修改方式。本小节以“修改 UPHY Lane 以支持自定义板 PCIe + USB3 分配”为例,属于实际开发中最常见、最容易出错的场景之一。


1. 实战背景:为什么要修改 UPHY Lane?

Jetson Orin(T234)平台的 UPHY(高速 SerDes)支持多路复用:

  • 同一组 Lane 可以作为 PCIeUSB3SATADP 等不同控制器的物理层。
  • 官方开发套件和自定义载板通常不同,需要重新分配。

错误 UPHY 配置 = PCIe 不能枚举 / USB3 无法工作 / SATA 不识别。

例:你设计的板子把 UPHY Lane 0 给了 USB3,而不是官方的 PCIe。

那么你必须修改 BCT(而不是 Kernel DTS)。


2. 修改 BCT 配置文件(DTS 源文件)

示例文件:tegra234-mb1-uphy-lane.dtsi

uphy-lane@0 {
    nvidia,lane-number = <0>;
    nvidia,usage = "usb3";      // 将原本的 PCIe 改成 USB3
    nvidia,controller = <&xusb_padctl>;
    nvidia,usb-mode = <1>;       // 1 = USB3 SuperSpeed
};

uphy-lane@1 {
    nvidia,lane-number = <1>;
    nvidia,usage = "pcie";      // 保留 PCIe 用途
    nvidia,controller = <&pcie_c5>;
};

说明:

  • usage 字段是真正决定 Lane 分配的关键字段。
  • 错误配置会导致 UART、USB、PCIe 都无任何输出。

3. 编译 DTS → DTB(树状结构)

dtc -I dts -O dtb -o mb1-uphy-temp.dtb tegra234-mb1-uphy-lane.dtsi

验证 dtb 内容是否正确:

dtdump mb1-uphy-temp.dtb | grep uphy

4. 生成 BCT(二进制配置表)

使用 NVIDIA 工具:tegrabct_v2

tegrabct_v2 \
  --chip 0x23 \
  --bct mb1-uphy-temp.dtb \
  --bct_out mb1-uphy-lane.bct

输出文件即为 BootROM/MB1 可解析的真正 BCT 二进制表


5. 将修改后的 BCT 烧录到板子

无需完整刷机,直接更新 MB1-BCT:

sudo ./flash.sh -r -k MB1_BCT mb1-uphy-lane.bct jetson-orin-nano-devkit mmcblk0p1

解释:

  • -r 不重新刷 RootFS
  • -k MB1_BCT 只更新 MB1 BCT 分区
  • 对开发效率极大提升

6. 重启并观察 Boot Log(串口)

在 UART 上,应看到:

[MB1]: UPHY lane 0 → USB3 mode
[MB1]: UPHY lane 1 → PCIe mode
[XUSB]: Pad configuration OK
[PCIe]: link up on C5

如果看到:

[PCIe]: link timeout

说明 lane 没配置对。


7. 在 Linux 中验证效果

检查 USB3 是否上线

dmesg | grep -i xhci
lsusb -t

检查 PCIe 枚举是否正常

lspci -vv

8. 实战技巧总结(非常重要)

技巧 1:UPHY 配置时必须同时确认 PMIC Rail 状态

某些 USB3 端口需要额外的 5V enable signal,若 PMIC 没配置,USB3 仍然无法工作。

技巧 2:不要把 Kernel DTS 当作 UPHY 配置入口

UPHY 属于 Bootloader 初始化阶段,Kernel DTS 修改无效。

技巧 3:建议每次只改一个 BCT 文件并单独刷新

避免多个变量同时变化,难以定位问题。

技巧 4:使用 diff 找到修改内容

diff -u origin-uphy.dtsi your-uphy.dtsi

十一、全文总结:BCT 的本质与实战价值

结合代码实战,我们可以更清晰理解:

  • BCT 是 Bootloader 用来初始化硬件的二进制表
  • DTS 仅是生成 BCT 的“配置语言”,不是设备树;
  • BCT 修改的典型场景包括 DDR、PMIC、UPHY、Pinmux;
  • Kernel DTS 与 BCT 完全不同,作用阶段不同;
  • 自定义载板开发中必须掌握 BCT,才能保证设备可正常上电启动;
  • Jetson 是行业中唯一采用“BCT 多配置表机制”的 ARM SoC;
  • 理解并掌握 BCT,是 Jetson BSP 工程师的核心能力之一。

📺 B站视频讲解(Bilibili)https://www.bilibili.com/video/BV1k1C9BYEAB/

📘 《Yocto项目实战教程》京东购买链接Yocto项目实战教程


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值