设备树

1、什么是设备树  

  设备树(Device Tree),将这个词分开就是“设备”和“树”,描述设备树的文件叫做 DTS(Device Tree Source),这个 DTS 文件采用树形结构描述板级设备,也就是开发板上的设备信息,比如CPU 数量、 内存基地址、 IIC 接口上接了哪些设备、 SPI 接口上接了哪些设备等等。
  设备树描述板级信息,设备信息的文件,dts结尾

2、DTS、DTB、DTC

make dtds

  .dts是DTS源码文件,DTC(在/scripts/dtc)相当于编译器,将.dts编译成.dtb

3、基本结构

(1)头文件

  和 C 语言一样,设备树也支持头文件,设备树的头文件扩展名为.dtsi一般.dtsi 文件用于描述通用SOC 的内部外设信息,比如 CPU 架构、主频、外设寄存器地址范围,比如 UARTIIC 等等。 

(2)设备节点

 1     / {
 2     aliases {
 3         can0 = &flexcan1;
 4     };
 5 
 6     cpus {
 7         #address-cells = <1>;
 8         #size-cells = <0>;
 9 
10         cpu0: cpu@0 {
11             compatible = "arm,cortex-a7";
12             device_type = "cpu";
13             reg = <0>;
14         };
15     };
16 
17     intc: interrupt-controller@00a01000 {
18         compatible = "arm,cortex-a7-gic";
19         #interrupt-cells = <3>;
20         interrupt-controller;
21         reg = <0x00a01000 0x1000>,
22         <0x00a02000 0x100>;
23     };
24 }                

  设备树是采用树形结构来描述板子上的设备信息的文件,每个设备都是一个节点,叫做设备节点,每个节点都通过一些属性信息来描述节点信息,属性就是键—值对。 

第一行中“/”表示根节点,每个设备树只有一个根节点。

aliasescpus intc 是三个子节点

node-name@unit-address

node-name”是节点名字, unit-address”一般表示设备的地址或寄存器首地址,如果某个节点没有地址或者寄存器的话“unit-address”可以不要,比如“cpu@0”、“interrupt-controller@00a01000”。 

label: node-name@unit-address

引入 label 的目的就是为了方便访问节点,可以直接通过&label 来访问这个节点,比如通过&cpu0 就可以访问“cpu@0”这个节点。


(3)属性

  (a)compatible属性

  compatible 属性的值是一个字符串列表, compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序, compatible 属性的值格式如下所示:

"manufacturer,model"
//其中 manufacturer 表示厂商, model 一般是模块对应的驱动名字。

一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。
  (b)model属性

  一般 model 属性描述设备模块信息。
  (c)status属性

  okay、disable、fail、fail-ass。

  (d)address-cells和size-cells属性

  描述子节点的地址信息。 #address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 )#size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 )#address-cells #size-cells 表明了子节点应该如何编写 reg 属性值。
  (f)status

  描述设备状态:okay:设备可操作性。disable:设备当前是不可操作的,但是在未来可以变为可操作的,比如热插拔设备插入后,fai:设备有错误。fail-sss:设备有错,后面接错误内容。

  (e)alisaes

  aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。不过一般会在节点命名的时候会加上 label,然后通过&label来访问节点,这样也很方便,而且设备树里面大量的使用&label 的形式来访问节点。

4、内核解析DTB

  Linux 内核在启动的时候会解析 DTB 文件,然后在/proc/device-tree 目录下生成相应的设备树节点文件。

 

 

5、OF操作函数

(1)常见查找函数

1of_find_node_by_name 函数

struct device_node *of_find_node_by_name(struct device_node *from, const char *name);
//from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
//name:要查找的节点名字。
//返回值: 找到的节点,如果为 NULL 表示查找失败。

2of_find_node_by_type 函数

struct device_node *of_find_node_by_type(struct device_node *from, const char *type)
//from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
//type:要查找的节点对应的 type 字符串,也就是 device_type 属性值。
//返回值: 找到的节点,如果为 NULL 表示查找失败。

3of_find_compatible_node 函数

struct device_node *of_find_compatible_node(struct device_node *from, const char *type, const char *compatible)
//from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
//type:要查找的节点对应的 type 字符串,也就是 device_type 属性值,可以为 NULL,表示忽略掉 device_type 属性。
//compatible: 要查找的节点所对应的 compatible 属性列表。
//返回值: 找到的节点,如果为 NULL 表示查找失败

4of_find_matching_node_and_match 函数

struct device_node *of_find_matching_node_and_match(struct device_node *from, const struct of_device_id *matches, const struct of_device_id **match)
//from:开始查找的节点,如果为 NULL 表示从根节点开始查找整个设备树。
//matches: of_device_id 匹配表,也就是在此匹配表里面查找节点。
//match: 找到的匹配的 of_device_id。
//返回值: 找到的节点,如果为 NULL 表示查找失败

5of_find_node_by_path 函数

inline struct device_node *of_find_node_by_path(const char *path)
//path:带有全路径的节点名
//返回值: 找到的节点,如果为 NULL 表示查找失败

(2)提取属性值

  Linux 内核中使用结构体 property 表示属性

1of_find_property 函数

property *of_find_property(const struct device_node *np, const char *name, int *lenp)
//np:设备节点。
//name: 属性名字。
//lenp:属性值的字节数

2of_property_count_elems_of_size 函数

用于获取属性中元素的数量

3、of_property_read_
读取属性中值

(3)其他的OF

1of_device_is_compatible 函数

查看节点中是否有compat

 

int of_device_is_compatible(const struct device_node *device,
const char *compat)
//device:设备节点。
//compat:要查看的字符串。

2of_get_address 函数

const __be32 *of_get_address(struct device_node *dev,
int index, u64 *size, unsigned int *flags)
//dev:设备节点。
//index:要读取的地址标号。
//size:地址长度。
//flags:参数,比如 IORESOURCE_IO、 IORESOURCE_MEM 等

3、of_iomap 函数

用于直接内存映射

 

posted @ 2020-12-08 09:44  11YS  阅读(903)  评论(0)    收藏  举报