ImageVerifierCode 换一换
格式:DOCX , 页数:14 ,大小:18.36KB ,
资源ID:4153826      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/4153826.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(Linux设备树详解.docx)为本站会员(b****4)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

Linux设备树详解.docx

1、Linux设备树详解1、ARM Linux社区为什么要引入设备树Linux之父Linus Torvalds闲来无事,在翻看ARM Linux代码的时候,有一天终于忍不住了。他在2011年3月17日的ARM Linux邮件列表中说道:“This whole ARM thing is a f*cking pain in the ass”。这句话迫使ARM Linux社区引入了设备树。Linus Torvalds为什么会发飙呢?而ARM Linux社区的牛人为什么又乖乖地听话了?你得首先理解Linux设备驱动框架中一个非常好的设计:设备信息和驱动分离。为了说明设备信息和驱动分离的概念,这里用一个简单

2、的模拟代码来解释:【例-1】实现一个代码,把要使用的信息简单写死在代码中:int add() /*模拟驱动代码*/return 3+5; /*模拟设备信息*/优点:简单缺点:一旦加数和被加数发生变化就得改代码改进设计如下:【例-2】实现一个代码,把要使用的信息和操作代码分离开来:struct devint id;int x;int y; /*模拟设备信息结构*/strcut drvint id;int (*add)(struct dev *info); /*模拟驱动结构*/int add(struct dev *info) /*模拟驱动代码*/return info-x + info-y; /

3、*模拟设备信息-通过参数传递进来*/struct drv drv = .id = 1,.add = add,;/*模拟设备信息*/struct dev dev = .id = 1,.x = 3,.y = 5,;/*模拟总线初始化匹配设备信息和驱动代码*/int bus()if(dev.id = drv.id)return drv.add(&dev);.优点:不管加数和被加数怎么变化,不需要修改代码,仅需要修改信息缺点:结构比较复杂那这个设备信息和驱动分离的设计跟驱动有什么关系呢?熟悉硬件编程的同学都知道,硬件一般的构成可以使用下图简单表述:操作外设的驱动代码逻辑,只要硬件是一样的,就不会变化。

4、但是外设挂到不同的主机上,可能会存在I/O地址的变化,如果有中断也是一样的,中断号也可能不同。这些I/O地址和中断号就是设备信息,使用这些信息来操作控制硬件的代码就是驱动。如果采用【例-1】的设计方式,那么同一个硬件外设接到不同的主机,或是换了地址线/中断线,设备信息就变化了,得去修改驱动。但是采用【例-2】的方式进行设计,问题就迎刃而解:不管同样的外设硬件接到哪里或是那个平台,其驱动代码逻辑并不需要改动,而仅仅需要改变下设备信息,主要的就是I/O地址和中断号。说了这么半天,跟引入设备树有什么关系呢?华清教学使用的开发板(A8/A9)都使用DM9000网卡芯片。DM9000驱动是开源的,在主线

5、内核源码中就有。我们每次基于A8/A9板子移植的时候,DM9000驱动并没有修改过,仅仅是选配了下,主要的工作是在板级文件中添加了设备信息。DM9000驱动使用的是platform框架,所以添加了一份DM9000网卡芯片的platform_device信息。问题来了,如果使用C代码的形式来描述设备信息,则在内核源码中,将会有多份DM9000的platform_device设备信息,造成了内核代码冗余。解决这个问题的办法就是引入设备树,改造【例-2】来说明设备树的作用。【例-3】实现一个代码,不仅把要使用的信息和操作代码分离开来,而且信息不是C代码编写的,而是文本配置文件保存的:struct d

6、evint id;int x;int y; /*模拟设备信息结构*/strcut drvint id;int (*add)(struct dev *info); /*模拟驱动结构*/int add(struct dev *info) /*模拟驱动代码*/return info-x + info-y; /*模拟设备信息-通过参数传递进来*/struct drv drv = .id = 1,.add = add,;/*模拟设备树-一个特殊的配置文件,xxx.dtbs的文本文件*/.Dm9000x = 3;y = 5;.;/*模拟总线初始化匹配设备信息和驱动代码*/int bus()/*模拟设备树初

7、始化处理*/读文件(xxx.dtbs);解析文件内容(根据设备树的规则来解析);生成struct dev设备信息;if(dev.id = drv.id)return drv.add(&dev);.如果像【例-3】这样,就可以解决大量设备信息的代码冗余问题。推而广之,系统的软硬件信息都可以使用设备树来描述。这样的话,ARM Linux社区就不会因为支持板子和驱动越来越多造成内核源码中出现很多冗余代码(主要是板级文件),仅仅需要移植者,把系统的软硬件信息通过设备树提供出来,选配一下内核代码,就可以了。2、设备树的概述2.1、参考资料内核源码目录Documentationdevicetree设备树说

8、明文档内核源码drivers/of/源码分析2.2、基本概念设备树是描述软/硬件信息的,包含节点和属性的一个树形结构。节点用以归类描述了一个硬件信息或是软件信息(好比文件系统的目录)。节点内描述了一个或多个属性,属性是键值对,描述具体的软/硬信息。简单形式如下:/nodeproperty=value;.child_nodechild_property=value;.;.;.;说明如下:/:根节点,节点使用“;”的语法描述作用范围node:根节点下的一个子节点child_node:node节点下的一个子节点property:node节点内描述的属性,value就是属性的值(任意字节数据,可以是整

9、型、字符串、数组、等等)。描述行以“;”结束2.3、存储形式在ARM Linux社区为什么要引入设备树中,已经讨论过设备树的使用方式。简而言之:内核初始化时,以配置的文件形式读取设备树文件的内容,并解析后生成相应的软/硬件信息,以供相应的内核代码使用。编写设备树文件是以.dts的文本文件存储的,主要是为了修改、添加编辑方便。那么问题来了,如果纯文本解析的话,显然比较慢且麻烦。譬如如果属性值是一个I/O地址:0x80000000,如果是字符串的形式存储,那么“0x80000000”就是一个字符串,内核代码解析这个信息的时候还得转换成整型数,不仅仅是慢,无形设备树文件大小还会增加不少,还得增加更多

