我所认知的LINUX设备树_第1页
我所认知的LINUX设备树_第2页
我所认知的LINUX设备树_第3页
我所认知的LINUX设备树_第4页
我所认知的LINUX设备树_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、 For Internal Only 设备树(Device tree)是一套用来描述硬件属相的规则.设备树是从软件使用的角度描述硬件的,不是从硬件设计的角度描述的。我们在写设备树时没有必要按照硬件逻辑生搬硬套,也不要指望通过阅读设备树弄清楚硬件是如何设计的。对于软件可以自动识别的硬件,如USB设备,PCI设备,也是没有必要通过设备树描述的。我个人觉得规范内容是可以分为两个层次的。第一层是关于设备树组织形式的,如设备树结构,节点名字的构成等,第一个层次是基础,是理解第二个层次的前提。第二层是关于设备树内容的,如多核CPU怎样描述,一个具体的设备如何描述。第二层可以看成是第一层的具体应用。DTS(

2、Device tree syntax,另一种说法是Device tree source)是设备树源文件,为了方便阅读及修改,采用文本格式。DTC(Device tree compiler)是一个小工具,负责将DTS转换成DTB(Device tree blob)。设备树首先是一个树形结构,并且是一棵树。除了根节点外其他子节点都有唯一的父节点,节点下可以有子节点和属性(子节点可以看成是树枝,属性可以看成是叶子)。属性由名字和值组成(名字是必须的,但是值不是必须的,如果只要根据是否存在这个属性就可以表示我们想要的功能,那么可以不需要有值)。节点(node)的表示首先说节点的表示方法,除了根节点只用

3、一个斜杠“/”表示外,其他节点的表示形式如“node-nameunit-address”。前边是节点名字,后边是节点地址。节点地址是用来区别同名节点的,不是软件意义上的地址,但是有些情况可以用软件地址作为这个地址。除此之外规范还要求,如果节点有地址,那么节点下边必须有一个叫reg的属性,并且该地址必须和reg的属性的第一个地址相同。如果节点没有reg属性,那么节点地址及前边的必须都不能有。除了名字和地址外,节点前边还可以有一个标签(label),这个标签不是必须的,一般只有在别个地方需要引用这个节点时才会用标签标示这个节点,因为如果用全路径太繁琐了。如“i2c_1: i2c12C70000”中

4、的i2c_1就是一个标签。属性(property)属性的值在内存中由0个或多个字节存储。标准定义的基本类型包括:空,u32,u64,字符串,<prop-encoded-array>,字符数组6种。标准的属性:“compatible”属性是用来匹配驱动的,他的类型是字符串数组,每个字符串表示一种设备的类型,从具体到一般。"model"属性用来表示设备的型号,用字符串表示,不像"compatible"用多个字符串,只需一个就够了。"device_type"属性用来表示设备类型,用字符串表示。"#address-cel

5、ls","#size-cells","reg","ranges","dma-ranges"属性都是和地址有关的。不同的平台,不同的总线,地址位长度可能不同,有32位地址"#address-cells"属性用来表示总线地址需要几个cell表示,该属性本身是u32类型的。"#size-cells"属性用来表示子总线地址空间的长度需要几个cell表示,属性本身的类型也是u32。,有64位地址,为了适应这个,规范规定一个32位的长度为一个cell。可以这么理解父节点表示总线

6、,总线上每个设备的地址长度以及地址范围是总线的一个特性,用"#address-cells","#size-cells"属性表示,比如总线是32位,那么"#address-cells"设置成1就可以了。这两个属性不可以继承,就是说在未定义这两个属性的时候,不会继承更高一级父节点的设置,如果没有设置的话,内核默认认为"#address-cells"为2,"#size-cells"为1。"reg"属性用来表示节点地址资源的,比如常见的就是寄存器的起始地址及大小。要想表示一块连续地址

7、,必须包含起始地址和空间大小两个参数,如果有多块地址,那么就需要多组这样的值表示。还记得前边说过的<prop-encoded-array>类型的属性吧,就是用来干这个的,他表示一个数组,每个元素的具体格式根据属性而定,对于'reg'属性,每个元素是一个二元组,包含起始地址和大小。还有另外一个问题,地址和大小用几个u32表示呢?这个就由父节点的"#address-cells","#size-cells"属性确定。总线上设备在总线地址和总线本身的地址可能不同,"ranges"属性用来表示如何转换。和'r

