设备树节点(node)的表示

本文介绍了设备树中节点的命名规则及其表示方法,包括节点名字的字符限制、节点地址的作用和使用场景,以及如何通过路径唯一标识一个节点。
首先说节点的表示方法,除了根节点只用一个斜杠“/”表示外,其他节点的表示形式如“node-name@unit-address”。
@前边是节点名字,后边是节点地址。
节点名字的长度范围是1到31,可以使用的字符在ePAPR规范中有说明,包括:
0-9    数字
a-z    小写字母
A-Z    大写字母
,    逗号
.    句点(英)
_    下划线
+    加号
-    破折号(英)
规范要求节点名字应该以字母开头,虽然允许后边的位置使用非字母的字符,但实际情况我们实在没必要使用其他字符,一般情况全部用字母表示就够了。特别是规范建议在起名字时采用通用的名字而不是专有的名字,比如对于网卡,使用ethernet表示就可以了,可以通过地址区分不同的网卡,网卡的区别可以通过节点下的属性区分。还有就是关于目前存在的设备基本上都已经有被广泛接受的名字了,我们完全没必要在此标新立异,比如下边规范中列举的节点名字(经常写驱动的人基本一眼就能猜出是哪种设备):
atm
cache-controller
compact-flash
can
cpu
crypto
disk
display
dma-controller
ethernet
ethernet-phy
fdc
flash
gpio
i2c
ide
interrupt-controller
isa
keyboard
mdio
memory
memory-controller
mouse
nvram
parallel
pc-card
pci
pcie
rtc
sata
scsi
serial
sound
spi
timer
usb
vme
watchdog
节点地址是用来区别同名节点的,不是软件意义上的地址,但是有些情况可以用软件地址作为这个地址。比如两个I2C控制器的名字可以都是i2c,然后用控制器寄存器首地址作为这个节点地址。对于cpu,因为它是没有寄存器地址的,就可以用核的号码作为地址,对于8核处理器,地址可以从0到7。ePAPR规范中关于节点地址的描述不太好理解,原文是“The unit-address component of the name is specific to the bus type on which the node sits”。其实我觉得这句话说的也不太准确,因为并不是所有节点表示的硬件都位于某个总线上,比如内存,cpu。设备树是软件对硬件的一种近似表示,软件需要他怎么表示,他就怎么表示。对于cpu,软件需要序号,那么地址就用序号,对于i2c控制器,软件需要寄存器首地址,那么就用地址。除此之外规范还要求,如果节点有地址,那么节点下边必须有一个叫reg的属性,并且该地址必须和reg的属性的第一个地址相同。如果节点没有reg属性,那么节点地址及前边的@必须都不能有。关于属性和值我们还没开始介绍,这里插一句,其实reg就是register的缩写,这个属性主要用来表示控制器寄存器首地址的。我觉得规范中这一条不是非常有必要,因为有些设备只要有一个地址就够了,那么放在节点地址中就够了,完全没必要非得再加个reg属性。在这一段的最后一句,规范来了句“The binding for a particular bus may specify additional, more specific requirements for the format of reg and the unit-address.”,我觉得这句话的意思和“设备树是软件对硬件的一种近似表示,软件需要他怎么表示,他就怎么表示”差不多,没有什么玄的。
节点路径也比较容易理解,从根节点到每个节点都可以形成一个路径,如第一节的例子/cpus/cpu@0,通过这个可以唯一的表示cpu@0这个节点。因为cpu@0在cpus下边是唯一的,但是在整个设备树可能不是唯一的,只有用全路径表示才能毫无异议的确认是哪个节点。如果省略了节点地址也不会产生歧义,那么可以省略不写。就像编程中的括号一样,个人觉得这个没必要省。
除了名字和地址外,节点前边还可以有一个标签(label),这个标签不是必须的,一般只有在别个地方需要引用这个节点时才会用标签标示这个节点,因为如果用全路径太繁琐了。如“i2c_1: i2c@12C70000”中的i2c_1就是一个标签。
<think>我们正在讨论的是Linux内核中平台设备驱动的注册和匹配问题。用户特别询问了在使用`platform_driver_register`注册驱动时,如何确认设备树节点匹配成功。我们需要结合之前的引用和内核机制来解答。 根据引用[1][2][3],匹配过程主要由平台总线(platform_bus_type)完成,其match函数会比较设备树节点的compatible属性和驱动中定义的of_match_table。当驱动注册时,总线会扫描已注册的设备(包括从设备树转换而来的platform_device),并尝试匹配。匹配成功后会调用驱动的probe函数。 因此,确认匹配成功的方法有: 1. 在驱动的probe函数中打印信息:这是最直接的方法,当probe被调用,说明匹配成功。 2. 查看系统日志:使用dmesg命令,可以看到内核在匹配过程中输出的调试信息(如果开启了调试)。 3. 查看sys文件系统:在/sys/bus/platform/devices/下可以找到设备,在/sys/bus/platform/drivers/下可以查看驱动和设备是否绑定。 下面详细展开回答。 </think>### 使用 `platform_driver_register` 时确认设备树节点匹配成功的方法 #### 一、匹配成功的核心标志:`probe()` 函数被调用 **本质原理**: 当驱动通过 `platform_driver_register()` 注册时,平台总线(`platform_bus_type`)会自动执行设备扫描与匹配。匹配设备树节点的关键条件是: **设备树节点的 `compatible` 属性**与驱动中定义的 `of_match_table.compatible` 值完全一致[^1][^3]。 若匹配成功,内核会自动调用驱动的 `probe()` 函数,这是最直接的确认标志[^1][^2]。 --- #### 二、四种验证匹配成功的方法 ##### 1. 在 `probe()` 函数中添加调试输出(推荐) ```c static int my_probe(struct platform_device *pdev) { // 匹配成功时输出设备树节点信息 printk(KERN_INFO "Matched DTS node: %s\n", pdev->dev.of_node->full_name); // 获取匹配的compatible值 const struct of_device_id *match; match = of_match_device(dt_ids, &pdev->dev); printk(KERN_INFO "Matched compatible: %s\n", match->compatible); return 0; } ``` **验证方式**: 查看内核日志 `dmesg | grep "Matched"`,若输出设备节点称和 `compatible` 值即表示匹配成功。 ##### 2. 检查内核日志的自动匹配记录 内核在匹配时会输出关键信息(需开启 `CONFIG_DEBUG_DRIVER`): ```bash $ dmesg | grep platform [ 5.120000] platform my_device: matched driver my_platform_drv # 匹配记录 [ 5.130000] my_platform_drv: probe() called for vendor,device123 # probe调用 ``` 出现类似日志表示设备树节点与驱动成功绑定[^3]。 ##### 3. 通过 sysfs 文件系统验证 查看设备与驱动的绑定状态: ```bash # 查看驱动绑定的设备 $ ls /sys/bus/platform/drivers/my_platform_drv bind module my_device uevent unbind # 查看设备对应的驱动 $ cat /sys/bus/platform/devices/my_device/driver /sys/bus/platform/drivers/my_platform_drv ``` 若设备出现在驱动的目录中,或设备指向该驱动路径,即表示匹配成功。 ##### 4. 验证设备树节点解析结果 检查内核是否成功解析设备树节点: ```c // 在probe函数中检查 if (!pdev->dev.of_node) { printk(KERN_ERR "No DTS node attached!\n"); return -ENODEV; } ``` 若此检查通过,说明内核已识别到对应的设备树节点。 --- #### 三、匹配流程图解 ```mermaid graph LR A[platform_driver_register] --> B[总线扫描设备树节点] B --> C{compatible匹配?} C -- 是 --> D[调用probe函数] C -- 否 --> E[忽略该节点] D --> F[日志输出/sysfs绑定状态更新] ``` (匹配过程由平台总线的 `match()` 函数实现[^3]) --- #### 四、常见匹配失败原因 1. **compatible 拼不一致** DTS: `compatible = "vendor,dev123";` 驱动: `.compatible = "vendor,device123"` // 多'e'导致失败 2. **设备树未启用节点** 缺少 `status = "okay";` 或未在 `dtsi` 中启用 3. **驱动初始化顺序问题** 设备树节点转换的 `platform_device` 在驱动之后注册(需确保驱动注册时机正确) > 提示:使用 `of_dump` 工具检查设备树节点是否被内核解析: > ```bash > $ dtc -I fs /sys/firmware/devicetree/base > ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值