4. 根节点与模型:根节点(/)定义、model属性、compatible属性、版本信息

设备树的根节点是整个硬件描述树的起点,使用斜杠 / 表示。所有其他节点(如 CPU、内存、外设总线)都是根节点的子节点或后代节点。根节点本身也包含若干关键属性,用于描述整个设备的模型、兼容性以及设备树版本信息。

4.1 根节点的定义与结构

在 DTS 文件中,根节点通常位于文件的最顶层,其定义方式如下:

/ {
    model = "TI AM335x BeagleBone Black";
    compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
    #address-cells = <1>;
    #size-cells = <1>;

    chosen { };
    memory@80000000 { };
    cpus { };
    ocp { };
};

根节点必须包含 model 和 compatible 属性,这是设备树规范的基本要求。此外,#address-cells 和 #size-cells 用于定义子节点中地址和长度字段的宽度(以 32 位字为单位)。

关键点: 根节点没有 reg 属性,因为它代表整个系统,而不是一个可寻址的设备。根节点的 #address-cells 和 #size-cells 会被所有子节点继承,除非子节点重新定义。

4.2 model 属性:设备型号标识

model 属性是一个字符串,用于精确标识硬件平台的型号名称。它通常包含制造商名称和产品型号,格式为 "制造商,产品型号"。

属性 格式 示例 说明
model 字符串 "TI AM335x BeagleBone Black" 人类可读的设备型号名称,用于识别具体硬件版本
compatible 字符串列表 "ti,am335x-bone-black", "ti,am33xx" 用于操作系统匹配驱动,按从具体到通用的顺序排列

model 属性的主要用途:

  • 调试与日志:内核启动时打印 model 字符串,帮助开发者确认当前运行的硬件平台。
  • 用户空间识别:通过 /proc/device-tree/model 文件读取,用户态程序可据此判断硬件类型。
  • 固件与引导加载程序:U-Boot 等引导程序可根据 model 选择不同的设备树覆盖或配置。

4.3 compatible 属性:操作系统匹配的核心

compatible 属性是设备树中最重要的属性之一,它定义了设备与操作系统驱动之间的匹配关系。该属性是一个字符串列表,每个字符串代表一个兼容的设备型号,按从最具体到最通用的顺序排列。

compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";

匹配规则:

  1. 操作系统(如 Linux 内核)在启动时读取根节点的 compatible 属性。
  2. 内核遍历字符串列表,依次尝试与注册的 DT_MACHINE 或 of_device_id 匹配。
  3. 匹配成功则加载对应的板级初始化代码或设备驱动。
  4. 如果所有字符串都匹配失败,内核可能无法正确初始化该平台。
实践建议: 编写根节点的 compatible 时,务必包含从具体型号到通用 SoC 系列的完整链条。例如,对于 BeagleBone Black,应包含板级型号 "ti,am335x-bone-black"、板级系列 "ti,am335x-bone" 和 SoC 系列 "ti,am33xx"。这样即使未来内核移除了对特定板级的支持,仍能通过通用 SoC 匹配项保持兼容。

4.4 版本信息与设备树版本

设备树本身也有版本概念,主要通过以下方式体现:

版本信息类型 表示方式 说明
DTS 文件版本 文件头注释或版本控制 通过 Git 等版本管理工具追踪 DTS 文件的修改历史
设备树规范版本 DTB 头部字段 编译后的 DTB 文件头部包含版本号字段,用于解析器兼容性检查
板级版本 model 属性 通过 model 字符串区分同一产品的不同硬件版本(如 Rev B vs Rev C)
兼容性版本 compatible 属性 通过字符串列表表达硬件兼容性层级,隐含版本演进关系

在 DTB 文件头部,设备树编译器会写入以下版本相关字段:

  • boot_param_header 版本:标识 DTB 头部结构的版本号,目前通常为 17。
  • totalsize:DTB 文件总大小,用于解析器分配内存。
  • off_dt_struct 和 off_dt_strings:指向设备树结构和字符串块的偏移量。
