设备树(Device Tree,简称DT)是一种用于描述硬件配置的数据结构,广泛应用于嵌入式Linux系统中。它将硬件信息从内核代码中剥离出来,通过树状结构的形式描述系统的硬件拓扑和设备属性,使内核能够动态适配不同的硬件平台。以下是设备树的核心概念、作用及工作原理的详细解析:
一、设备树的核心作用
-
硬件抽象与解耦
设备树将硬件描述(如CPU、内存、外设等)与内核代码分离,使内核无需针对特定硬件进行硬编码。硬件变更时,只需修改设备树文件,无需重新编译内核。 -
支持多硬件平台
同一内核镜像可通过加载不同的设备树文件,适配多种硬件配置(如开发板、量产设备),显著提升内核的可移植性。 -
动态硬件配置
内核在启动时解析设备树,动态初始化硬件设备,避免静态编译导致的代码冗余。
二、设备树的结构与组成
设备树以树状结构组织,包含以下关键元素:
- 节点(Node)
- 描述硬件设备或总线,如CPU、内存、I2C控制器等。
- 节点通过属性(Property)定义具体配置(如寄存器地址、中断号等)。
- 示例:
i2c0: i2c@fe002000 { compatible = "fsl,imx28-i2c"; reg = <0xfe002000 0x1000>; interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>; };
- 属性(Property)
compatible
:定义设备与驱动的匹配规则(如"vendor,model"
)。reg
:描述寄存器地址和长度(如<0xfe002000 0x1000>
)。interrupts
:定义中断号及触发方式。status
:控制设备状态(如"okay"
启用,"disabled"
禁用)。
- 根节点与特殊节点
- 根节点:包含系统级属性(如
compatible
、model
)。 aliases
节点:为常用节点提供别名(如ethernet0 = ð0
)。chosen
节点:传递启动参数(如bootargs
)。
- 根节点:包含系统级属性(如
三、设备树的工作流程
- 编译设备树
- 设备树源文件(
.dts
)通过设备树编译器(DTC)生成二进制文件(.dtb
)。 - 示例命令:
dtc -I dts -O dtb -o myboard.dtb myboard.dts
- 设备树源文件(
- 启动时加载
- Bootloader(如U-Boot)将
.dtb
文件加载到内存,并将地址传递给内核。
- Bootloader(如U-Boot)将
- 内核解析
- 内核通过Open Firmware(OF)子系统解析设备树,生成设备模型(Device Model)。
- 驱动通过匹配
compatible
属性绑定到对应设备节点,获取硬件配置。
四、设备树的优势
-
可维护性
硬件修改仅需更新设备树文件,无需修改内核代码。 -
可扩展性
支持动态添加新设备(如外设扩展),无需重新编译内核。 -
标准化
统一硬件描述方式,降低多平台开发复杂度。
五、实际应用示例
以下是一个简化的设备树片段,描述一个I2C控制器及其连接的传感器:
/ {
compatible = "vendor,my-board";
model = "My Custom Board";
i2c0: i2c@fe002000 {
compatible = "fsl,imx28-i2c";
reg = <0xfe002000 0x1000>;
interrupts = <GIC_SPI 66 IRQ_TYPE_LEVEL_HIGH>;
status = "okay";
temp_sensor: temp@48 {
compatible = "vendor,temp-sensor";
reg = <0x48>;
};
};
};
- 解析结果:
- 内核识别到I2C控制器(
fsl,imx28-i2c
)和温度传感器(vendor,temp-sensor
)。 - 驱动通过
compatible
属性匹配,初始化设备并读取传感器数据。
- 内核识别到I2C控制器(
六、总结
设备树通过结构化的硬件描述方式,显著提升了嵌入式Linux系统的灵活性、可维护性和可移植性。它是现代嵌入式开发中不可或缺的工具,尤其适用于多硬件平台、动态硬件配置的场景。