8、eg'属性类似,'ranges'属性也是<prop-encoded-array>类型的属性,不同的是'ranges'属性的每个元素是三元组,按照前后顺序分别是(子总线地址,父总线地址,大小)。子总线地址需要几个u32表示由'ranges'属性所在节点的'#address-cells'属性决定,父总线地址需要几个u32表示由上一级节点的'#address-cells'属性决定,大小需要几个u32表示由当前节点的'#size-cells'属性确定。'dma-ranges

9、9;属性的结构和定义与'ranges'属性完全相同,唯一不同的是地址是dma使用的地址,'ranges'中的地址是cpu使用的地址。有的时候在一个节点中需要引用另外一个节点,比如某个外设的中断连在哪个中断控制器上。在讲节点那一节我们说过,可以通过节点的全路径指定是哪个节点,但这种方法非常繁琐。'phandle'属性是专门为方便引用节点设计的,想要引用哪个节点就在该节点下边增加一个'phandle'属性,设定值为一个u32,如'phandle = <1>',引用的地方直接使用数字1就可以引用该节点,如&#

10、39;interrupt-parent = <1>'。以上是规范中描述的方法,实际上这样也不方便,我在实际的代码中没有看到这么用的。还记得节点那节说过节点名字前边可以定义一个标签吧,实际情况是都用标签引用,比如节点标签为intc1,那么用'interrupt-parent = <&intc1>'就可以引用了。'status'属性用来表示节点的状态的,其实就是硬件的状态,用字符串表示。'okay'表示硬件正常工作,“disabled”表示硬件当前不可用,“fail”表示因为出错不可用,“fail-sss”表示

11、因为某种原因出错不可用,sss表示具体的出错原因。实际中,基本只用'okay'和'disabled'。中断中断一般包括中断产生设备和中断处理设备。中断控制器负责处理中断,每一个中断都有对应的中断号及触发条件。中断产生设备可能有多个中断源,有时多个中断源对应中断控制器中的一个中断,这种情况中断产生设备的中断源称之为中断控制器中对应中断的子中断。中断产生设备用interrupts属性描述中断源(interrupt specifier),因为不同的硬件描述中断源需要的数据量不同,所以interrupts属性的类型也是<prop-encoded-array>

12、。为了明确表示一个中断由几个u32表示,又引入了#interrupt-cells属性,#interrupt-cells属性的类型是u32,假如一个中断源需要2个u32表示(一个表示中断号,另一个表示中断类型),那么#interrupt-cells就设置成2。interrupt-parent属性的类型是<phandle>,用来引用中断父节点(我们前边说过,一般用父节点的标签,这个地方说中断父节点而不是中断控制器是有原因的)。如果设备树的父节点就是中断父节点,那么可以不用设置interrupt-parent属性。interrupts属性和interrupt-parent属性都是中断产生

13、设备节点的属性,但是#interrupt-cells属性不是,#interrupt-cells属性是中断控制器节点以及interrupt nexus节点的属性,这两类节点都可能是中断父节点。中断控制器节点用interrupt-controller属性表示自己是中断控制器,这个属性的类型是空,不用设置值,只要存在这个节点就表示该节点是中断控制器。除了这个属性外,中断控制器节点还有#interrupt-cells属性,用来表示该中断控制器直接管理下的interrupt domain(后边我们会讲中断控制器的中断子节点interrupt nexus节点有单独的interrupt domain)用几个

14、u32表示一个中断源(interrupt specifier)。interrupt nexus节点就是描述中断映射关系的(中断控制器中的一个中断可能对应中断产生设备中的多个中断源),该节点通过interrupt-map,interrupt-map-mask属性描述中断映射关系。interrupt-map属性是<prop-encoded-array>类型的,每个元素表示一个中断映射关系(注意是一个"中断映射关系",不是"一个中断"映射关系),从前向后包括:中断子设备地址,中断子设备中断源(interrupt specifier),中断父设备,中