注意: 不要将设备树版本与 Linux 内核版本混淆。同一份 DTS 文件可以用于多个内核版本,但需要确保内核中的设备树解析器版本与 DTB 版本兼容。通常,使用较新版本的 dtc 编译器生成的 DTB 可以向后兼容旧内核。

4.5 根节点结构图

下图展示了根节点及其核心属性的层次关系,以及它们如何与操作系统交互:

根节点结构模型与操作系统匹配流程 根节点 (/) model = "BeagleBone Black" compatible = "ti,am335x-..." #address-cells = <1> 操作系统读取根节点 compatible 属性 遍历 compatible 列表,匹配内核驱动 匹配成功 → 加载板级初始化 匹配失败 → 内核 panic 或降级 说明:model 用于人类识别硬件;compatible 用于操作系统驱动匹配;#address-cells/#size-cells 定义地址空间宽度

4.6 根节点属性对比表

下表总结了根节点中常见属性的用途、格式和注意事项:

属性名 是否必需 格式 用途 注意事项
model 是 字符串 标识硬件平台型号 应包含制造商和产品名,如 "TI AM335x BeagleBone Black"
compatible 是 字符串列表 操作系统驱动匹配 按从具体到通用排序,至少包含一个 SoC 级兼容项
#address-cells 推荐 32 位整数 定义子节点地址字段的 32 位字数量 通常为 1(32 位地址)或 2(64 位地址)
#size-cells 推荐 32 位整数 定义子节点长度字段的 32 位字数量 通常为 1(32 位长度)或 2(64 位长度)
chosen 否 子节点 传递引导参数(如 bootargs、stdout-path) 由引导加载程序填充,DTS 中可定义默认值
aliases 否 子节点 为节点定义别名,方便引用 别名必须是唯一的,且不能包含特殊字符

4.7 实践案例:编写根节点

假设我们要为一块基于 NXP i.MX6ULL 的工控板编写根节点,硬件信息如下:

  • 板级型号:MYD-Y6ULL-14x14
  • SoC 系列:fsl,imx6ull
  • 内存地址空间:32 位
  • 引导控制台:串口 1

对应的根节点定义如下:

/ {
    model = "MYiR MYD-Y6ULL-14x14 Board";
    compatible = "myir,myd-y6ull-14x14", "fsl,imx6ull";
    #address-cells = <1>;
    #size-cells = <1>;

    chosen {
        stdout-path = &uart1;
        bootargs = "console=ttymxc0,115200 root=/dev/mmcblk0p2 rootwait";
    };

    aliases {
        mmc0 = &usdhc1;
        mmc1 = &usdhc2;
        serial0 = &uart1;
    };

    memory@80000000 {
        device_type = "memory";
        reg = <0x80000000 0x20000000>;  /* 512 MB */
    };
};
关键实践要点:
  • compatible 的第一项必须是当前板级的具体型号,第二项是 SoC 系列,便于内核回退匹配。
  • model 字符串应包含制造商和完整产品名,方便调试时快速识别。
  • chosen 节点中的 stdout-path 指定内核启动日志输出设备,通常指向调试串口。
  • aliases 节点为常用外设(如 MMC、串口)定义简短别名,便于其他节点引用。
  • memory 节点必须包含 device_type = "memory" 属性,这是设备树规范的要求。

4.8 常见错误与排查

错误类型 现象 原因 解决方案
缺少 model 属性 内核启动时显示 No model name in device tree 根节点未定义 model 属性 添加 model = "xxx";
compatible 顺序错误 内核无法匹配到正确的板级初始化代码 通用项放在了具体项之前 将最具体的板级型号放在列表首位
#address-cells 缺失 子节点 reg 属性解析错误,内存映射异常 根节点未定义地址单元大小 根据 SoC 地址宽度添加 #address-cells
chosen 节点拼写错误 内核启动参数不生效 节点名写成了 choose 或 chossen 检查节点名必须为 chosen
调试提示: 如果内核启动时出现 OF: fdt: not found /model 或 No compatible manufacturer found 等错误,请首先检查根节点的 model 和 compatible 属性是否正确定义。可以使用 dtc -I dtb -O dts xxx.dtb 反编译 DTB 文件,直接查看根节点内容。