设备树的概念:

设备树只是用来给内核里的驱动程序, 指定硬件的信息 。比如 LED 驱动,在内核的驱动程序里去操作寄存器,但是操作哪一个引脚?这由设备树指定。
一个单板启动时, u-boot 先运行,它的作用是启动内核。 U-boot 会把内核 和设备树文件都读入内存,然后启动内核。在启动内核时会把设备树在内存中的 地址告诉内核。

设备树:

设备树的概念及引入-LMLPHP

怎么描述这棵树?

我们需要编写设备树文件 (dts: device tree source) ,它需要编译为 dtb(device tree blob)文件,内核使用的是 dtb 文件。

dts文件包含dtsi 文件

设备树文件不需要我们从零写出来,内核支持了某款芯片比如 imx6ull,在内核的arch/arm/boot/dts 目录下就有了能用的设备树模板,一般命名为 xxxx.dtsi。“i”表示“include”,被别的文件引用的。

        我们使用某款芯片制作出了自己的单板,所用资源跟 xxxx.dtsi 是大部分相同,小部分不同,所以需要引脚 xxxx.dtsi 并修改。
dtsi 文件跟 dts 文件的语法是完全一样的

编译、更换设备树

我们一般不会从零写 dts 文件,而是修改。程序员水平有高有低,怎么知道改得对不对?需要编译一下。并且内核直接使用 dts 文件的话,就太低效了,它也需要使用二进制格式的 dtb 文件。

在内核中直接 make

设置 ARCH CROSS_COMPILE PATH 这三个环境变量后,进入 ubuntu 上板子内核源码的目录,执行如下命令即可编译 dtb 文件:make dtbs V=1

内核对设备树的处理

从源代码文件 dts 文件开始,设备树的处理过程为:
设备树的概念及引入-LMLPHP
  • dts PC 机上被编译为 dtb 文件;
  • u-boot dtb 文件传给内核;
  • 内核解析 dtb 文件,把每一个节点都转换为 device_node 结构体;
  • 对于某些 device_node 结构体,会被转换为 platform_device 结构体。

哪些设备树节点会被转换为 platform_device

a)根节点下含有compatile 属性的子节点

b)含有特定compatile 属性的节点的子节点

        如果一个节点的 compatile 属性,它的值是这 4 者之一:"simple-bus","simple-mfd","isa","arm,amba-bus", 那 么 它 的 子结点 ( 需 含 compatile 属性)也可以转换为 platform_device

c)总线 I2CSPI 节点下的子节点:不转换platform_device

        某个总线下到子节点,应该交给对应的总线驱动程序来处理, 它们不应该被 转换为 platform_device

设备树的概念及引入-LMLPHP

怎么转换为 platform_device

内核处理设备树的函数调用过程,这里不去分析;我们只需要得到如下结论:
platform_device 中含有 resource 数组 , 它来自 device_node 的 reg, interrupts 属性 ;
platform_device.dev.of_node 指向 device_node, 可以通过它获得其他属性

platform_device 如何与 platform_driver 配对

从设备树转换得来的 platform_device 会被注册进内核里,以后当我们每 注册一个 platform_driver 时,它们就会两两确定能否配对,如果能配对成功 就调用 platform_driver probe 函数。
设备树的概念及引入-LMLPHP

1 最先比较:是否强制选择某个 driver

比较 : platform_device.driver_override 和 platform_driver.driver.name
        可以设置 platform_device driver_override ,强制选择某个 platform_driver

2 然后比较:设备树信息

比较: platform_device.dev.of_node p latform_driver.driver.of_match_table
        由设备树节点转换得来的 platform_device 中,含有一个结构体: of_node
它的类型如下
设备树的概念及引入-LMLPHP
如果一个 platform_driver 支 持 设 备 树 , 它 的 platform_driver.driver.of_match_table 是一个数组,类型如下:
设备树的概念及引入-LMLPHP
使用设备树信息来判断 dev drv 是否配对时 :
首先 ,如果 of_match_table 中含有 compatible 值,就跟 dev compatile 属性比较,若一致则成功,否则返回失败;
其次 ,如果 of_match_table 中含有 type 值,就跟 dev device_type 属性 比较,若一致则成功,否则返回失败;
最后 ,如果 of_match_table 中含有 name 值,就跟 dev name 属性比 较,若一致则成功,否则返回失败。
而设备树中建议不再使用 devcie_type name 属性,所以基本上只使用设 备节点的 compatible 属性来寻找匹配的 platform_driver

3 接下来比较:platform_device_id

 ⚫ 比较 :platform_device. name 和 platform_driver.id_table[i].name ,id_table 中可能有多项。
        platform_driver.id_table 是“ platform_device_id ”指针,表示该 drv 支持若干个 device,它里面列出了各个 device {.name, .driver_data} , 其中的“name ”表示该 drv 支持的设备的名字, driver_data 是些提供给该 device 的私有数据。

4 最后比较

⚫ 比较:platform_device.name 和 platform_driver.driver.name
        platform_driver.id_table 可能为空, 这 时 可 以 根 据 platform_driver.driver.name 来 寻 找 同 名 的 platform_device。
设备树的概念及引入-LMLPHP

怎么修改设备树文件

一个写得好的驱动程序 , 它会尽量确定所用资源。只把不能确定的资源留给 设备树, 让设备树来指定。根据原理图确定 " 驱动程序无法确定的硬件资源 ", 再在设备树文件中填写对应内容。那么 , 所填写内容的格式是什么 ?

使用芯片厂家提供的工具

有些芯片,厂家提供了对应的设备树生成工具,可以选择某个引脚用于某些 功能,就可以自动生成设备树节点。 再把这些节点复制到内核的设备树文件里即可。

看绑定文档

内核文档 Documentation/devicetree/bindings/ 做得好的厂家也会提供设备树的说明文档

参考同类型单板的设备树文件

网上搜索

实在没办法时, 只能去研究驱动源码

04-09 01:42