一、簡介
設備樹定義是保留着存在於系統中的設備信息,當機器引導時,OS通過使用驅動程序和其他組件獲得的信息建立此樹,並且當添加或刪除設備時更新此樹。
- 設備樹保留着存在於系統中的設備信息。當機器引導時,OS通過使用驅動程序和其他組件獲得的信息建立此樹,並且當添加或刪除設備時更新此樹。
- 設備樹是分級的, 總線上的設備代表着總線適配器或驅動控制器的“子集”。
- 設備樹的每一個節點是一個設備節點(devnode),一個devnode包括設備驅動程序的設備對象加上有OS所保留的內部信息。
- DTS:設備樹源文件,ASCII格式
- DTC:設備樹編譯工具。
- DTB:二進制設備樹。
二、設備樹的使用
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屬性
(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
- 失敗:負值