4、设备树绑定文档:如何阅读内核Documentation/devicetree/bindings/

设备树绑定文档,说白了就是硬件描述语言的“说明书”。

我刚入行那会儿,总觉得设备树就是一堆dts文件,改改reg属性、加个compatible就完事了。直到有一次,我调试一个I2C外设死活不工作,折腾了两天,最后发现是绑定时少了一个必需的属性。嗯,从那以后,我再也不敢跳过绑定文档了。

4.1 绑定文档长什么样?

打开内核源码,进入 Documentation/devicetree/bindings/ 目录。你会看到一堆子目录,按硬件类型分类:

  • arm/ — ARM平台相关
  • i2c/ — I2C控制器和设备
  • gpio/ — GPIO控制器
  • clock/ — 时钟框架
  • pinctrl/ — 引脚控制
  • regulator/ — 电源管理
  • sound/ — 音频设备
  • display/ — 显示相关

每个子目录下,通常是一个或多个YAML文件(新格式)或者纯文本文件(老格式)。我个人习惯先看YAML格式的,结构更清晰。

核心要点:绑定文档定义了设备树节点的“语法规则”。你写的dts必须符合这个规则,内核才能正确解析。

4.2 YAML格式的绑定文档怎么读?

以 Documentation/devicetree/bindings/i2c/i2c-imx.yaml 为例。我带你拆解一下:

# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/i2c/i2c-imx.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#

title: Freescale i.MX I2C Controller

maintainers:
  - Oleksij Rempel <o.rempel@pengutronix.de>

properties:
  compatible:
    oneOf:
      - items:
          - enum:
              - fsl,imx1-i2c
              - fsl,imx21-i2c
          - const: fsl,imx1-i2c
      - items:
          - enum:
              - fsl,imx6q-i2c
              - fsl,imx7d-i2c
          - const: fsl,imx21-i2c

  reg:
    maxItems: 1

  interrupts:
    maxItems: 1

  clocks:
    maxItems: 1

  clock-names:
    items:
      - const: ipg

required:
  - compatible
  - reg
  - interrupts
  - clocks

additionalProperties: false

你看,结构非常清晰:

  • title — 文档标题,告诉你这是啥设备
  • maintainers — 维护者邮箱,有问题可以找他们
  • properties — 所有允许的属性列表
  • required — 必须提供的属性,少一个都不行
  • additionalProperties: false — 不允许额外属性,写多了会报错

我的经验:看绑定文档时,先看 required 部分。把必须的属性配齐了,设备大概率能跑起来。optional的属性可以后面慢慢加。

4.3 老格式的纯文本绑定文档

有些老的绑定文档还是纯文本格式,比如 Documentation/devicetree/bindings/gpio/gpio-mxc.txt。这种文档结构松散一些,但核心信息一样:

Freescale i.MX GPIO controller

Required properties:
- compatible: Should be "fsl,imx35-gpio", "fsl,imx31-gpio", etc.
- reg: Address and length of the register set
- interrupts: Should contain the GPIO interrupt(s)
- gpio-controller: Marks the device node as a GPIO controller
- #gpio-cells: Should be 2
- interrupt-controller: Marks the device node as an interrupt controller
- #interrupt-cells: Should be 2

Optional properties:
- clocks: Clock specifier
- clock-names: Should be "gpio"

Example:
gpio1: gpio@73f84000 {
    compatible = "fsl,imx35-gpio", "fsl,imx31-gpio";
    reg = <0x73f84000 0x4000>;
    interrupts = <0 43 0x04>;
    gpio-controller;
    #gpio-cells = <2>;
    interrupt-controller;
    #interrupt-cells = <2>;
};

读这种文档,我一般直接跳到 Example 部分。看一个完整的例子,比读十行文字描述都管用。

4.4 绑定文档里的“坑”

我曾经在一个项目里,把 compatible 字符串写反了顺序。文档里写的是:

compatible = "fsl,imx6q-i2c", "fsl,imx21-i2c";

我写成了:

compatible = "fsl,imx21-i2c", "fsl,imx6q-i2c";

结果内核匹配驱动时,先匹配了 imx21-i2c 的驱动,导致一些新特性没生效。嗯,顺序很重要——越具体的兼容性字符串放前面。

避坑指南:我曾经因为漏掉 #gpio-cells 属性,导致GPIO申请失败。绑定文档里写的 required 属性,一个都不能少。少了内核不会报编译错误,但运行时行为会异常。

4.5 如何快速定位绑定文档?

内核源码那么大,怎么找到某个设备的绑定文档?我一般用这几种方法:

  1. 按目录找 — 知道设备类型,直接进对应子目录
  2. grep大法 — grep -r "compatible字符串" Documentation/devicetree/bindings/
  3. 看驱动源码 — 驱动文件里通常有 MODULE_DEVICE_TABLE,里面会引用绑定文档
  4. 用dt-schema工具 — 新内核支持 make dt_binding_check 直接验证绑定文档

小技巧:我习惯在驱动目录下直接 grep -r "of_match_table",找到匹配表后,再反向搜索绑定文档。这样效率最高。

4.6 绑定文档与设备树的关系

我画了一张图,帮你理清它们之间的关系:

绑定文档 Documentation/devicetree/bindings/ 定义语法规则、必需属性 提供示例、约束条件 设备树源文件 arch/arm/boot/dts/xxx.dts 按绑定文档规则编写 描述具体硬件配置 约束/指导 DTC 编译 dtc -I dts -O dtb -o xxx.dtb xxx.dts DTB 二进制 内核启动时解析 验证 图例: 约束/指导 数据流

说白了,绑定文档就是设备树的“语法书”。你写dts的时候,得照着这本书来。内核启动时,驱动会通过 of_match_table 去匹配设备树节点,匹配的依据就是 compatible 属性。如果属性写错了,驱动根本认不出这个设备。

4.7 实战:如何验证你的设备树是否正确?

写完dts,别急着编译烧录。先用工具验证一下:

# 方法1:使用dt-validate工具
dt-validate -s Documentation/devicetree/bindings/ your.dts

# 方法2:内核自带的检查
make dt_binding_check
make dtbs_check

# 方法3:手动检查关键属性
dtc -I dts -O dtb -o temp.dtb your.dts
dtc -I dtb -O dts temp.dtb | grep -A 20 "your-device"

核心建议:每次修改设备树后,至少跑一遍 dtbs_check。它能帮你发现90%的语法错误和属性缺失问题。我曾经在一个项目中,就因为少写了一个 #clock-cells,导致整个时钟树解析失败,系统起不来。这种低级错误,工具一查就能发现。

4.8 总结一下

读绑定文档,其实就三步:

  1. 找到文档 — 按目录或grep
  2. 看required属性 — 先把必须的配齐
  3. 对照Example — 照猫画虎,别自己发明创造

嗯,就这么简单。但简单不代表不重要。我见过太多工程师,设备树写错了,然后花几天时间调试驱动,最后发现是设备树的问题。绑定文档就是你的“防呆设计”,多看两眼,能省下大把时间。

最后一个小建议:如果你用的是新版本内核(5.x以上),尽量看YAML格式的绑定文档。它结构清晰,而且支持自动化验证。老格式的txt文档虽然也能看,但容易遗漏信息。


可可精品资料库