3. 设备树基础语法
设备树(Device Tree)是嵌入式 Linux 系统中描述硬件拓扑与资源分配的标准机制。对于网络驱动开发者而言,理解设备树的节点结构、属性定义以及中断绑定规则,是编写可移植、可维护驱动的基石。本章将系统讲解设备树的核心语法,并通过实战案例展示其在网络设备中的应用。
学习目标:掌握设备树节点与属性的定义规则;理解
reg、compatible、interrupts 等核心属性的语义与用法;能够独立编写或修改网络设备节点。
3.1 节点(Node)与属性(Property)基础
设备树由一系列节点组成,每个节点代表一个硬件设备或总线。节点通过属性描述其特性,如地址、中断、时钟等。节点名称通常为 device-name@address 格式,其中 @address 部分可选,用于区分同一类型的不同实例。
/dts-v1/;
/ {
model = "Embedded Network Board";
compatible = "vendor,board-v1";
soc {
#address-cells = <1>;
#size-cells = <1>;
ranges;
ethernet@10000000 {
compatible = "vendor,eth-mac";
reg = <0x10000000 0x1000>;
interrupts = <0 33 4>;
phy-mode = "rgmii";
status = "okay";
};
};
};
节点结构解析:
- 根节点:
/是设备树的根,包含整个系统的顶层属性。 - 子节点:
soc是总线节点,ethernet@10000000是网络设备节点。 - 属性:
compatible、reg、interrupts等描述设备的具体信息。
3.2 核心属性详解
3.2.1 compatible 属性:驱动匹配的关键
compatible 属性是设备树与驱动代码之间的“握手协议”。它定义了一个或多个字符串,用于标识设备的具体型号。Linux 内核通过 of_match_table 匹配该属性,从而加载正确的驱动程序。
// 设备树中的 compatible 属性
compatible = "vendor,eth-mac", "generic,eth";
// 驱动中的匹配表
static const struct of_device_id eth_of_match[] = {
{ .compatible = "vendor,eth-mac", .data = ð_vendor_data },
{ .compatible = "generic,eth", .data = ð_generic_data },
{ /* end */ }
};
MODULE_DEVICE_TABLE(of, eth_of_match);
| 属性 | 格式 | 说明 |
|---|---|---|
compatible |
字符串列表 | 第一个字符串为最精确的型号,后续为兼容型号 |
reg |
地址-长度对 | 描述设备在总线上的地址空间 |
interrupts |
中断描述符 | 指定中断号、触发类型等 |
status |
字符串 | okay 启用,disabled 禁用 |
注意:
compatible 字符串的命名规范为 厂商,设备型号,避免使用通用名称导致驱动匹配冲突。例如 ti,davinci_mdio 优于 mdio。
3.2.2 reg 属性:地址空间描述
reg 属性用于描述设备在总线上的地址范围。其格式由父节点的 #address-cells 和 #size-cells 决定。对于 32 位系统,通常 #address-cells = <1>,#size-cells = <1>。
// 32 位地址空间
soc {
#address-cells = <1>;
#size-cells = <1>;
ethernet@10000000 {
reg = <0x10000000 0x1000>; // 起始地址 0x10000000,长度 0x1000
};
};
// 64 位地址空间
soc {
#address-cells = <2>;
#size-cells = <2>;
ethernet@3000000000 {
reg = <0x0 0x30000000 0x0 0x1000>; // 高32位 0x0,低32位 0x30000000
};
};
3.2.3 interrupts 属性:中断绑定
interrupts 属性是网络驱动中最重要的属性之一。它定义了设备的中断号、中断触发类型以及中断域。中断描述符的格式由 #interrupt-cells 决定,常见格式如下:
// 中断控制器定义
gic: interrupt-controller@f0001000 {
compatible = "arm,gic-400";
reg = <0xf0001000 0x1000>;
interrupt-controller;
#interrupt-cells = <3>; // 3 个 cell:中断类型、中断号、触发类型
};
// 网络设备中断绑定
ethernet@10000000 {
compatible = "vendor,eth-mac";
reg = <0x10000000 0x1000>;
interrupts = <0 33 4>; // GIC_SPI 33, IRQ_TYPE_LEVEL_HIGH
interrupt-parent = <&gic>;
};
| 中断类型 | 值 | 说明 |
|---|---|---|
| GIC_SPI | 0 | 共享外设中断,可路由到任意 CPU |
| GIC_PPI | 1 | 私有外设中断,绑定到特定 CPU |
| IRQ_TYPE_EDGE_RISING | 1 | 上升沿触发 |
| IRQ_TYPE_EDGE_FALLING | 2 | 下降沿触发 |
| IRQ_TYPE_LEVEL_HIGH | 4 | 高电平触发 |
| IRQ_TYPE_LEVEL_LOW | 8 | 低电平触发 |
中断绑定实战要点:
- interrupt-parent:显式指定中断控制器,若不指定则继承父节点。
- 中断号偏移:GIC 中断号通常从 32 开始(SPI 0 对应硬件中断号 32)。
- 触发类型:网络设备常用
IRQ_TYPE_LEVEL_HIGH(4)或IRQ_TYPE_EDGE_RISING(1)。
3.3 网络设备节点实战案例
以下是一个完整的千兆以太网控制器设备树节点示例,包含 MDIO 总线、PHY 设备以及中断绑定:
// 千兆以太网控制器节点
gmac: ethernet@10000000 {
compatible = "snps,dwmac-4.20", "snps,dwmac";
reg = <0x10000000 0x2000>;
interrupts = <0 33 4>, <0 34 4>, <0 35 4>;
interrupt-names = "macirq", "eth_wake_irq", "eth_lpi";
interrupt-parent = <&gic>;
phy-mode = "rgmii";
rx-fifo-depth = <4096>;
tx-fifo-depth = <4096>;
status = "okay";
mdio0: mdio {
#address-cells = <1>;
#size-cells = <0>;
compatible = "snps,dwmac-mdio";
phy0: ethernet-phy@0 {
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c22";
interrupts = <0 36 4>;
interrupt-parent = <&gic>;
};
};
};
实战提示:
- interrupt-names:为每个中断指定名称,驱动可通过
platform_get_irq_byname()获取。 - MDIO 子节点:用于管理 PHY 设备,PHY 的
reg属性对应其 MDIO 地址。 - phy-mode:定义 MAC 与 PHY 之间的接口模式,如
rgmii、rmii、sgmii。
3.4 常见错误与调试方法
| 错误类型 | 现象 | 解决方案 |
|---|---|---|
| compatible 不匹配 | 驱动 probe 失败,dmesg 显示无匹配驱动 |
检查设备树与驱动中的 compatible 字符串是否一致 |
| reg 地址错误 | ioremap 返回 NULL,访问寄存器导致崩溃 | 核对 #address-cells 和 #size-cells,确保地址范围正确 |
| 中断号冲突 | 中断无法触发或触发异常 | 使用 cat /proc/interrupts 查看中断分配情况 |
| 中断类型错误 | 中断丢失或频繁触发 | 确认硬件实际触发类型与设备树中 interrupts 的 cell 一致 |
调试建议:使用
dtc -I dtb -O dts 反编译设备树二进制文件,验证节点属性是否正确。内核启动时添加 clk_ignore_unused 参数可避免时钟未使能导致的中断问题。
3.5 本章小结
设备树是嵌入式 Linux 网络驱动开发的核心技能。通过本章学习,你应掌握:
- 节点与属性:设备树的基本结构,节点命名规则,属性值的格式。
- compatible:驱动匹配的关键,必须与驱动中的
of_match_table一致。 - reg:地址空间描述,注意
#address-cells和#size-cells的配置。 - interrupts:中断绑定,理解中断类型、中断号与触发类型的组合。
- 实战案例:完整的网络设备节点包含 MAC、MDIO、PHY 以及中断配置。