二十二、【devicetree】设备树的介绍
一、简介
设备树定义是保留着存在于系统中的设备信息,当机器引导时,OS通过使用驱动程序和其他组件获得的信息建立此树,并且当添加或删除设备时更新此树。
- 设备树保留着存在于系统中的设备信息。当机器引导时,OS通过使用驱动程序和其他组件获得的信息建立此树,并且当添加或删除设备时更新此树。
- 设备树是分级的, 总线上的设备代表着总线适配器或驱动控制器的“子集”。
- 设备树的每一个节点是一个设备节点(devnode),一个devnode包括设备驱动程序的设备对象加上有OS所保留的内部信息。
- DTS:设备树源文件,ASCII格式
- DTC:设备树编译工具。
- DTB:二进制设备树。
二、设备树的使用
uboot负责加载到内存,内核解析使用。
1、编译
1 2 3 4 5 6 | // 内核编译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)节点属性
1 2 3 4 5 | cpu0: cpu@0 { compatible = "arm,cortex-a7" ; device_type = "cpu" ; reg = <0>; } |
- cpu0:为结点名称起一个别名。
(2)compatible属性
1 2 3 4 5 6 7 | 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属性
1 | model = "embedfire i.MX6 ULL NPi Board" ; |
- 准确描述当前板子型号信息。
(4)status属性
(5)reg属性
1 2 3 4 | ocrams: sram@900000 { compatible = "fsl,lpm-sram" ; reg = <0x900000 0x4000>; }; |
- 地址:外设寄存器组的起始地址。
- 长度:外设寄存器组的字节长度。
(6)#address-cells和#size-cells属性
1 2 3 4 5 6 7 8 9 10 11 | 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、系统中查看设备树
1 | ls /sys/firmware/devicetree/base |
或者:
1 | ls /proc/device-tree |
4、驱动中获取DTS属性信息的接口
(1)节点表示:/include/linux/of.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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()函数
1 | 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“属性来查找节点
1 | struct device_node *of_find_node_by_type( struct device_node *from, const char *type); |
不建议使用
(4)of_find_node_by_name()函数:根据"name"属性来查找节点
1 | struct device_node *of_find_node_by_name( struct device_node *from, const char *name); |
不建议使用
(5)of_find_compatible_node()函数
1 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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()函数
-
节点+属性名
查找节点中的属性
1 | 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位无符号整数
1 2 | 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位无符号整数数组
1 | 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()函数:读字符串
1 | int of_property_read_string( struct device_node *np, const char *propname, const char **out_string) |
参数:
-
np:device_node表示的节点
-
proname:查找的属性名字
-
out_string:读取到的字符串值
返回值:
- 成功:0
- 失败:负值
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
2021-01-20 奇偶校验
2020-01-20 windows CMD指令