Linux 设备树详解

目录

1、概述

2、节点( node)和属性( property)

2.1、DTS 描述键值对的语法:

2.2 节点语法规范说明

2.3节点名及节点路径

2.4 节点别名(节点引用)

2.5 合并节点内容

2.6 替换节点内容

2.8 chosen 节点

2.9 查找节点

2.10 查找办法

3 节点描述

 3.1 节点属性


1、概述

        设备树( Device Tree)是一种描述硬件的数据结构,在操作系统( OS)引导
阶段进行设备初始化的时候,数据结构中的硬件信息被检测并传递给操作系统
最早诞生于 Open Firmware, Flattened Device Tree (FDT)格式标准。
 dts 文件( Device Tree Source, dts)是以 ASCII 文本形式描述设备树内容。
 dtb 文件是二进制格式,编译工具为: Device Tree Compiler( DTC)。
 2011 年被引入 ARM Linux 内核。 ARM Linux 设备树描述了内核的软/硬件信息。

2、节点( node)和属性( property)

        节点用以归类描述一个硬件信息或是软件信息(好比文件系统的目录)
     节点内描述了一个或多个属性,属性是键值对( key/value),描述具体的
软/硬信息。
为什么 ARM Linux 社区会引入设备树呢?
    主要是想解决 ARM Linux 内核代码冗余的问题。

2.1、DTS 描述键值对的语法:


 1、字符串信息
 2、 32bits 无符号整型数组信息
 3、二进制数数组
 4、混和形式
 5、字符串哈希表

/dts-v1/;
#include "exynos4412.dtsi" //此设备树依赖于exynos4412.dtsi 文件
#include <dt-bindings/gpio/gpio.h> //gpio引脚配置文件
/ { //根节点 root nodemodel = "FriendlyARM TINY4412 board based on Exynos4412";compatible = "friendlyarm,tiny4412", "samsung,exynos4412", "samsung,exynos4";chosen {stdout-path = &serial_0;
};

2.2 节点语法规范说明

节点名:
语法: <name>[@<unit-address>]
规范:
名字是ASCII字符串
(字母、数字、 "-"、等等构成)
最长可以是31个字符一般的,应该以设备类型命名
unit-address一般的是设备地址
/*****示例*****/
/{serial@101F0000{……};gpio@101F3000{……};interrupt-controller@10140000{……};spi@10115000{…….};external-bus{……};
}; 

2.3节点名及节点路径

/{…dm9000{…};…
};
节点名:dm9000
节点路径:/dm9000

2.4 节点别名(节点引用)

    为了解决节点路径名过长的问题,引入了节点别名的概念,可以引用到一个全路径的节点

/{aliases{demo=&demo0;};…demo:demo0@80000000{…};…
};
节点名:demo0
节点路径:/demo0@80000000
节点别名:demo(等价/demo0@80000000)/**********************************/
引用语法范例1:
&demo{…
};
引用语法范例2:
/{reference-node{property=<&demo>;…};…
};

2.5 合并节点内容

     一般的, 一个硬件设备的部分信息不会变化,但是部分信息是可能会变化的,就出现了节点内容合并。即:先编写好节点,仅仅描述部分属性值;使用者后加一部分属性值。在同级路径下,节点名相同的“两个”节点实际是一个节点。

/{node{property=value;};
};
/*移植者添加的节点*/
/{node{property2=value;};
};
/***合并后的节点内容***/
/{node{property2=value;};
};

2.6 替换节点内容

        一个硬件设备的部分属性信息可能会变化,但是设备树里面已经描述了所有的属性值,使用者可以添加已有的属性值,以替换原有的属性值,就出现了节点内容替换。在同级路径下,节点名相同的“两个”节点实际是一个节点。

2.7 引用节点内容

     一个设备可能会使用到别的节点的内容,可以通过节点的别名来引用到其内容。 引用的目的可能是合并两个节点的内容、 替换部分内容、或是使用部分内容.

/{node:node@80000000{property=value;};
};
/*移植者添加的node节点*/
&node{property=value;status = “okay”;
}
/*移植者添加demo节点*/
/{demo{property=<&node>;};
};
说明:demo节点的属性property引用了节点的node的属性值,一般的,引用的目的是使用node节点的部分属性内容

2.8 chosen 节点

     chosen 节点不描述一个真实设备,而是用于 firmware 传递一些数据给 OS,譬如 bootloader 传递内核启动参数给内核.

