一、简介

  设备树定义是保留着存在于系统中的设备信息,当机器引导时,OS通过使用驱动程序和其他组件获得的信息建立此树,并且当添加或删除设备时更新此树。

  • 设备树保留着存在于系统中的设备信息。当机器引导时,OS通过使用驱动程序和其他组件获得的信息建立此树,并且当添加或删除设备时更新此树。
  • 设备树是分级的, 总线上的设备代表着总线适配器或驱动控制器的“子集”。
  • 设备树的每一个节点是一个设备节点(devnode),一个devnode包括设备驱动程序的设备对象加上有OS所保留的内部信息。
  • DTS:设备树源文件,ASCII格式
  • DTC:设备树编译工具。
  • DTB:二进制设备树。

Android DisplayArea树详解 android设备树_属性值

 

 

二、设备树的使用

  uboot负责加载到内存,内核解析使用。

1、编译

//内核编译dts
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs

//手工编译
./scripts/dtc/dtc -I dts -O dtb -o xxx.dtb arch/arm/boot/dts/xxx.dts // 编译 dts 为 dtb
./scripts/dtc/dtc -I dtb -O dts -o xxx.dts arch/arm/boot/dts/xxx.dtb // 反编译 dtb 为 dts

2、设备树常见属性介绍

(1)节点属性
cpu0: cpu@0 {
    compatible = "arm,cortex-a7";
    device_type = "cpu";
    reg = <0>;
}
  • cpu0:为结点名称起一个别名。
(2)compatible属性
intc: interrupt-controller@a01000 {
    compatible = "arm,cortex-a7-gic";
    #interrupt-cells = <3>;
    interrupt-controller;
    reg = <0xa01000 0x1000>,
          <0xa02000 0x100>;
};
  • arm:芯片厂商。
  • cortex-a7-gic:模块对应的驱动名
(3)model属性
model = "embedfire i.MX6 ULL NPi Board";
  • 准确描述当前板子型号信息。
(4)status属性

Android DisplayArea树详解 android设备树_设备树_02

 (5)reg属性
ocrams: sram@900000 {
      compatible = "fsl,lpm-sram";
      reg = <0x900000 0x4000>;
    };
  • 地址:外设寄存器组的起始地址。
  • 长度:外设寄存器组的字节长度。
(6)#address-cells和#size-cells属性
soc {
    #address-cells = <1>;
    #size-cells = <0>;
    compatible = "simple-bus";
    interrupt-parent = <&gpc>;
    ranges;
    ocrams: sram@900000 {
            compatible = "fsl,lpm-sram";
            reg = <0x900000>;
    };
};
  • #address-cells:设置子节点reg地址的数量 。
  • #size-cells:设置子节点中reg地址的长度的数量。  

 3、系统中查看设备树

ls /sys/firmware/devicetree/base

 或者:

ls /proc/device-tree

4、驱动中获取DTS属性信息的接口

(1)节点表示:/include/linux/of.h
struct device_node {
    const char *name;  //节点名
    const char *type;  //设备类型
    phandle phandle;
    const char *full_name; //完整名字
    struct fwnode_handle fwnode;
   
    struct  property *properties; //属性
    struct  property *deadprops; 
    struct  device_node *parent; //父节点
    struct  device_node *child;  //子节点
    struct  device_node *sibling;
#if defined(CONFIG_OF_KOBJ)
    struct  kobject kobj;
#endif
    unsigned long _flags;
    void    *data;
#if defined(CONFIG_SPARC)
    const char *path_component_name;
    unsigned int unique_id;
    struct of_irq_controller *irq_trans;
#endif
};

查节点

  • 路径/类型/名字/compatible

incldue/linux/of.h

(2)of_find_node_by_path()函数
struct device_node *of_find_node_by_path(struct device_node *from,const char *path);

参数:

  • from:开始查找的节点,NULL表示从根节点开始查找
  • path:查找的节点名

返回值:

  • 成功:device_node表示的节点
  • 失败:NULL
(3)of_find_node_by_type()函数:根据“device_type“属性来查找节点
struct device_node *of_find_node_by_type(struct device_node *from, const char *type);

不建议使用

(4)of_find_node_by_name()函数:根据"name"属性来查找节点
struct device_node *of_find_node_by_name(struct device_node *from,const char *name);

不建议使用

(5)of_find_compatible_node()函数
struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compat);

参数:

  • from:开始查找的节点,NULL表示从根节点开始查找
  • type:指定 device_type 属性值
  • compat:指定 compatible 属性值

返回值:

  • 成功:device_node表示的节点
  • 失败:NULL

(4)查节点的属性值:incldue/linux/of.h

struct property {
    char    *name;      //属性名
    int     length;     //属性长度
    void    *value;     //属性值
    struct property *next; //下一个属性
#if defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)
    unsigned long _flags;
#endif
#if defined(CONFIG_OF_PROMTREE)
    unsigned int unique_id;
#endif
#if defined(CONFIG_OF_KOBJ)
    struct bin_attribute attr;
#endif
};
(5)of_find_property()函数
  • 节点+属性名

查找节点中的属性

struct property *of_find_property(const struct device_node *np,const char *name,int *lenp);

参数:

  • np:device_node表示的节点
  • name:查找的属性名字
  • lenp:属性值的字节数

返回值:

  • 成功:property表示的属性
  • 失败:NULL
(6)of_property_read_u32()函数:读取一个32位无符号整数
static inline int of_property_read_u32(const struct device_node *np,const char *propname,
u32 *out_value);

参数:

  • np:device_node表示的节点
  • propname:查找的属性名字
  • out_value:属性值的整数值

返回值:

  • 成功:0
  • 失败:负值
(7)of_property_read_u32_array()函数:读取32位无符号整数数组
int of_property_read_u32_array(const struct device_node *np,const char *propname,u32 *out_values,size_t sz)
  • np:device_node表示的节点
  • name:查找的属性名字
  • out_value:读取到的数组值
  • sz :要读取的数组元素数量
(8)of_property_read_string()函数:读字符串
int of_property_read_string(struct device_node *np,const char *propname,const char **out_string)

参数:

  • np:device_node表示的节点
  • proname:查找的属性名字
  • out_string:读取到的字符串值

返回值:

  • 成功:0
  • 失败:负值