15、断父设备地址,中断父设备中断源(interrupt specifier)五部分。中断父设备地址具体由几个u32组成是由中断父设备节点下的#address-cells属性决定的(注意,不是中断父设备所在总线的#address-cells属性)。中断父设备中断源(interrupt specifier)由几个u32组成是由中断父设备的#interrupt-cells属性决定的。为了让多个子中断共享映射关系,引入了interrupt-map-mask属性,该属性的类型也是<prop-enacoded-array>,包含中断子设备地址和中断子设备中断源的bit mask,给定一个子中断源,

16、那么首先和interrupt-map-mask做与运算,运算结果再通过interrupt-map属性查找对应的中断父设备中断源。这就是我们前边为什么说interrupt-map属性的一行是一个“中断映射关系”,而不是“一个中断”映射关系的原因。整个中断树的最底层是中断产生设备(也可能是从interrupt nexus节点),中断产生设备用interrupts属性描述他能产生的中断。他的中断父设备可能是中断控制器(如果中断产生设备的中断和中断控制器的中断是一一对应的,或者最底层是interrupt nexus节点),也可能是interrupt nexus节点(如果最底层是中断产生设备,且需要映射

17、).interrupt nexus节点及他的所有直接子节点构成了一个interrupt domain,在该interrupt domain下中断源怎样表示由#interrupt-cells属性决定,如何由中断子设备中断源找到中断父设备中断源由interrupt-map和interrupt-map-mask属性决定。interrupt nexus的父节点可能还是一个interrupt nexus父节点,也可能是一个中断控制器,当向上找到最后一个中断控制器,并且该中断控制器再也没有中断父设备时,整个中断树就遍历完成了。中断控制器用interrupt-controller属性表示自己是中断控制器,并

18、且用#interrupt-cells属性表示他所直接管理的interrupt domain用几个u32表示一个中断源。根据中断树的特性,一个设备树中是有可能有多个中断树的。例子:/ model = "Marvell Armada 375 family SoC" compatible = "marvell,armada375" soc #address-cells = <2> #size-cells = <1> interrupt-parent = <&gic> internal-regs compatible

19、= "simple-bus" #address-cells = <1> #size-cells = <1> timerc600 compatible = "arm,cortex-a9-twd-timer" reg = <0xc600 0x20> interrupts = <GIC_PPI 13 (IRQ_TYPE_EDGE_RISING | GIC_CPU_MASK_SIMPLE(2)> clocks = <&coreclk 2> ; gic: interrupt-controllerd

20、000 compatible = "arm,cortex-a9-gic" #interrupt-cells = <3> #address-cells = <0> interrupt-controller; reg = <0xd000 0x1000>, <0xc100 0x100> ; pcie-controller compatible = "marvell,armada-370-pcie" #address-cells = <3> #size-cells = <2> pcie1,0

21、 #address-cells = <3> #size-cells = <2> #interrupt-cells = <1> interrupt-map-mask = <0 0 0 0> interrupt-map = <0 0 0 0 &gic GIC_SPI 29 IRQ_TYPE_LEVEL_HIGH> ; ;首先我们看到timerc600这个设备节点下定义了interrupts属性,这说明该设备可以产生中断,但是这个属性下描述了几个中断我们是看不出来的(如果有经验了,我们能猜出只是一个中断,现在我们按照规则确认)。因为

22、该节点没有interrupt-parent属性,那么认为设备树的父节点internal-regs就是中断父节点,在internal-regs父节点下还是没有interrupt-parent属性,那么还是继续找设备树父节点,找到了soc,在该节点下边有interrupt-parent属性。该属性引用的标签为gic,搜索整个设备树,interrupt-controllerd000的标签为gic。gic节点下有interrupt-controller属性,说明他是一个中断控制器。gic节点还有属性#interrupt-cells = <3>,说明在该控制器的interrupt domain下,中断源(interrupt specifier)用3个u32表示,我们再看timerc600下的interrupts属性也确实由3个u32组成(可以参考GIC的规范,第一个u32表示中断类型,第二个是中断号,第三个是中断触发条件)。这个例子说明如果中断产生设备的中断源和中断控制器的中断源是一一对应的,那么可以不需要interrupt nexus节点及相关的属性来表示中断映射。再看pcie1,0这个节点,有#interrupt-cells属性,但是没有interrupt-controller属性,这说明他是一个interrupt nexus节点。该节点的#interrupt-cells

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论