文章目录
- 一、设备树的整体样子
- 二、一个**标准节点**长什么样?
- 逐段解释
- 1. 节点名格式
- 2. compatible(驱动匹配)
- 3. reg(硬件地址)
- 4. status(是否启用)
- 5. 引用其他节点(时钟、中断、引脚)
- 三、最简单可运行的完整示例
- 四、设备树的核心规则(记住就会写)
- 五、一句话总结设备树到底是啥
一、设备树的整体样子
/dts-v1/; /* 版本声明,必须写在第一行 */ / { /* 根节点:整棵树的起点 */ model = "我的开发板"; compatible = "vendor,board", "vendor,chip"; /* 子节点:CPU、内存、时钟、串口、GPIO、I2C…… */ cpus { ... }; memory@80000000 { ... }; uart0: uart@fe001000 { ... }; i2c0: i2c@fe010000 { ... }; };一句话概括:
设备树 = 一棵由节点组成的树,描述板子上有哪些硬件、地址是多少、用什么驱动。
二、一个标准节点长什么样?
这是你 99% 会用到的格式:
标签: 设备名@地址 { /* 必选/常用属性 */ compatible = "厂商,型号"; /* 驱动匹配用 */ reg = <地址 长度>; /* 寄存器地址 */ status = "okay"; /* 启用设备 */ /* 可选引用 */ clocks = <&时钟节点>; interrupts = <中断类型 编号 触发方式>; pinctrl-names = "default"; pinctrl-0 = <&引脚配置节点>; };逐段解释
1. 节点名格式
uart0: uart@fe001000uart0:→标签(label),用于被别人引用:&uart0uart→ 设备类型@fe001000→寄存器基地址,必须和 reg 第一个地址一致
设备类型和地址都不是必须的。
2. compatible(驱动匹配)
compatible = "ns16550";- 设备的“身份证”
- 内核靠它找到对应的驱动
双引号表示字符串。
3. reg(硬件地址)
reg = <0xfe001000 0x100>;- 物理地址 + 长度
- 驱动通过它映射寄存器、操作硬件
<>表示单元格数组(cell array) ,也就是一系列 32 位整数值
4. status(是否启用)
status = "okay"; /* 启用 */ status = "disabled"; /* 禁用 */5. 引用其他节点(时钟、中断、引脚)
clocks = <&clk_uart0>; interrupt-parent = <&gic>; interrupts = <0 32 4>; pinctrl-0 = <&uart0_pins>;<&xxx>就是指向另一个节点的指针。
三、最简单可运行的完整示例
/dts-v1/; / { model = "demo-board"; compatible = "demo,board"; /* 内存 */ memory@80000000 { device_type = "memory"; reg = <0x80000000 0x20000000>; /* 512MB */ }; /* 串口 */ uart0: uart@fe001000 { compatible = "ns16550"; reg = <0xfe001000 0x100>; clocks = <&clk_uart0>; status = "okay"; }; /* 时钟 */ clk_uart0: clock { #clock-cells = <0>; compatible = "fixed-clock"; clock-frequency = <24000000>; }; };四、设备树的核心规则(记住就会写)
- 整个文件只有一个根节点
/ - 所有硬件都写在根节点内部,作为子节点
- 带地址的节点必须命名为
xxx@addr @addr必须等于reg的第一个地址compatible是驱动匹配的关键<&xxx>是引用另一个节点reg描述硬件地址status = "okay"表示启用设备
五、一句话总结设备树到底是啥
设备树就是一个结构化的硬件说明书,
告诉 Linux:
板子上有什么设备、地址在哪、用什么驱动、时钟/中断从哪来。