关键词不能为空

当前您在: 主页 > 英语 >

Linux 设备树详解

作者:高考题库网
来源:https://www.bjmy2z.cn/gaokao
2021-02-02 10:41
tags:

-

2021年2月2日发(作者:女伞)


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


社区 的牛人为什么又乖乖地听话了


?


你得首先理解

< br>Linux


设备驱动框架中一个非常好的设计:设备信息和驱动分离。

< p>


为了说明设备信息和驱动分离的概念,这里用一个简单的模拟代码来解释 :



【例


-1


】实现一个代码,把要使用的信息简单写死在代码中:



int add() /*


模拟驱动代码


*/



{



return 3+5; /*


模拟设备信息


*/



}



优点:简单



缺点:一旦加数和被加数发生变化就得改代码



改进设计如下:



【例


-2


】实现一个代码,把要使用的信息和操作代码分离开来:

< br>


struct dev{



int id;



int x;



int y;



}; /*


模拟设备信息结构


*/



strcut drv{



int id;



int (*add)(struct dev *info);



}; /*


模拟驱动结构


*/



int add(struct dev *info) /*


模拟驱动代码


*/



{



return info->x + info->y; /*


模拟设备信息


-

< br>通过参数传递进来


*/



}



struct drv drv = {



.id = 1,



.add = add,



};



/*


模 拟设备信息


*/



struct dev dev = {



.id = 1,



.x = 3,



.y = 5,



};



/*


模 拟总线初始化匹配设备信息和驱动代码


*/



int bus()



{



if( == ){



return (&dev);



}



...



}



优点:不管加数和被加数怎么变化 ,不需要修改代码,仅需要修改信息



缺点:结构比较复杂



那这个设备信息 和驱动分离的设计跟驱动有什么关系呢


?


熟悉硬件编程的同学都 知道,硬件一般的构


成可以使用下图简单表述:



操作外设的驱动代码逻辑,只要硬件是一样的,就不会变化。但是外设挂到不同的主机上,可能会


存在


I/O


地址的变化,

< br>如果有中断也是一样的,


中断号也可能不同。


这些


I/O


地址和中断号就是设备信息,


使用这些 信息来操作控制硬件的代码就是驱动。



如果采用【例


-1


】的设计方式,那么同一个硬件外设接到不同的主机,或是换了地址 线


/


中断线,设


备信息就变化了,得去 修改驱动。但是采用【例


-2


】的方式进行设计,问题就迎刃而 解:不管同样的外设


硬件接到哪里或是那个平台,


其驱动代码逻 辑并不需要改动,


而仅仅需要改变下设备信息,


主要的就是


I/O


地址和中断号。


< br>说了这么半天,跟引入设备树有什么关系呢


?


华清教学使 用的开发板


(A8/A9)


都使用


DM 9000


网卡芯


片。


DM9000


驱动是开源的,在主线内核源码中就有。我们每次基于


A8/A9< /p>


板子移植的时候,


DM9000



动并没有修改过,仅仅是选配了下,主要的工作是在板级文件中添加了设备信息。


DM9000


驱动使用的是


platform


框架,所以添加了一份


DM9000


网卡芯片 的


platform_device


信息。问题来了,如果使用


C


代码


的形式来描述设备信息,则在内 核源码中,将会有多份


DM9000



platform_device


设备信息,造成了内


核代码冗 余。



解决这个问题的办法就是引入设备树,改造【例


-2


】来说明设备树的作用。



【例


-3


】实现一个代码,不仅把要使用的信息和操作 代码分离开来,而且信息不是


C


代码编写的,

< br>而是文本配置文件保存的:



struct dev{



int id;



int x;



int y;



}; /*


模拟设备信息结构


*/



strcut drv{



int id;



int (*add)(struct dev *info);



}; /*


模拟驱动结构


*/



int add(struct dev *info) /*


模拟驱动代码


*/



{



return info->x + info->y; /*


模拟设备信息


-

< br>通过参数传递进来


*/



}



struct drv drv = {



.id = 1,



.add = add,



};



/*


模 拟设备树


-


一个特殊的配置文件,



的文本文件


*/



