U-Boot 设备树的来源


📂 设备树文件的层次结构

1. 设备树源文件(.dts/.dtsi)

arch/arm/dts/
├── rv1106.dtsi                    # RV1106 SoC 公共定义(包含)
├── rv1106-evb.dts                 # RV1106 EVB 开发板配置
├── rv1106-evb2.dts                # RV1106 EVB2 开发板配置
├── rv1106b-evb2.dts               # RV1106B EVB2 开发板配置
└── rv1106b-evb2-spi-nand.dts      # RV1106B SPI NAND 配置 ⭐ 你的板子用这个

🌳 设备树来源详解

设备树的三层结构

┌─────────────────────────────────────────────────┐
│  1. rv1106b-evb2-spi-nand.dts (板级配置)          │ ← 最顶层:具体板子
│     #include "rv1106b-evb2.dts"                  │    - 选择启动设备
│                                                  │    - 启用/禁用外设
└────────────────────┬────────────────────────────┘
                     ↓ include
┌─────────────────────────────────────────────────┐
│  2. rv1106b-evb2.dts (开发板配置)                 │ ← 中间层:开发板
│     #include "rv1103b.dtsi"                      │    - 内存配置
│     #include "rv1103b-u-boot.dtsi"               │    - 外设使能
│                                                  │    - 引脚定义
└────────────────────┬────────────────────────────┘
                     ↓ include
┌─────────────────────────────────────────────────┐
│  3. rv1106.dtsi / rv1103b.dtsi (SoC 基础定义)    │ ← 底层:芯片
│     - CPU 核心                                   │    - CPU 信息
│     - 内存控制器                                  │    - 所有外设地址
│     - 中断控制器                                  │    - 时钟定义
│     - 所有外设节点(默认 disabled)                │    - 寄存器映射
└─────────────────────────────────────────────────┘

📝 设备树编译流程

步骤 1:从 .dts 到 .dtb

编译流程图

1. 配置阶段 (make rv1106-spi-nand-tb_defconfig)
   ↓
   .config 中设置:
   CONFIG_DEFAULT_DEVICE_TREE="rv1106-evb"
   
2. 编译阶段 (make -j16)
   ↓
   a. 预处理 .dts 文件
      rv1106-evb.dts + rv1106.dtsi + ... 
      ↓ (cpp 预处理器)
      rv1106-evb.dts.pre.tmp
   
   b. 编译成 .dtb
      rv1106-evb.dts.pre.tmp
      ↓ (dtc - Device Tree Compiler)
      arch/arm/dts/rv1106-evb.dtb
   
   c. 合并到 U-Boot
      u-boot-nodtb.bin + rv1106-evb.dtb
      ↓ (cat 命令)
      u-boot-dtb.bin
   
   d. 打包成镜像
      u-boot-dtb.bin
      ↓ (mkimage)
      u-boot-dtb.img

🔍 实际查看生成的设备树

查看设备树内容的方法

# 方法 1: 反编译 .dtb 为可读的 .dts 格式
dtc -I dtb -O dts /root/rk-tools/u-boot/arch/arm/dts/rv1106b-evb2-spi-nand.dtb

# 方法 2: 使用 U-Boot 工具
fdtdump /root/rk-tools/u-boot/arch/arm/dts/rv1106b-evb2-spi-nand.dtb

# 方法 3: 在 U-Boot 命令行中查看(烧录后)
=> fdt list /
=> fdt print /memory
=> fdt print /spi_nand

📚 完整答案:设备树从哪里来?

1. 设备树的来源

设备树不是"从某处复制"的,而是:

  1. Rockchip 官方编写 → 放在 U-Boot 源码的 arch/arm/dts/ 目录
  2. 编译时自动生成 → 通过 dtc (Device Tree Compiler) 编译成二进制

2. 设备树文件的位置

U-Boot 源码目录:
/root/rk-tools/u-boot/arch/arm/dts/
├── rv1106.dtsi                    # SoC 基础定义(Rockchip 编写)
├── rv1106-u-boot.dtsi             # U-Boot 特定配置
├── rv1106-evb.dts                 # EVB 开发板配置
├── rv1106b-evb2.dts               # EVB2 开发板配置
└── rv1106b-evb2-spi-nand.dts      # ⭐ SPI NAND 板子配置

