一、设备树
1、采用树型的结构描述设备,单片机驱动里面的设备信息都写在.c文件中,如果linux也这样,会导致内核臃肿,系统应该专注做系统该做的工作,对于设备等文件应该用一个文件(设备树文件)来管理。
二、DTS、DTB、DTC
1、DTS源码文件:.dts类似.c文件
2、DTB:.dts编译后生成的.dtb文件,相当于bin文件
3、DTC:编译器,相当于gcc编译器。可以使用make dtbs命令编译所有的dts文件,编译指定dtbs使用make +指定的dtb文件
三、DTS语法(重点)
1、设备树头文件扩展名为.dtsi,可用include引入。如把一款soc的所有设备共有信息提取成一个通用的.dtsi文件。
2、DTS从'/'开始,从/根节点开始描述设备信息,在/根节点外有一些以&开头如&cpu0这样的语句是“追加内容”。
3、节点名字要求:node-name@unit-address,unit-address一般是外设寄存器的起始地址,特殊情况有可能是I2C的设备地址,要具体分析。一般会使用label:node-name@unit-address的格式来表示,然后通过&label来访问找个节点。
四、设备树在系统中的体现
1、系统启动后可以在根文件系统中看到设备树的节点信息。在/proc/device-tree/目录下存放设备树信息,内核启动的时候会解析设备树,然后在/proc/device-tree/目录下展现出来。
1)我们进入/proc/device-tree/目录下,查看目录下文件,如图所示。
2)然后去到开发板目前对应设备树源文件.dts以及imx6ull.dtsi查看,可以发现/proc/device-tree/目录下的文件和这两个文件下的的根节点以及子节点是对应的。
五、特殊节点
1、aliases子节点,意思是别名,所以它的功能是定义别名,这样方便访问节点,不过一般我们是使用&label来访问节点。
2、chosen子节点,主要为了让uboot的bootargs环境变量传递给内核,在开发板/proc/device-tree/chosen路径下可以查看到有一个文件夹叫bootargs,查看它的值结果和uboot中bootargs的值是一样的,这是uboot启动内核的时候内部通过fdt_chosen函数查找到chosen节点,并在里面添加了bootargs属性,属性值就是bootargs变量值。
六、设备树中的标准属性
1、compatible(兼容性)属性,每一个设备节点下都有这个属性,用于将设备和启动绑定, 属性值为compatible = ”厂商名“,“设备对应驱动名”。如:
compatible = "fsl,imx6ul-evk-wm8960",
2、model属性,一般用于描述设备模块信息。
3、status属性,一般描述设备状态信息:
"okay"表示设备可操作的;
"disabled"表示设备当前不可操作的,但是为了可能可以操作,如热插拔设备;
"fail"表示设备不可操作,设备检测到一系列错误或者设备未来很大几率持续不可工作;
"fail-sss"表示设备不可操作,sss部分表示检测到的错误信息;
4、#address-cells与#size-cells属性
1)#address-cells属性决定了子节点的reg属性中地址信息所占地址的字长(32位);
2)#size-cells属性决定了子节点的reg属性中长度信息所占地址的字长(32位);
3)#address-cells属性与#size-cells属性决定了子节点reg属性如何构建属性值;
5、reg属性:一般用于描述设备地址资源信息(在i2c设备下可能描述地址),比如某个外设 的寄存器地址氛围信息,属性值一般为(address, length)对。
6、ranges属性:它是一个地址映射/转换表,属性值可以为空或者为某种格式编写的数字矩 阵,值不为空说明需要地址转换。
7、name属性:老版本用于记录节点名字。
8、device_type属性:用于描述设备的 FCode,但是设备树没有FCode,此属性只能用于 cpu节点或者 memory 节点。
七、根节点的compatible属性
1、根节点下的compatible属性用于内核检查某设备或某平台支不支持内核运行,也就是与内 核的适配性。
2、在没有设备树的情况下,uboot会向内核发送一个machine id的值也就是设备ID值,告诉内核是什么设备需要启动,内核会将machine id与MACH_TYPE_XXX 宏进行对比,看看其中有木有相等的值,有就支持反之。
3、在使用设备树的情况下,检查的是根节点下的compatible属性值来判断是否支持内核。
八、绑定信息文档
1、设备树是描述板子上设备信息的,不同设备信息不同,反映到设备树属性也会不同。一般想要添加硬件对应的节点可以从linux内核源码中目录/Documentation/devicetree/bindings下查看,格式为.txt文件。(仅供参考)
九、linux内核的OF操作函数
1、设备树是描述设备信息的,驱动是通过OF函数获取设备树的信息的。设备是通过节点的形式挂载在设备树上的,如果想要获取到这个设备的信息,比如先获取设备的节点,linux内核采用device_node结构体来描述一个节点,定义在include/linux/of.h中。
2、查找节点函数
1)查找结点一般使用of_find_node_by_path 函数,通过路径来查找节点,参数是带有全路径的节点名,可以使用节点的别名,比如“/backlight”就是 backlight 这个节点的全路径。
2)查找父子节点的函数分别用of_get_parent函数、of_get_next_child函数。查找父节点函数的参数是为要查找父节点的节点。查找子节点函数的参数有两个,一个是父节点,另一个是前一个子节点,也就是从哪一个子节点开始迭代的查找下一个子节点。可以设置为NULL,表示从第一个子节点开始。
3、获取属性值的OF函数