10、的初始化代码。所以.dts的设备树文件,在内核使用前需要转换一次,主要是把繁复的语法形式及属性值转换成字节数据(特殊的数据结构),而非符号。.dts文件转换后是.dtb的二进制文件。3、节点3.1、命名节点的命名以字母、数字、_、等等符号构成。常见的命令方式如下:A、以“设备名”为节点名,范例:DM9000命名如下:/.dm9000.;.;B、以“设备I/O地址”为“节点名I/O地址”,范例:DM9000在主机端的I/O地址为0x8000 0000,可以命名如下:/.dm900080000000.;.;C、以“设备类型I/O地址”为“节点名I/O地址”,范例:DM9000在主机端的I/O地址为

11、0x8000 0000,可以命名如下:/.ethernet80000000.;.;3.2、节点路径A、/.dm9000.;.;节点名:dm9000节点路径:/dm9000B、/.dm900080000000.;.;节点名:dm9000节点路径:/dm900080000000C、/.ethernet80000000.;.;节点名:ethernet节点路径:/ethernet800000003.3、节点引用/aliases demo = &demo;.demo:demo80000000.;.;节点名:demo节点路径:/demo80000000引用路径:demo(等价/demo80000000,解

12、决路径名过程的问题)设备树中引用节点“/demo80000000”的范例:&demo.;3.4、节点查找有时候,分享内核代码或是编写内核代码的时候,可能会涉及使用查找节点函数。内核提供很多内核函数来查找(解析设备树)一个指定节点:A、路径查找/* 功能:通过路径查找指定节点* 参数:* const char *path - 节点路径,可以是路径,也可以是路径引用* 返回值:* 成功:得到节点对象的首地址;失败:NULL*/struct device_node *of_find_node_by_path(const char *path);B、节点名查找/* 功能:通过节点名查找指定节点* 参数

13、:* struct device_node *from - 指向开始路径的节点,如果为NULL,则从根节点开始* const char *name- 节点名* 返回值:* 成功:得到节点对象的首地址;失败:NULL*/struct device_node *of_find_node_by_name(struct device_node *from, const char *name);C、通过compatible属性查找/* 功能:通过compatible属性查找指定节点* 参数:* struct device_node *from - 指向开始路径的节点,如果为NULL,则从根节点开始* c

14、onst char *type - 节点类型,可以为NULL* const char *compat - 指向节点的compatible属性的值(字符串)的首地址* 返回值:* 成功:得到节点对象的首地址;失败:NULL*/struct device_node *of_find_compatible_node(struct device_node *from,const char *type, const char *compat);设备ID表结构struct of_device_id char name32; /*设备名*/char type32; /*设备类型*/char compatib

15、le128; /*用于与设备树compatible属性值匹配的字符串*/const void *data; /*私有数据*/;/* 功能:通过compatible属性查找指定节点* 参数:* 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, ,;* 返回值:* 成

16、功:得到节点对象的首地址;失败:NULL*/struct device_node *of_find_matching_node(struct device_node *from,const struct of_device_id *matches);D、查找子节点/* 功能:查找指定节点的子节点* 参数:* const struct device_node *node - 指向要查找子节点的父节点* const char *name - 子节点名* 返回值:* 成功:得到子节点对象的首地址;失败:NULL*/struct device_node *of_get_child_by_name(co

17、nst struct device_node *node,const char *name);3.5、节点内容合并有时候,一个硬件设备的部分信息不会变化,但是部分信息是可能会变化的,就出现了节点内容合并。即:先编写好节点,仅仅描述部分属性值;使用者后加一部分属性值。在同级路径下,节点名相同的“两个”节点实际是一个节点。/*参考板的已经编写好的node节点*/nodeitem1=value;/*移植者添加的node节点*/nodeitem2=value;等价于:/nodeitem1=value;item2=value;3.6、节点内容替换有时候,一个硬件设备的部分属性信息可能会变化,但是设备树里

18、面已经描述了所有的属性值,使用者可以添加已有的属性值,以替换原有的属性值,就出现了节点内容替换。另外,节点的内容即使不会变化,但是可能不会使用。在同级路径下,节点名相同的“两个”节点实际是一个节点。内容替换的常见形式之一:/*参考板的已经编写好的node节点*/nodeitem=value1;/*移植者添加的node节点*/nodeitem=value2;等价于:/nodeitem=value2;内容替换的常见形式之二:/*参考板的已经编写好的node节点*/nodeitem=value;status = disabled;/*移植者添加的node节点*/nodestatus = okay;等

19、价于:/nodeitem=value;status = okay;3.7、节点内容引用有时候,一个节点需要使用到别的节点的属性值,就需要引用的概念。有时候在设备树编写时,要替换节点属性值,或是合并节点的属性值,也会使用引用。A、引用节点完成属性值的替换及合并:/*参考板的已经编写好的node节点*/node:node80000000item1=value;status = disabled;/*移植者添加的node节点*/&nodeitem2=value;status = okay;等价于:/node : node80000000item1=value;item2=value;status = okay;B、节点引用另一个节点:/*参考板的已经编写好的node节点*/node:node80000000item=value;/*移植者添加的demo节点*/demoitem=;说明:demo节点的属性item引用了节点的node的属性值,具体怎么使用node节点的属性值,在属性章节进行讨论。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1