chosen {bootargs = “root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200”;
};

2.9 查找节点

   涉及设备、总线、驱动的概念,即所谓设备信息和驱动代码分离的驱动框架,如 platform、 i2c、 usb、spi、 pci、等等; 或是分层驱动框架( MTD 设备驱动、framebuffer 设备驱动、 input 设备驱动、 ...),则设备树中设备节点的会内核初始化时候被查找到,驱动代码将不关心节点的查找。
 如果仅仅是接口驱动框架(字符设备驱动、块设备驱动、网络设备驱动) ,则需要使用内核节点查找函数查找设备树中的设备节点。

2.10 查找办法


 通过节点的 compatible 属性值查找指定节点
 通过节点名查找指定节点
 通过节点路径查找指定节点

3 节点描述

头文件: include/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; /* removed properties */struct  device_node *parent; 父节点指针struct  device_node *child; //子节点指针struct  device_node *sibling;struct  kobject kobj;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 属性查找指定节点

struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compat);
参数:
struct device_node *from - 指向开始路径的节点,如果为NULL,则从根节点开始
const char *type - device_type设备类型,可以为NULL
const char *compat - 指向节点的compatible属性的值(字符串)的首地址
返回值:
成功:得到节点的首地址;失败: NULL

设备 ID 表结构,用于匹配设备节点和驱动

struct of_device_id {char name[32]; /*设备名*/char type[32]; /*设备类型*/char compatible[128]; /*用于与设备树compatible属性值匹配的字符串*/const void *data; /*驱动私有数据*/
};
//注册支持设备树的设备ID表
include/module.h
MODULE_DEVICE_TABLE(of, ID表首地址)

功能:通过 compatible 属性查找指定节点

struct device_node *of_find_matching_node(struct device_node *from,
const struct of_device_id *matches);
参数:
struct device_node *from - 指向开始路径的节点,如果为NULL,则从根节点开始
const struct of_device_id *matches - 指向设备ID表,注意ID表必须以NULL结束
范例:
const struct of_device_id mydemo_of_match[] = {{ .compatible = "fs4412,mydemo", },{}
};
返回值:
成功:得到节点的首地址;失败: NULL

功能:通过路径查找指定节点

struct device_node *of_find_node_by_path(const char *path);
参数:
const char *path - 带全路径的节点名,也可以是节点的别名
返回值:
成功:得到节点的首地址;失败: NULL

功能:通过节点名查找指定节点

struct device_node *of_find_node_by_name(struct device_node *from,
const char *name);
参数:
struct device_node *from - 开始查找节点,如果为NULL,则从根节点开始
const char *name- 节点名
返回值:
成功:
得到节点的首地址;失败: NULL

 3.1 节点属性


有默认意义的属性
 1、设备树语法中已经定义好的,具有通用规范意义的属性。
 如果是设备信息和驱动分离框架的设备节点,则能够在内核初始化找到节点时候,自动解析生成相应的设备信息。
 常见属性的有: compatible、地址 address、中断 interrupt
 ARM Linux 内核定义好的,一类设备通用的有默认意义的属性
 一般的,不能被内核自动解析生成相应的设备信息,但是内核已经编写了相应的解析提取函数。
 常见属性的有: MAC 地址、 GPIO 口、 clock、 power、 regulator、等等

驱动自定义属性

针对具体设备,有部分属性很难通用,需要驱动自己定义好,通过内核的属性提取解析函数进行值的获得。

ethernet@18000000 {compatible = “davicom,dm9000”;reg = <0x18000000 0x2 0x18000004 0x2>;interrupt = <7 4>;local-mac-address = [00 00 de ad be ef];davicom,no-eeprom;reset-gpios = <&gpf 12 GPIO_ACTIVE_LOW>;vcc-supply = <&eth0_power>;
};

compatible 属性

用于匹配设备节点和设备驱动,规则是驱动设备 ID 表中的 compatible 域的值(字符串),和设备树中设备节点中的 compatible 属性值完全一致,则节点的内容是给驱动的。
 设备树中的命名规范如下