/{



......



Dm9000{



x = 3;



y = 5;



};



......



};



/*


模 拟总线初始化匹配设备信息和驱动代码


*/



int bus()



{



/*


模拟 设备树初始化处理


*/



读文件


();



解析文件内容


(


根据设备树的规则来解析

);



生成


struct dev


设备信息


;



if( == ){



return (&dev);



}



...



}



如果像【例


-3


】这样,就可以解决大 量设备信息的代码冗余问题。



推而广之,系统的软硬件信息都 可以使用设备树来描述。这样的话,


ARM Linux


社区就 不会因为支


持板子和驱动越来越多造成内核源码中出现很多冗余代码

(


主要是板级文件


)


,仅仅需要移 植者,把系统的


软硬件信息通过设备树提供出来,选配一下内核代码,就可以了。



2


、设备树的概述



2.1


、参考资料


< br>内核源码目录


Documentationdevicetree


设备树说明文档



内核源码


d rivers/of/


源码分析



2.2


、基本概念


< br>设备树是描述软


/


硬件信息的,包含节点和属性的一个树 形结构。节点用以归类描述了一个硬件信息


或是软件信息


(


好比文件系统的目录


)


。节点内描述了一个 或多个属性,属性是键值对,描述具体的软


/


硬信


息。简单形式如下:



/{



node{



property=value;



...



child_node{



child_property=value;



...



};



...



};



...



};



说明如下:



/


:根节点,节点使用


“{};”


的语法描述作用范围



node


:根节点下的一个子节点


< /p>


child_node



node


节点下的一个子节点



property



node


节点内描述的属性,

< p>
value


就是属性的值


(


任意字节数据,可以是整型、字符串、数


组、等等


)


。描述行以


“;”


结束



2.3


、存储形式



在《


ARM Linux


社区为什么要 引入设备树》中,已经讨论过设备树的使用方式。简而言之:内核初


始化时,以配置的文 件形式读取设备树文件的内容,并解析后生成相应的软


/


硬件信 息,以供相应的内核代


码使用。



编写 设备树文件是以


.dts


的文本文件存储的,主要是为了修改、 添加编辑方便。



那么问题来了,如果纯文本解析的话,显然比 较慢且麻烦。譬如如果属性值是一个


I/O


地址:


0x80000000


,如果是字符串的形式存储,那么

“0x80000000”


就是一个字符串,内核代码解析这个信息的


时候还得转换成整型数,不仅仅是慢,无形设备树文件大小还会增加不少,还得增加更多的初始化代码 。



所以


.dts

的设备树文件,


在内核使用前需要转换一次,


主要是把繁复 的语法形式及属性值转换成字节


数据


(


特殊的数据结构


)


,而非符号。


.dt s


文件转换后是


.dtb


的二进制文件 。



3


、节点



3.1


、命名



节点的命名以字母、数字、


_


、等等符号构成。常见的命令方 式如下:



A


、以


设备名



为节点名,范例:



DM9000


命名如下:



/{



...



dm9000{



...



};



...



};



B


、以



设备


@I/O


地址





节点名


@I/O


地址



,范例:


< p>
DM9000


在主机端的


I/O

< br>地址为


0x8000 0000


,可以命名如下:



/{



...



dm9000@80000000{



...



};



...



};



C


、以



设备 类型


@I/O


地址


< br>为



节点名


@I/O

< p>
地址



,范例:



DM9000


在主机端的


I/O


地址为


0x8000 0000


,可以命名如下:



/{



...



ethernet@80000000{



...



};



...



};



3.2


、节点路径



A




/{



...



dm9000{



...



};



...



};



节点名:


dm9000



节点路径:


/dm9000



B




/{



...



dm9000@80000000{



...



};



...



};



节点名:


dm9000



节点路径:


/dm9000@80000000



C




/{



...



ethernet@80000000{



...



};



...



};


-


-


-


-


-


-


-


-



本文更新与2021-02-02 10:41,由作者提供,不代表本网站立场,转载请注明出处:https://www.bjmy2z.cn/gaokao/599080.html

Linux 设备树详解的相关文章