3. 设备树的继承关系

dts// rv1106b-evb2-spi-nand.dts (你的板子)
/dts-v1/;
#include "rv1106b-evb2.dts"        // ← 包含开发板配置

/ {
    model = "Rockchip RV1106B EVB2 Board";
    compatible = "rockchip,rv1106b-evb2-spi-nand", "rockchip,rv1106b";
    
    chosen {
        stdout-path = &uart0;
        u-boot,spl-boot-order = &spi_nand;  // ← 从 SPI NAND 启动
    };
};

&spi_nand {
    u-boot,dm-spl;                  // ← SPL 阶段启用 SPI NAND
    status = "okay";                // ← 启用 SPI NAND
};
dts// rv1106b-evb2.dts (开发板层)
/dts-v1/;
#include "rv1103b.dtsi"            // ← 包含 SoC 定义
#include "rv1103b-u-boot.dtsi"     // ← U-Boot 配置

/ {
    model = "Rockchip RV1106B EVB2 Board";
    
    chosen {
        u-boot,spl-boot-order = &spi_nor, &emmc;  // 默认从 SPI NOR/eMMC 启动
    };
};

&spi_nand {
    status = "disabled";            // ← 默认禁用 SPI NAND
};
dts// rv1106.dtsi / rv1103b.dtsi (SoC 层 - Rockchip 编写)
/ {
    compatible = "rockchip,rv1106";
    
    cpus {
        cpu0: cpu@f00 {
            compatible = "arm,cortex-a7";
            reg = <0xf00>;
        };
    };
    
    // 所有外设节点(默认 disabled)
    spi_nand: spi@20d40000 {
        compatible = "rockchip,rv1106-sfc";
        reg = <0x20d40000 0x1000>;
        interrupts = <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>;
        clocks = <&cru CLK_SFC>;
        status = "disabled";        // ← 默认禁用,由板级配置启用
    };
    
    // ... 更多外设定义
};

🔧 设备树编译过程


✅ 最终答案

设备树 u-boot.dtb / u-boot-dtb.img 的来源:

  1. 源文件位置

    /root/rk-tools/u-boot/arch/arm/dts/
    ├── rv1106.dtsi              # Rockchip 官方编写的 SoC 定义
    ├── rv1106-evb.dts           # Rockchip 官方编写的开发板配置
    └── rv1106b-evb2-spi-nand.dts # 你的板子配置
    
  2. 编译过程

    # 步骤 1: 预处理(展开 #include)
    cpp rv1106-evb.dts > rv1106-evb.dts.pre.tmp
    
    # 步骤 2: 编译成二进制 DTB
    dtc -I dts -O dtb -o rv1106-evb.dtb rv1106-evb.dts.pre.tmp
    
    # 步骤 3: 复制到输出目录
    cp rv1106-evb.dtb dts/dt.dtb
    
    # 步骤 4: 合并到 U-Boot
    cat u-boot-nodtb.bin dts/dt.dtb > u-boot-dtb.bin
    
    # 步骤 5: 打包成镜像
    mkimage -A arm -T firmware -d u-boot-dtb.bin u-boot-dtb.img
    
  3. 由谁编写

    • Rockchip 官方工程师编写和维护
    • ✅ 放在 U-Boot 源码的 arch/arm/dts/ 目录
    • ✅ 随 U-Boot 源码一起发布
    • ✅ 你可以根据需要修改或创建新的 .dts 文件
  4. 如何查看内容

    # 反编译为可读格式
    dtc -I dtb -O dts /root/rk-tools/u-boot/arch/arm/dts/rv1106-evb.dtb
    
    # 或在 U-Boot 命令行中
    => fdt list /
    => fdt print /memory
    

💡 关键点总结

  • 设备树不是"从某处复制",而是 Rockchip 官方编写并包含在 U-Boot 源码中
  • 编译时自动生成 .dtb 文件
  • 三层结构:SoC 定义 (.dtsi) → 开发板配置 (.dts) → 具体板子配置 (.dts)
  • 通过 #include 继承,避免重复定义
  • 最终合并到 u-boot.bin 形成 u-boot-dtb.bin