/{
node{compatible=“厂商名,名称” ;......vcc-supply = <&eth0_power>;
};设备树示例
/{…mydemo{compatible = “fs4412,mydemo”;…}
}/*platform 框架的探测函数*/
static int demo_probe(struct platform_device *devices)
{
//设备树对应节点的信息已经被内核构造成struct platform_devic
…
}
static const struct of_device_id demo_of_matches[] = {{.compatible = “fs4412,mydemo”,},{}
}
MODULE_DEVICE_TABLE(of,demo_of_matches);static struct platform_driver demo_drv = {.driver = {.name = DEMONAME,.owner = THIS_MODULE,.of_match_table = of_match_ptr(demo_of)}
}

属性-address

#address-cells:描述子节点 reg 属性值的地址表中首地址 cell 数量
#size-cells:描述子节点 reg 属性值的地址表中地址长度 cell 数量

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/634607.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue2:用ref方式绑定自定义事件的注意事项

一、场景描述 我们知道绑定自定义事件可以用ref方式实现。 但是&#xff0c;这个方式&#xff0c;需要注意下&#xff0c;否则&#xff0c;实现不了我们的效果。 需求是这样的&#xff0c;我们通过ref绑定的事件&#xff0c;来给App的data块中的变量赋值。 二、绑定自定义事…

java:流程控制

一、流程控制语句分类 顺序结构分支结构&#xff08;if&#xff0c;switch&#xff09;循环结构&#xff08;for&#xff0c;while&#xff0c;do...while&#xff09; 二、顺序结构 定义&#xff1a;顺序结构是程序中最基本的流程控制&#xff0c;没有特定的语法结构&#…

[latex]将表格中\cmidrule加粗

在写论文时&#xff0c;偶尔会出现需要使用 \cmidrule 代替 \bottomrule 和 \toprule 的时候&#xff0c;但是苦于无法对\cmidrule进行加粗。解决方法&#xff1a; 在LaTeX中&#xff0c;\cmidrule默认没有直接设置线宽的选项&#xff0c;但读者可以通过一些技巧实现。以下是一…

Midjourney

知数云 | 数字化服务的智慧之选 Midjourney是一款AI制图工具&#xff0c;只要输入关键字&#xff0c;透过AI算法就能生成相对应的图片。 使用Spring接口与Midjourney官方API交互涉及几个步骤。首先&#xff0c;确保你已经在Midjourney官方网站上注册了账户并获取了API密钥。 …

Sqoop故障排除指南:处理错误和问题

故障排除是每位数据工程师和分析师在使用Sqoop进行数据传输时都可能遇到的关键任务。Sqoop是一个功能强大的工具&#xff0c;但在实际使用中可能会出现各种错误和问题。本文将提供一个详尽的Sqoop故障排除指南&#xff0c;涵盖常见错误、问题和解决方法&#xff0c;并提供丰富的…

leetcode-杨辉三角

118. 杨辉三角 题解&#xff1a; 首先&#xff0c;我们需要创建一个二维列表&#xff0c;用于存储杨辉三角的每一行。然后&#xff0c;我们初始化第一行和第二行&#xff0c;因为杨辉三角的前两行是固定的。接下来&#xff0c;我们使用一个循环&#xff0c;从第三行开始&…

HarmonyOS4.0系列——07、自定义组件的生命周期、路由以及路由传参

自定义组件的生命周期 允许在生命周期函数中使用 Promise 和异步回调函数&#xff0c;比如网络资源获取&#xff0c;定时器设置等&#xff1b; 页面生命周期 即被Entry 装饰的组件生命周期&#xff0c;提供以下生命周期接口&#xff1a; onPageShow 页面加载时触发&#xff…

2023年上半年网络工程师真题(3/3)

41.某主机无法上网&#xff0c;查看本地连接后&#xff0c;发现只有发送包没有接收包&#xff0c;故障原因可能是&#xff08;C&#xff09;。 A.网线没有插好 B.DNS配置错误 C.IP地址配置错误 D.TCP/IP协议故障 如果网线没有插好&#xff0c;就没有发送包没有接收包;DNS配…

UI设计中的插画运用优势(上)

1. 插画是设计的原创性和艺术性的基础 无论是印刷品、品牌设计还是UI界面&#xff0c;更加风格化的插画能够将不同的风格和创意加入其中&#xff0c;在激烈的竞争中更容易因此脱颖而出。留下用户才有转化。 2. 插画是视觉触发器&#xff0c;瞬间传达大量信息 我们常说「一图胜千…

Skydel 23.8新版本发布!GNSS模拟器完成首项实地路测项目

奥本大学自动驾驶团队运用GNSS模拟器完成首项实地路测项目 奥本大学与最近与阿拉巴马州伯明翰的巴伯赛车运动公园合作进行道路测试&#xff0c;该车在没有任何人工干预的情况下成功绕赛道完成了一圈&#xff0c;这也是印地自动驾驶挑战赛中车辆首次在美国专业赛道上完成一圈。…

unity-shader笔记OLD

shader shader在面板中的位置相关代码代码切换shader shader在面板中的位置 选中物体属性面板中 相关代码 代码切换shader 挂载到怪物上的shader名字统一叫body&#xff0c;然后获取上面的SkinnedMeshRender SkinnedMeshRender smr&#xff1b; //恢复到原来的shader …

智能驾驶新浪潮:SSD与UFS存储技术如何破浪前行?- SSD篇

随着汽车行业的不断发展&#xff0c;对存储的需求也在不断的变化中。早期阶段的汽车对存储的需求主要是收音机、播放器、导航仪等&#xff0c;有些还可以支持光盘和U盘的外接播放。中期阶段&#xff0c;也是当前主流的燃油车行车记录、多媒体、车联网的需求&#xff0c;对存储性…

大数据开发之Hadoop(优化新特征)

第 1 章&#xff1a;HDFS-故障排除 注意&#xff1a;采用三台服务器即可&#xff0c;恢复到Yarn开始的服务器快照。 1.1 集群安全模块 1、安全模式&#xff1a;文件系统只接收读数据请求&#xff0c;而不接收删除、修改等变更请求 2、进入安全模式场景 1&#xff09;NameNod…

【ARM 嵌入式 编译系列 2.2 -- GCC 编译参数学习 assembler-with-cpp 使用介绍】

文章目录 GCC 编译选项 assembler-with-cpp GCC 编译选项 assembler-with-cpp 在 rt-thread 的编译脚本中经常会看到下面编译参数&#xff1a; AFLAGS -c DEVICE -x assembler-with-cpp -Wa,-mimplicit-itthumb arm-none-eabi-gcc 是针对 ARM 架构的交叉编译器&#xff…

国考省考行测:语句排序2刷题

国考省考行测&#xff1a;语句排序2刷题 2022找工作是学历、能力和运气的超强结合体! 公务员特招重点就是专业技能&#xff0c;附带行测和申论&#xff0c;而常规国考省考最重要的还是申论和行测&#xff0c;所以大家认真准备吧&#xff0c;我讲一起屡屡申论和行测的重要知识点…

肯尼斯·里科《C和指针》第6章 指针(6)编程的练习:查找字符

1.编写一个函数&#xff0c;它在一个字符串中进行搜索&#xff0c;查找在一个给定字符集合中出现的所有字符。这个函数的原型如下&#xff1a; char *find_char( char const *source, char const *chars ); 它的基本想法是查找source字符串中匹配chars字符串中任何字符的第1个…

软件是什么?前端,后端,数据库

软件是什么&#xff1f; 由于很多东西没有实际接触&#xff0c;很难理解&#xff0c;对于软件的定义也是各种各样。但是我还是不理解&#xff0c;软件开发中的前端&#xff0c;后端&#xff0c;数据库到底有什么关系呢&#xff01; 这个问题足足困扰了三年半&#xff0c;练习时…

Facebook营销避免封号秘诀

随着数字营销的崛起&#xff0c;Facebook成为企业推广的重要平台。然而&#xff0c;在使用Facebook进行营销时&#xff0c;不少企业面临封号的风险。本文将分享一些避免封号的秘诀&#xff0c;帮助您在Facebook上安全地进行营销活动。 一、遵循Facebook规定 在进行Facebook营…

VUE 中的 v-for 和 v-if 是否可以共存

VUE 中的 v-for 和 v-if 是否可以共存 前言1、面试经2、正确回答3、总结总结&#xff1a; 前言 要成功&#xff0c;先发疯&#xff0c;头脑简单往前冲&#xff01; 三金四银&#xff0c;金九银十&#xff0c;多学知识&#xff0c;也不能埋头苦干&#xff0c;要成功&#xff0c…

获取编译工具链默认的链接脚本

1、ld命令使用“–verbose”参数 命令&#xff1a;riscv64-linux-gnu-ld --verbose想使用自己的链接脚本&#xff0c;链接时使用“-T”指定