糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > Linux 驱动开发 十:《Devicetree Specification》翻译

Linux 驱动开发 十:《Devicetree Specification》翻译

时间:2023-08-24 20:54:46

相关推荐

Linux 驱动开发 十:《Devicetree Specification》翻译

一、设备树

1、概述

DTSpec指定了一个称为设备树结构描述系统硬件引导程序将设备树加载到客户端程序内存中,并将指向设备树的指针传递给客户端。

本章描述了设备树逻辑结构,并指定了一组用于描述设备节点的基本属性。第 3 章指定了符合DTSpec的设备树所需的某些设备节点。第 4 章描述了DTSpec定义的设备绑定- 表示某些设备类型或设备类别的要求。第 5 章描述了设备树的内存编码

设备树是一种树数据结构,其节点描述系统中的设备。每个节点都有描述所代表设备特性属性/值对。除了没有父节点的根节点之外,每个节点都只有一个父节点。

符合DTSpec设备树描述了系统中的设备信息,客户端程序不一定能动态检测到这些信息。例如,PCI体系结构使客户端能够探测检测连接的设备,因此可能不需要描述PCI设备的设备树节点。但是,如果无法通过探测检测到,则需要设备节点来描述系统中的PCI主桥设备。

1、Example

图 2.1 显示了一个简单设备树示例表示,它几乎足以启动一个简单的操作系统,其中描述了平台类型CPU内存单个UART设备节点与每个节点内的属性和值一起显示。

2、设备树结构和约定

1、节点名称

节点名称要求

设备树中的每个节点都根据以下约定命名:

node-name@unit-address

node-name组件指定节点的名称。它的长度应为131个字符,并且仅由来自表2.1中字符集的字符组成。

节点名称应以小写大写字符开头,并应描述设备的一般类别。

名称的单元地址部分特定节点所在的总线类型。它由表 2.1 中字符集中的一个或多个ASCII字符组成。

unit-address必须节点reg属性指定第一个地址相匹配。如果节点没有reg属性@unit-address必须被省略,节点名称单独区分节点与树中同一级别的其他节点。特定总线的绑定可以为reg格式单元地址指定额外的更具体要求

根节点没有节点名单元地址。它由正斜杠 (/) 标识。

名为cpu的节点通过它们的单元地址值01来区分。名称为ethernet的节点通过其单元地址值fe002000fe003000区分

2、通用名称建议

节点的名称应该有点通用反映设备的功能不是其精确的编程模型。如果合适,名称应该是以下选项之一:

3、路径名称

设备树中的节点可以通过指定从根节点到所有后代节点到所需节点的完整路径唯一标识

指定设备路径的约定是:

/node-name-1/node-name-2/node-name-N

例如,在图 2.2 中,cpu #1 的设备路径为:

/cpus/cpu@1

根节点的路径是/

如果到节点的完整路径明确的,则可以省略单元地址

如果客户端程序遇到不明确的路径,则其行为未定义

4、属性

设备树中的每个节点都有描述节点特征属性。属性由名称组成。

1、属性名称

属性名称是表2.2中显示的字符中的131个字符的字符串

非标准属性名称应指定唯一字符串前缀,例如股票代码,以标识定义该属性的公司组织的名称。例子:

fsl,channel-fifo-len ibm,ppc-interrupt-server#s linux,network-index

2、属性值

属性值是包含与该属性相关联信息零个多个字节数组

如果传达真假信息属性可能具有空值。在这种情况下,属性的存在不存在是充分的描述。

表 2.3 描述了DTSpec定义的一组基本值类型

1、empty

值为。当属性本身存在不存在具有足够的描述性时,用于传达真假信息

2、u32

大端格式32位整数

示例:32位值0x11223344在内存中表示为:

address 11 address+1 22 address+2 33 address+3 44

3、u64

表示大端格式64位整数。由两个值组成,其中第一个值包含整数的最高有效位第二个值包含最低有效位

示例:640x1122334455667788将表示为两个单元格<0x11223344 0x55667788>

该值将在内存中表示为:

address 11 address+1 22 address+2 33 address+3 44 address+4 55 address+5 66 address+6 77 address+7 88

4、string

字符串是可打印的并且以空值结尾

示例:字符串“hello”将在内存中表示为:

address 68 'h' address+1 65 'e' address+2 6C 'l' address+3 6C 'l' address+4 6F 'o' address+5 00 '\0'

5、prop-encoded-array

格式特定属性。请参阅属性定义。

6、phandle

一个< u32 >值。phandle值是一种引用设备树中另一个节点的方法。任何可以被引用的节点都定义了一个具有唯一< u32 >值的phandle属性。该数字用于具有phandle值类型的属性值。

7、stringlist

连接在一起的< string >值列表。

示例:字符串列表“hello”“world”将在内存中表示为:

address 68 'h' address+1 65 'e' address+2 6C 'l' address+3 6C 'l' address+4 6F 'o' address+5 00 '\0' address+6 77 'w' address+7 6f 'o' address+8 72 'r' address+9 6C 'l' address+10 64 'd' address+11 00 '\0'

3、标准属性

DTSpec为设备节点指定了一组标准属性。本节详细介绍了这些属性。DTSpec定义的设备节点(见第3章)可以指定有关标准属性使用的附加要求或约束

4章描述了特定设备的表示,也可能规定了附加要求

注意:本文档中的所有设备树节点示例都使用DTS设备树源格式指定节点和属性。

1、compatible(兼容)

1、属性名称

compatible

2、值类型

< stringlist >

3、描述

兼容属性值由一个多个定义设备特定编程模型字符串组成客户端程序应使用此字符串列表选择设备驱动程序。属性值由空终止字符串的串联列表组成,从最具体到最一般。它们允许设备表达其与一系列类似设备的兼容性,可能允许单个设备驱动程序匹配多个设备。

4、例子

compatible = "fsl,mpc8641", "ns16550";

在此示例中,操作系统将首先尝试定位支持fsl,mpc8641 的设备驱动程序。如果未找到驱动程序,它将尝试定位支持更通用的ns16550设备类型的驱动程序

2、model(模型)

1、属性名称

model

2、值类型

< string >

3、描述

模型属性值是一个string,用于指定设备的制造商型号。

推荐的格式是:“manufacturer,model”,其中manufacturer是描述制造商名称的字符串(例如股票代码),model指定型号

4、例子

model = "fsl,MPC8349EMITX";

3、phandle()

1、属性名称

phandle

2、值类型

< u32 >

3、描述

phandle属性指定一个在设备树唯一节点数字标识符phandle属性值由需要引用与该属性关联的节点其他节点使用。

4、例子

请参阅以下设备树摘录:

pic@10000000 { phandle = <1>; interrupt-controller;};

phandle值定义为 1。另一个设备节点可以使用phandle值为1引用pic节点

another-device-node { interrupt-parent = <1>;};

注意:可能会遇到旧版本设备树,其中包含称为linuxphandle的此属性的弃用形式。为了兼容性,如果phandle属性不存在,客户端程序可能希望支持linuxphandle。这两个属性的含义和用途是相同的

注意DTS中的大多数设备树(参见附录 A)将不包含显式的phandle属性DTC工具在将DTS编译为二进制DTB格式时会自动插入phandle属性。

4、status(状态)

1、属性名称

status

2、值类型

< string >

3、描述

status属性指示设备的操作状态。有效值在表2.4中列出和定义。

1、okay

表示设备正在运行

2、disabled

表示设备当前无法运行,但将来可能会运行(例如,某些设备未插入或关闭)。

有关禁用对给定设备的含义的详细信息,请参阅设备绑定

3、reserved

表示设备可运行,但不应使用。通常用于由其他软件组件(如平台固件)控制的设备。

4、fail

表示设备未运行。在设备中检测到严重错误,如果不修复它不太可能投入使用。

5、fail-sss

表示设备未运行。在设备中检测到严重错误,如果不修理它不太可能投入使用。该值的 sss 部分特定于设备并指示检测到的错误条件。

5、#address-cells and #size-cells(地址单元和大小单元)

1、属性名称

#address-cells, #size-cells

2、值类型

< u32 >

3、描述

#address-cells#size-cells属性可用于在设备树层次结构中具有子设备的任何设备节点,并描述子设备节点应如何寻址

#address-cells属性定义了用于对子节点reg属性中的地址字段进行编码< u32 >单元格的数量

#size-cells属性定义了用于对子节点reg属性中的大小字段进行编码的< u32 >单元格的数量

符合DTSpec引导程序应在所有具有子节点的节点上提供#address-cells#size-cells

如果丢失,客户端程序应假定#address-cells默认值为**2#size-cells1**。

4、例子

请参阅以下设备树摘录:

soc {#address-cells = <1>; #size-cells = <1>;serial@4600 { compatible = "ns16550"; reg = <0x4600 0x100>; clock-frequency = <0>; interrupts = <0xA 0x8>; interrupt-parent = <&ipic>;}; };

在此示例中,soc节点的**#address-cells** 和**#size-cells** 属性均设置为**1。此设置指定需要一个单元格来表示地址**,并且需要一个单元格来表示节点的大小是这个节点的孩子。

串行设备reg属性必须遵循在父节点中设置的此规范——地址单个单元格(0x4600) 表示,大小单个单元格(0x100) 表示。

6、reg()

1、属性名称

reg

2、属性值

< prop-encoded-array >编码为任意数量的(地址,长度)对。

3、描述

reg 属性描述了设备资源在其父总线定义地址空间内地址最常见的是,这意味着内存映射IO寄存器块偏移量长度,但在某些总线类型可能具有不同的含义

该值是一个< prop-encoded-array >,由任意数量地址长度组成,< address length >

指定地址长度所需的< u32 >单元的数量特定总线的,并且由设备节点的父节点中的#address-cells#size-cells属性指定。

如果父节点#size-cells指定值为**0,则应省略reg中的长度字段**。

4、例子

假设片上系统中的设备有两个寄存器块SOC中偏移0x3000处的32字节块和偏移0xFE00处的256字节块。

reg属性将编码如下(假设#address-cells#size-cells值为1):

reg = <0x3000 0x20 0xFE00 0x100>;

7、virtual-reg(虚拟-reg)

1、属性名称

virtual-reg

2、值类型

< u32 >

3、描述

virtual-reg属性指定一个有效地址,该地址映射到设备节点的reg属性中指定的第一个物理地址。此属性使引导程序能够为客户端程序提供已设置的虚拟到物理映射

8、ranges(范围)

1、属性名称

ranges

2、值类型

< empty>< prop-encoded-array>编码为任意数量的(子总线地址、父总线地址、长度)三元组

3、描述

Ranges属性提供了一种定义总线地址空间(子地址空间)和总线节点父节点地址空间(父地址空间)之间的映射转换的方法。

range属性值的格式是任意数量的 (child-bus-address, parentbus-address, length)

子总线地址是子总线地址空间内的物理地址。表示地址的单元格数量取决于总线,可以从该节点(出现range属性的节点)的#address-cells确定。父总线地址是父总线地址空间内的物理地址。表示父地址的单元数取决于总线,可以从定义父地址空间的节点的#address-cells属性确定。长度指定子地址空间范围的大小。表示大小的单元格数量可以从该节点(出现ranges属性的节点)的#size-cells确定。

如果属性定义为< empty>值,则它指定父子地址空间相同,不需要地址转换

如果该属性不存在于总线节点中,则假定节点的子节点与父地址空间之间不存在映射

4、例子

地址转换示例:

soc {compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe0000000 0x00100000>;serial@4600 { device_type = "serial"; compatible = "ns16550"; reg = <0x4600 0x100>; clock-frequency = <0>; interrupts = <0xA 0x8>; interrupt-parent = <&ipic>;}; };

soc节点指定了一个range属性

<0x0 0xe0000000 0x00100000>;

此属性值指定对于1024KB范围的地址空间,在物理0x0处寻址的子节点映射物理0xe0000000的父地址。

通过此映射,串行设备节点可以通过地址0xe0004600处的加载存储0x4600(在reg中指定)的偏移量加上范围中指定的0xe0000000映射来寻址。

9、dma-ranges

1、属性名称

dma-ranges

2、值类型

< empty>< prop-encoded-array>编码为任意数量的(子总线地址、父总线地址、长度)三元组

3、描述

dma-ranges属性用于描述内存映射总线直接内存访问(DMA)结构,可以从源自总线的DMA操作访问其设备树父级。它提供了一种定义总线物理地址空间总线父级物理地址空间之间的映射转换方法

dma-ranges属性值的格式是(子总线地址、父总线地址、长度)的任意数量三元组。指定的每个三元组描述了一个连续DMA地址范围

子总线地址是子总线地址空间内的物理地址。表示地址的单元格数量取决于总线,可以从该节点(出现dma-ranges属性的节点)的#address-cells确定。父总线地址是父总线地址空间内的物理地址。表示父地址的单元数取决于总线,可以从定义父地址空间的节点的#address-cells属性确定。长度指定子地址空间中范围的大小。表示大小的单元格数量可以从该节点(出现dma-ranges属性的节点)的#size-cells中确定。

4、例子

10、name (deprecated)

1、属性名称

name

2、值类型

< string >

3、描述

name属性是一个字符串,指定节点的名称。此属性已弃用,不推荐使用。但是,它可能用于较旧的不符合DTSpec的设备树。操作系统应该根据节点名称的节点名称组件来确定节点的名称(请参阅第2.2.1节)。

11、device_type (deprecated)

1、属性名称

device_type

2、值类型

< string >

3、描述

IEEE 1275中使用device_type属性来描述设备FCode编程模型。由于DTSpec没有FCode不推荐使用该属性的新用途,为了与IEEE 1275派生的设备树兼容,它应该只包含在cpu和内存节点上。

4、中断和中断映射

DTSpec采用Open Firmware Recommendation Practice: Interrupt Mapping, Version 0.9 [b7]中规定的表示中断中断树模型。在设备树中存在一个逻辑中断树,它表示平台硬件中断的层次结构和路由。虽然通常被称为中断树,但它在技术上更像是一个有向无环图

中断源中断控制器的物理连接在设备树中用interruptparent属性表示。代表中断生成设备的节点包含一个中断父属性,该属性具有一个phandle,该值指向设备的中断路由到的设备,通常是一个中断控制器。如果中断生成设备没有中断父级属性,则假定其中断父级为其设备树父级。

每个中断生成设备都包含一个**interrupts属性**,其中的值描述了该设备的一个多个中断源。每个源都用称为中断说明符的信息表示。中断说明符的格式含义特定于中断域的,即它依赖于其中断域根节点上的属性中断域的根使用#interrupt-cells属性来定义对中断说明符进行编码所需的< u32>值的数量。例如,对于Open PIC中断控制器,中断说明符采用两个32位值,由中断编号中断的级别/检测信息组成。

中断域解释中断说明符上下文域的根中断控制器中断关系。

1:中断控制器是:一个物理设备,需要一个驱动程序处理通过它路由的中断。它也可以级联到另一个中断域。中断控制器由设备树中该节点上的中断控制器属性的存在来指定。

2:中断关系定义了一个中断域另一个中断域之间的转换。转换基于特定于域特定于总线的信息。域之间的这种转换是通过中断映射属性执行的。例如,PCI控制器设备节点可以是一个中断关系,它定义了从PCI中断命名空间INTA、INTB等)到具有中断请求 (IRQ) 编号的中断控制器转换

中断树遍历到达没有中断属性中断控制器节点确定中断树的根,因此没有明确的中断父节点

有关显示中断父关系的设备树的图形表示示例,请参见图2.3。它显示了设备树的自然结构以及每个节点在逻辑中断树中的位置

在图2.3所示的例子中:

open-pic中断控制器是中断树的根。中断树的根有三个子节点——将中断直接路由到open-pic的设备device1PCI host controllerGPIO Controller存在三个中断域;一种根植于open-pic节点,一种根植于PCI主机桥节点,一种根植于GPIO控制器节点。有两个连接节点;一个在PCI主机桥上,一个在GPIO控制器上。

1、中断生成设备的属性

1、interrupts

1、属性

interrupts

2、值类型

< prop-encoded-array >编码为任意数量的中断说明符。

3、描述

设备节点的中断属性定义了设备产生一个或多个中断。中断属性的值由任意数量中断说明符组成。中断说明符的格式中断域根的绑定定义。

中断中断扩展属性覆盖,通常只应使用一个或另一个

4、例子

开放PIC兼容中断域中中断说明符常见定义两个单元组成中断号电平/检测信息。请参见以下示例,该示例定义了单个中断说明符中断编号0xA级别/检测编码8

interrupts = <0xA 8>;

2、interrupt-parent

1、属性

interrupt-parent

2、值类型

< phandle >

3、描述

由于中断树中节点的层次结构可能与设备树不匹配,因此可以使用中断父级属性明确定义中断父级。该值是中断父级的phandle。如果设备缺少此属性,则假定其中断父级为其设备树父级

3、interrupts-extended

1、属性

interrupts-extended

2、值类型

< phandle > < prop-encoded-array >

3、描述

interrupts-extended属性列出设备生成的中断。当设备连接到多个中断控制器时,应使用interrupts-extended而不是interrupts,因为它使用每个中断说明符对父phandle进行编码。

4、例子

此示例显示了具有连接两个独立中断控制器两个中断输出的设备将如何使用中断扩展属性描述连接pic是一个#interrupt-cells说明符为2的中断控制器,而gic是一个#interrupts-cells说明符为1的中断控制器

interrupts-extended = <&pic 0xA 8>, <&gic 0xda>;

中断中断扩展属性互斥的。设备节点应该使用一个或另一个,但不能同时使用两者。只有在需要与不理解中断扩展的软件兼容时才允许使用两者。如果两个中断扩展和存在中断,然后中断扩展优先

2、中断控制器的属性

1、#interrupt-cells

1、属性

#interrupt-cells

2、值类型

< u32 >

3、描述

#interrupt-cells属性定义为中断域编码中断说明符所需的单元数

2、interrupt-controller

1、属性

interrupt-controller

2、值类型

< empty >

3、描述

中断控制器属性的存在将节点定义为中断控制器节点

3、中断关系属性

一个中断关系节点应该有一个#interrupt-cells属性。

1、interrupt-map

1、属性

interrupt-map

2、值类型

< prop-encoded-array >编码为任意数量中断映射条目

3、描述

中断映射连接节点上的一个属性,它将一个中断域与一组父中断域连接起来,并指定子域中的中断说明符如何映射到它们各自的父域

中断映射是一张表,其中每一行都是一个映射条目,由五个部分组成子单元地址子中断说明符中断父父单元地址父中断说明符

child unit address

被映射子节点单元地址指定这一点所需的32位单元的数量子节点所在总线节点#address-cells属性描述。

child interrupt specifier

被映射子节点中断说明符。指定此组件所需的 32 位单元数由此节点的 #interrupt-cells 属性描述 - 包含中断映射属性的连接节点。

interrupt-parent

指向子域映射到的中断父级的单个< phandle >值。

parent unit address

中断父域中的单元地址。指定此地址所需的 32 位单元的数量由中断父字段指向的节点的#address-cells属性描述。

parent interrupt specifier

父域中的中断说明符。指定此组件所需的 32 位单元的数量由中断父字段指向的节点的#interrupt-cells属性描述。

通过将单元地址/中断说明符对与中断映射中的子组件进行匹配,在中断映射表上执行查找。由于单元中断说明符中的某些字段可能不相关,因此在完成查找之前应用掩码。这个掩码在interrupt-map-mask属性中定义(见2.4.3.2 节)。

注意子节点和中断父节点都需要定义#address-cells#interruptcells属性。如果不需要单元地址组件,#address-cells应明确定义为零。

2、interrupt-map-mask

1、属性

interrupt-map-mask

2、值类型

< prop-encoded-array >编码为位掩码

3、描述

中断树中的连接节点指定了中断映射掩码属性。此属性指定一个掩码,该掩码应用于在中断映射属性中指定的表查找的传入单元中断说明符

3、#interrupt-cells

1、属性

#interrupt-cells

2、值类型

< u32 >

3、描述

#interrupt-cells属性定义为中断域编码中断说明符所需的单元数

4、中断映射示例

下面显示了带有PCI总线控制器设备树片段的表示和用于描述两个PCI插槽IDSEL 0x11,0x12)的中断路由的示例中断映射。插槽12INTAINTBINTCINTD引脚连接到Open PIC中断控制器。

soc {compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>;open-pic {clock-frequency = <0>; interrupt-controller; /*中断控制器*/#address-cells = <0>; #interrupt-cells = <2>;}; pci {#interrupt-cells = <1>; #size-cells = <2>; #address-cells = <3>; interrupt-map-mask = <0xf800 0 0 7>; interrupt-map = < /* IDSEL 0x11 - PCI slot 1 */ 0x8800 0 0 1 &open-pic 2 1 /* INTA */ 0x8800 0 0 2 &open-pic 3 1 /* INTB */ 0x8800 0 0 3 &open-pic 4 1 /* INTC */ 0x8800 0 0 4 &open-pic 1 1 /* INTD */ /* IDSEL 0x12 - PCI slot 2 */ 0x9000 0 0 1 &open-pic 3 1 /* INTA */0x9000 0 0 2 &open-pic 4 1 /* INTB */ 0x9000 0 0 3 &open-pic 1 1 /* INTC */ 0x9000 0 0 4 &open-pic 2 1 /* INTD */>;}; };

一个Open PIC中断控制器被表示并被标识为具有中断控制器属性的中断控制器

中断映射表中的每一行由五部分组成:子单元地址中断说明符,它们映射到具有指定父单元地址中断说明符的中断父节点

例如,中断映射表第一行指定了插槽1INTA的映射。该行的组件如下所示

子单元地址:0x8800 0 0子中断说明符:1中断父母:&open-pic父母单位地址:(空,因为#address-cells = <0>open-pic节点)父中断说明符:2 1子单元地址为<0x8800 0 0>。该值由三个32位单元编码,由PCI控制器的#address-cells属性值(值为3)决定。这三个单元代表PCI地址,如PCI总线的绑定所描述的。 编码包括总线号(0x0 << 16)、设备号(0x11 << 11) 和功能号(0x0 << 8)。子中断说明符<1>,它指定了 PCI 绑定所描述的INTA。这需要一个由PCI控制器#interrupt-cells属性(值为1)指定的32位单元,它是子中断域中断父级由指向插槽的中断父级的phandle指定,即Open PIC中断控制器。父节点没有单元地址,因为父中断域(open-pic节点)的**#address-cells值为<0>**。父中断说明符<2 1>。表示中断说明符的单元格数(两个单元格)由中断父节点(open-pic节点)上的#interrupt-cells属性决定<2 1>是由设备绑定为Open PIC中断控制器指定的值(参见第4.5节)。<2>指定INTA连接到的中断控制器上的物理中断源编号<1>指定级别/感知编码

在此示例中,interrupt-map-mask属性的值为<0xf800 0 0 7>。在中断映射表中执行查找,此掩码应用于子单元中断说明符

要查找IDSEL 0x12(插槽2)、功能0x3INTBopen-pic中断源编号,将执行以下步骤

子单元地址中断说明符形成值<0x9300 0 0 2>。 地址的编码包括总线号0x0 << 16)、设备号0x12 << 11)和功能号0x3 << 8)。中断说明符是2,这是根据PCI绑定对INTB的编码。 应用中断映射掩码值<0xf800 0 0 7>,结果为<0x9000 0 0 2>。在中断映射表查找该结果,该表映射到父中断说明符<4 1>

4、Nexus 节点和说明符映射

1、Nexus 节点属性

一个连接节点应该有一个#<specifier>-cells属性,其中<specifier>是一些说明符空间,如‘gpio’‘clock’‘reset’等。

1、#< specifier >-map

1、属性

#< specifier >-map

2、值类型

< prop-encoded-array >编码为任意数量的说明符映射条目

3、描述

< specifier >-map连接节点中的一个属性,它将一个说明符域与一组父说明符域连接起来,并描述子域中的说明符如何映射到它们各自的父域。

映射是一个表,其中每一行都是一个映射条目,由三个组件组成:子说明符、说明符父项和父说明符。

child specifier

被映射的子节点的说明符。指定此组件所需的 32 位单元数由此节点的#<specifier>-cells属性描述 - 包含<specifier>-map属性的连接节点。

specifier parent

一个<phandle>值,指向子域被映射到的说明符父级。

parent specifier

父域中的说明符。指定此组件所需的 32 位单元数由说明符父节点的#-cells属性描述。

通过将说明符与映射中的子说明符进行匹配,在映射表上执行查找。由于说明符中的某些字段可能不相关或需要修改,因此在完成查找之前应用掩码。该掩码在<specifier>-map-mask属性中定义(参见第2.5.1.2节)。

类似地,当映射说明符时,单元说明符中的某些字段可能需要保持不变并从子节点传递到父节点。在这种情况下,可以指定<specifier>-map-pass-thru属性(参见第2.5.1.3节)以将掩码应用于子说明符并复制与父单元说明符匹配的任何位。

2、< specifier >-map-mask

1、属性

< specifier >-map-mask

2、值类型

< prop-encoded-array >编码为位掩码

3、描述

可以为连接节点指定< specifier >-map-mask属性。此属性指定一个掩码,该掩码应用于在< specifier >-map属性中指定的表中查找的子单元说明符。如果未指定此属性,则假定掩码是设置了所有位的掩码。

3、< specifier>-map-pass-thru

1、属性

< specifier>-map-pass-thru

2、值类型

< prop-encoded-array >编码为位掩码

3、描述

可以为连接节点指定 -map-pass-thru 属性。此属性指定一个掩码,该掩码应用于在<specifier>-map属性中指定的表中查找的子单元说明符。子单元说明符中的任何匹配位都被复制到父说明符。如果未指定此属性,则假定掩码是未设置位的掩码。

4、#< specifier>-cells

1、属性

#< specifier >-cells

2、值类型

< u32 >

3、描述

#< specifier >-cells属性定义对域的说明符进行编码所需的单元格数。

2、说明符映射示例

下面显示了具有两个GPIO控制器的设备树片段的表示和示例说明符映射,用于描述两个控制器上的几个gpios通过板上的连接器到设备的GPIO路由。扩展设备节点位于连接器节点的一侧,带有两个GPIO控制器的SoC位于连接器的另一侧。

soc {soc_gpio1: gpio-controller1 { #gpio-cells = <2>;};soc_gpio2: gpio-controller2 { #gpio-cells = <2>;}; };connector: connector { #gpio-cells = <2>; gpio-map = <0 0 &soc_gpio1 1 0>, <1 0 &soc_gpio2 4 0>, <2 0 &soc_gpio1 3 0>, <3 0 &soc_gpio2 2 0>;gpio-map-mask = <0xf 0x0>; gpio-map-pass-thru = <0x0 0x1>;};expansion_device { reset-gpios = <&connector 2 GPIO_ACTIVE_LOW>;};

gpio-map表中的每一行都由三部分组成:一个子单元说明符,它被映射到一个带有父说明符的gpio-controller节点。

例如,说明符映射表的第一行指定连接器的GPIO 0的映射。该行的组件显示在此处

子说明符:0 0

说明符父:&soc_gpio1

父说明符:1 0

子说明符<0 0>,它在标志字段为0的连接器中指定GPIO 0。这需要由连接器节点的#gpio-cells属性指定的两个32位单元,这是子说明符域。

说明符父级由指向连接器的说明符父级的phandle指定,即SoC中的第一个GPIO控制器。

父说明符<1 0>。表示gpio说明符(两个单元格)的单元格数量由说明符父节点soc_gpio1节点上的#gpio-cells属性决定。

<1 0>是由设备绑定为GPIO控制器指定的值。

<1>指定连接器上的GPIO 0所连接到的GPIO控制器上的GPIO引脚编号。

<0>指定标志(低电平有效、高电平有效等)。

在本例中,gpio-map-mask属性的值为<0xf 0>。在gpio-map表中执行查找之前,此掩码应用于子单元说明符。同样,gpio-map-pass-thru属性的值为<0x0 0x1>。在将子单元说明符映射到父单元说明符时,此掩码应用于子单元说明符。在此掩码中设置的任何位都将从父单元说明符中清除,并从子单元说明符复制到父单元说明符。

要从扩展设备的reset-gpios属性查找GPIO 2的连接器说明符源编号,将执行以下步骤:

子说明符形成值<2 GPIO_ACTIVE_LOW>。 说明符使用每个GPIO绑定的低电平有效标志对GPIO 2进行编码。gpio-map-mask<0xf 0x0>与子说明符进行AND运算,结果为<0x2 0>。结果在 gpio-map 表中查找,该表映射到父说明符<3 0>&soc_gpio1 phandlegpio-map-pass-thru<0x0 0x1>被反转并与在gpio-map表中找到的父说明符进行AND运算,结果为<3 0>。子说明符与gpio-map-pass-thru掩码进行AND运算,形成<0 GPIO_ACTIVE_LOW>,然后与清除的父说明符<3 0>进行OR运算,得到<3 GPIO_ACTIVE_LOW>。说明符<3 GPIO_ACTIVE_LOW>附加到映射的phandle &soc_gpio1导致<&soc_gpio1 3 GPIO_ACTIVE_LOW>

二、设备节点要求

1、基本设备节点类型

以下部分指定了符合DTSpec的设备树中所需的基本设备节点集要求

所有设备树都应有一个根节点,并且以下节点应出现所有设备树的根部

一个/cpus节点至少一个/memory节点

2、Root 节点

设备树有一个根节点,所有其他设备节点都是其后代。根节点的完整路径/

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的

3、/aliases 节点

设备树可能有一个别名节点(/aliases),用于定义一个多个别名属性。别名节点应位于设备树的根部并具有节点名称/aliases

/aliases节点的每个属性都定义了一个别名属性名称指定别名。属性值指定设备树中节点的完整路径例如,属性serial0 = "/simple-bus@fe000000/ serial@llc500"定义别名serial0

别名应是以下字符集中的131个字符的小写文本字符串

别名值是一个设备路径并被编码为一个字符串。该值表示节点的完整路径,但该路径不需要引用叶节点

客户端程序可以使用别名属性名称引用完整的设备路径作为其字符串值的全部部分。客户端程序在将字符串视为设备路径时,应检测使用别名

例如:

aliases { serial0 = "/simple-bus@fe000000/serial@llc500"; ethernet0 = "/simple-bus@fe000000/ethernet@31c000";};

给定别名serial0,客户端程序可以查看/aliases节点并确定别名指的是设备路径/simple-bus@fe000000/serial@llc500

4、/memory 节点

所有设备树都需要一个内存设备节点,它描述系统物理内存布局。如果系统有多个内存范围,可以创建多个内存节点,或者可以在单个内存节点的reg属性中指定范围

节点名称的单元名称组件(参见第2.2.1节)应为内存。

客户端程序可以使用它选择的任何存储属性访问任何内存预留(参见第5.3节)未涵盖的内存。但是,在更改用于访问真实页面存储属性之前,客户端程序负责执行架构和实现所需的操作,可能包括从缓存中刷新真实页面引导程序负责确保在不采取任何与存储属性更改相关的操作的情况下,客户端程序可以安全地访问所有内存(包括内存预留覆盖的内存),因为WIMG = 0b001x。那是:

不需要直写不禁止缓存内存连贯性需要或不受保护或受保护

如果支持VLE存储属性,则VLE=0

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

例子

给定具有以下物理内存布局64Power系统

RAM:起始地址0x0,长度0x80000000 (2 GB)RAM:起始地址0x100000000,长度0x100000000 (4 GB)

内存节点可以定义如下,假设**#address-cells = <2>** 和**#size-cells = <2>**。

Example #1

memory@0 {device_type = "memory"; reg = <0x000000000 0x00000000 0x00000000 0x80000000 0x000000001 0x00000000 0x00000001 0x00000000>;};

Example #2

memory@0 {device_type = "memory"; reg = <0x000000000 0x00000000 0x00000000 0x80000000>;};memory@100000000 { device_type = "memory"; reg = <0x000000001 0x00000000 0x00000001 0x00000000>;};

reg属性用于定义两个内存范围地址和大小。跳过2 GB I/O区域。请注意,根节点的**#address-cells** 和**#size-cells** 属性指定值为**2,这意味着需要两个32 位单元定义内存节点reg属性地址长度**。

5、/chosen 节点

/chosen节点不代表系统中的真实设备,而是描述系统固件运行时选择或指定的参数。它应该是根节点的子节点

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

例子

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

可能会遇到旧版本设备树,其中包含称为linuxstdout-pathstdout-path属性的弃用形式。为了兼容性,如果stdout-path属性不存在,客户端程序可能希望支持linuxstdout-path。这两个属性的含义和用途是相同的。

6、/cpus 节点

所有设备树都需要一个/cpus节点。它并不代表系统中的真实设备,而是充当代表系统CPU的子CPU节点的容器

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

/cpus节点可能包含跨cpu节点通用的属性。有关详细信息,请参阅第3.7节。

有关示例,请参阅第3.8.1节。

7、/cpus/cpu* 节点

一个cpu节点代表一个足够独立硬件执行块,它能够运行操作系统不会干扰可能运行其他操作系统的其他CPU

共享一个MMU的硬件线程通常表示在一个cpu节点下。如果设计了其他更复杂的CPU拓扑,则CPU的绑定必须描述拓扑(例如,不共享MMU的线程)。

CPU线程通过统一的数字空间进行编号,该空间应尽可能匹配中断控制器的CPU/线程编号

cpu节点具有相同值属性可能会被放置在/cpus节点中。客户端程序必须首先检查特定的cpu节点,但如果未找到预期的属性,则应查看父/cpus节点。这导致在所有CPU上都相同的属性的更详细的表示。

每个CPU节点的节点名称应为cpu

1、/cpus/cpu* 节点的一般属性

下表描述了cpu节点的一般属性。表3.6中描述的一些属性是具有特定适用细节的选择标准属性。

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

可能会遇到旧版本的设备树,它们在CPU节点上包含总线频率属性。为了兼容性,客户端程序可能希望支持总线频率。该值的格式与clock-frequency的格式相同。推荐的做法是使用时钟频率属性来表示总线节点上总线的频率。

2、TLB 属性

cpu节点的以下属性描述了处理器MMU中的转换后备缓冲区

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

3、Internal (L1) Cache 属性

cpu节点的以下属性描述了处理器的内部 (L1) 缓存

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

可能会遇到旧版本的设备树,其中包含称为l2-cache的下一级缓存属性的弃用形式。为了兼容性,如果不存在next-level-cache属性,客户端程序可能希望支持l2-cache。这两个属性的含义和用途是相同的。

4、例子

这是一个带有一个子cpu节点的/cpus节点的示例:

cpus {#address-cells = <1>; #size-cells = <0>; cpu@0 {device_type = "cpu"; reg = <0>;d-cache-block-size = <32>; // L1 - 32 bytes i-cache-block-size = <32>; // L1 - 32 bytes d-cache-size = <0x8000>; // L1, 32K i-cache-size = <0x8000>; // L1, 32K timebase-frequency = <82500000>; // 82.5 MHz clock-frequency = <825000000>; // 825 MHz}; };

8、多级共享缓存节点(/cpus/cpu*/l?-cache)

处理器系统可以实现附加级别缓存层次结构。例如,二级 (L2) 或三级 (L3) 缓存。这些缓存可能与CPU紧密集成也可能在多个CPU之间共享

具有**“缓存”兼容值**的设备节点描述了这些类型的缓存。

缓存节点应定义一个phandle属性,所有与缓存相关或共享缓存的cpu节点或缓存节点都应包含一个下一级缓存属性,该属性指定缓存节点的phandle

缓存节点可以表示在CPU节点下或设备树中的任何其他适当位置

多级缓存共享缓存用表3-9中的属性表示。表3-8中描述了L1缓存属性。

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

1、例子

请参阅以下两个CPU的设备树表示示例,每个CPU都有自己的片上L2和共享的L3

cpus {#address-cells = <1>; #size-cells = <0>;cpu@0 {device_type = "cpu"; reg = <0>; cache-unified; cache-size = <0x8000>; // L1, 32 KB cache-block-size = <32>; timebase-frequency = <82500000>; // 82.5 MHz next-level-cache = <&L2_0>; // phandle to L2L2_0:l2-cache { compatible = "cache"; cache-unified; cache-size = <0x40000>; // 256 KBcache-sets = <1024>; cache-block-size = <32>; cache-level = <2>; next-level-cache = <&L3>; // phandle to L3L3:l3-cache { compatible = "cache"; cache-unified; cache-size = <0x40000>; // 256 KB cache-sets = <0x400>; // 1024 cache-block-size = <32>; cache-level = <3>;}; }; };cpu@1 {device_type = "cpu"; reg = <1>; cache-unified; cache-block-size = <32>; cache-size = <0x8000>; // L1, 32 KB timebase-frequency = <82500000>; // 82.5 MHz clock-frequency = <825000000>; // 825 MHz cache-level = <2>; next-level-cache = <&L2_1>; // phandle to L2 L2_1:l2-cache { compatible = "cache"; cache-unified; cache-size = <0x40000>; // 256 KB cache-sets = <0x400>; // 1024 cache-line-size = <32>; // 32 bytes next-level-cache = <&L3>; // phandle to L3}; }; };

三、设备绑定

本章包含有关如何在设备树中表示特定类型和类别的设备的要求(称为绑定)。设备节点的compatible属性描述了节点遵守的特定绑定(或多个绑定)。

绑定可以定义为彼此的扩展。例如,可以将新的总线类型定义为简单总线绑定的扩展。在这种情况下,compatible属性将包含几个字符串来标识每个绑定——从最具体到最一般(参见第2.3.1节,兼容)。

1、约束准则

1、一般原则

设备创建新的设备树表示时,应创建一个绑定来完整描述设备所需的属性和值。这组属性应具有足够的描述性,以便为设备驱动程序提供所需的设备属性。

一些推荐的做法包括:

1、使用第2.3.1节中描述的约定定义兼容字符串。

2、使用适用于新设备的标准属性(在第2.32.4节中定义)。这种用法通常至少包括reginterrupts属性。

3、如果新设备适合DTSpec定义的设备类,则使用第4节(设备绑定)中指定的约定。

4、如果适用,请使用第4.1.2节中指定的其他属性约定。

5、如果绑定需要新属性,则推荐的属性名称格式为:“<company>,<property-name>“,其中<company>是一个OUI或唯一的短字符串,如标识绑定创建者的股票代码。

示例“ibm,ppc-interrupt-server#s”

2、其他属性

本节定义了可能适用于多种类型设备和设备类的有用属性列表。此处定义它们是为了促进名称和用法的标准化

1、clock-frequency

2、reg-shift

3、label

2、串口设备

1、串行类绑定

串行设备类由各种类型的点对点串行线路设备组成。串行线路设备的示例包括8250 UART16550 UARTHDLC设备和BISYNC设备。在大多数情况下,与RS-232标准兼容的硬件适合串行设备类。

I2CSPI(串行外设接口)设备不应表示为串行端口设备,因为它们有自己的特定表示

1、clock-frequency

2、current-speed

2、美国国家半导体 16450/16550 兼容 UART 要求

National Semiconductor 16450/16550 UART(通用异步接收器发射器)兼容的串行设备应使用以下属性在设备树中表示。

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第 2.3 节)都是允许的,但都是可选的。

3、网络设备

网络设备是面向分组的通信设备假定此类中的设备实现七层OSI模型的数据链路层(第2层)并使用媒体访问控制 (MAC) 地址。网络设备的示例包括以太网FDDI802.11令牌环

1、网络类绑定

1、address-bits

2、local-mac-address

3、mac-address

4、max-frame-size

2、以太网特定注意事项

了网络设备类指定的属性之外,还可以使用以下属性设备树中表示基于IEEE 802.3 LAN标准集合(统称为以太网)的网络设备

本节中列出的属性扩充了网络设备类中列出的属性

1、max-speed

2、phy-connection-type

phy-connection-type属性的定义值

3、phy-handle

4、电源 ISA 开放 PIC 中断控制器

本节规定了表示Open PIC兼容中断控制器的要求。开放 PIC 中断控制器实现开放PIC架构(由AMDCyrix联合开发)并在开放可编程中断控制器 (PIC) 寄存器接口规范修订版1.2 [b18]中指定。

Open PIC中断域中的中断说明符两个单元编码。第一个单元格定义中断号。第二个单元格定义了意义和级别信息。

感知和电平信息应在中断说明符中按如下方式编码

0 = low to high edge sensitive type enabled 1 = active low level sensitive type enabled 2 = active high level sensitive type enabled 3 = high to low edge sensitive type enabled

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

注意:所有其他标准属性(第2.3节)都是允许的,但都是可选的。

5、simple-bus 兼容值

片上系统处理器可能具有无法探测设备的内部I/O总线无需额外配置即可直接访问总线上的设备。这种类型的总线被表示为具有“simple-bus”兼容值的节点。

用法说明

R = Required(必须的)O = Optional(可选的)OR = Optional but Recommended(可选但推荐)SD = See Definition(见定义)

四、扁平化设备树 (DTB) 格式

设备树Blob (DTB)格式是设备树数据的平面二进制编码。它用于在软件程序之间交换设备树数据。例如,在启动操作系统时,固件会将DTB传递给操作系统内核

注意IEEE1275开放固件[IEEE1275]没有定义DTB格式。在大多数开放固件兼容平台上,通过调用固件方法遍历树结构来提取设备树。

DTB格式单个线性无指针数据结构中对设备树数据进行编码。它由一个小头部(见5.2节)和三个可变大小的部分组成内存保留块(见5.3节)、结构块(见5.4节)和字符串块(见5.5节)。这些应该以该顺序出现在展平的设备树中。因此,设备树结构作为一个整体,当加载到内存地址时,将类似于图5.1中的图(较低的地址在图的顶部)。

(自由空间)部分可能不存在,但在某些情况下,它们可能需要满足各个块的对齐约束(参见第5.6节)。

1、版本控制

自从格式的原始定义以来,已经定义了几个版本的扁平设备树结构标头中的字段给出版本,以便客户端程序可以确定设备树是否以兼容格式编码

本文档仅描述了该格式的第17版。DTSpec兼容的引导程序应提供版本17或更高版本的设备树,并应提供与版本16向后兼容的版本的设备树。DTSpec兼容的客户端程序应接受向后兼容版本17的任何版本的设备树,并且可以接受其他版本以及。

注意:版本是关于设备树的二进制结构,而不是它的内容。

2、Header

devicetree头布局由以下C结构定义。所有的头字段都是32位整数,以大端格式存储

struct fdt_header { uint32_t magic; uint32_t totalsize; uint32_t off_dt_struct; uint32_t off_dt_strings; uint32_t off_mem_rsvmap; uint32_t version; uint32_t last_comp_version; uint32_t boot_cpuid_phys; uint32_t size_dt_strings; uint32_t size_dt_struct;};

3、内存保留块

1、目的

内存保留块为客户端程序提供物理内存中保留的区域列表;也就是说,不应将其用于一般内存分配。它用于保护重要数据结构不被客户端程序覆盖。例如,在一些带有IOMMU的系统上,由DTSpec引导程序初始化的TCE(翻译控制条目)表需要以这种方式进行保护。同样,在客户端程序运行时使用的任何引导程序代码或数据都需要保留(例如,开放固件平台上的RTAS)。DTSpec不要求引导程序提供任何此类运行时组件,但它不禁止实现作为扩展这样做。

更具体地说客户端程序不应访问保留区域中的内存除非引导程序提供的其他信息明确指示它应该这样做。客户端程序然后可以以指示的方式访问保留存储器的指示部分。引导程序可以向客户端程序指示保留内存的特定用途的方法可能出现在本文档、它的可选扩展或特定于平台的文档中。

引导程序提供的保留区域可以但不要求包含设备树blob本身。客户端程序应确保在使用之前不会覆盖此数据结构,无论它是否在保留区域中。

任何在内存节点中声明并被引导程序访问或在客户端进入后被引导程序访问的内存都必须保留。此类访问的示例包括(例如,通过不受保护的虚拟页面进行推测性内存读取)。

这个要求是必要的,因为任何未被保留的内存都可以被具有任意存储属性的客户端程序访问。

任何由引导程序或由引导程序引起的对保留内存的访问都必须在不禁止缓存和内存一致性要求(即WIMG = 0bx01x)的情况下完成,另外对于第三册-S 实现,不要求直写(即,WIMG = 0b001x) 。此外,如果支持 VLE 存储属性,则必须在VLE=0时完成对保留内存的所有访问。

此要求是必要的,因为客户端程序被允许映射具有指定为不要求直写、不禁止缓存和要求内存一致性(即,WIMG = 0b001x)和VLE = 0的存储属性的内存。客户端程序可能会使用包含保留内存的大型虚拟页面。但是,客户端程序可能不会修改保留内存,因此引导程序可能会按照需要直写的方式执行对保留内存的访问,其中此存储属性的冲突值在体系结构上是允许的。

2、Format

内存预留块由一组64位大端整数对的列表组成,每对由以下C结构表示。

struct fdt_reserve_entry { uint64_t address; uint64_t size;};

每对都给出了保留内存区域物理地址和大小(以字节为单位)。这些给定区域不应相互重叠。保留块列表应以地址和大小都等于0的条目结束。注意地址和大小值始终为64位。在32CPU上,值的高32位被忽略。

内存预留块中的每个uint64_t以及整个内存预留块都应位于距设备树blob开头的8字节对齐偏移处(参见第 5.6 节)。

4、结构块

结构块描述了设备树本身的结构和内容。它由带有数据的令牌序列组成,如下所述。这些被组织成线性树结构,如下所述。

结构块中的每个标记,以及结构块本身,都应位于距设备树blob开头的4字节对齐偏移处(见 5.6)。

1、词汇结构

结构块由一系列片段组成,每个片段以一个标记开头,即一个大端32位整数。一些令牌后跟额外的数据,其格式由令牌值决定。所有令牌都应在32位边界上对齐,这可能需要在前一个令牌数据之后插入填充字节(值为0x0)。

五种令牌类型如下:

1、FDT_BEGIN_NODE (0x00000001)

FDT_BEGIN_NODE标记标志着节点表示的开始。后面应该跟节点的单元名称作为额外数据。名称存储为以空字符结尾的字符串,并且应包括单元地址(参见第2.2.1节),如果有的话。节点名称后跟零填充字节(如果需要对齐),然后是下一个标记,可以是除FDT_END之外的任何标记。

2、FDT_END_NODE (0x00000002)

FDT_END_NODE标记标志着节点表示的结束。这个令牌没有额外的数据;所以紧随其后的是下一个标记,它可以是除FDT_PROP之外的任何标记。

3、FDT_PROP (0x00000003)

FDT_PROP标记标志着设备树中一个属性表示的开始。其后应是描述该属性的额外数据。该数据首先由属性的长度和名称组成,表示为以下C结构:

struct {uint32_t len; uint32_t nameoff;}

此结构中的两个字段都是32位大端整数。

len以字节为单位给出属性值的长度(可能为零,表示一个空属性,请参阅第2.2.4.2节)。nameoff给出了字符串块(参见第5.5节)的偏移量,在该块中属性的名称存储为以空字符结尾的字符串。

在此结构之后,属性的值作为长度为len的字节字符串给出。该值后跟零填充字节(如有必要)以与下一个32位边界对齐,然后是下一个令牌,它可以是除FDT_END之外的任何令牌。

4、FDT_NOP (0x00000004)

FDT_NOP令牌将被任何解析设备树的程序忽略。这个令牌没有额外的数据;因此紧随其后的是下一个令牌,它可以是任何有效的令牌。树中的属性或节点定义可以用FDT_NOP令牌覆盖以将其从树中删除,而无需移动设备树 blob 中树表示的其他部分。

5、FDT_END (0x00000009)

FDT_END标记标记结构块结束。应该只有一个FDT_END标记,它应该是结构块中的最后一个标记。它没有额外的数据;所以紧跟在FDT_END标记之后的字节从结构块的开头偏移等于设备树blob标头中size_dt_struct字段的值。

2、树状结构

devicetree结构表示为线性树每个节点的表示以FDT_BEGIN_NODE标记开始,以FDT_END_NODE标记结束。节点的属性和子节点(如果有)在FDT_END_NODE之前表示,因此这些子节点的FDT_BEGIN_NODEFDT_END_NODE令牌嵌套在父节点的令牌中。

整个结构块由根节点的表示(其中包含所有其他节点的表示)组成,后跟FDT_END标记以标记整个结构块的结尾。

更准确地说,每个节点的表示由以下组件组成:

(可选)任意数量的FDT_NOP令牌FDT_BEGIN_NODE令牌 节点的名称作为以空字符结尾的字符串[将填充字节归零以对齐4字节边界] 对于节点的每个属性: (可选)任意数量的FDT_NOP令牌FDT_PROP令牌 第5.4.1节中给出的属性信息[将填充字节归零以对齐4字节边界] 这种格式的所有子节点的表示(可选)任意数量的FDT_NOP令牌FDT_END_NODE令牌

注意,此过程要求特定节点的所有属性定义在该节点的任何子节点定义之前。虽然如果属性和子节点混合在一起,结构不会有歧义,但是处理扁平树所需的代码被这个要求简化了。

5、字符串块

strings块包含表示树中使用的所有属性名称的字符串。这些空终止的字符串在本节中简单地连接在一起,并从结构块中通过偏移量引用到字符串块中。

字符串块没有对齐约束,可以出现在距设备树blob开头的任何偏移处。

6、对齐

对于在没有未对齐内存访问的情况下使用的内存预留和结构块中的数据,它们应位于适当对齐的内存地址。具体而言,内存预留块应与8字节边界对齐,结构块应与4字节边界对齐。

此外,可以在不破坏子块对齐的情况下重新定位整个设备树blob

如前几节所述,结构块和字符串块应与设备树blob的开头对齐偏移。为了确保块在内存中的对齐,确保设备树作为一个整体被加载到与任何子块的最大对齐对齐的地址处,即8字节边界就足够了。符合DTSpec的引导程序应在这样的对齐地址加载设备树blob,然后再将其传递给客户端程序。如果DTSpec客户端程序将设备树blob重新定位到内存中,它应该只将其重新定位到另一个8字节对齐的地址。

五、设备树源 (DTS) 格式(版本 1)

Devicetree Source (DTS)格式是一种形式的设备树的文本表示,dtc可以将其处理为内核期望的形式的二进制设备树。下面的描述不是DTS的正式语法定义,而是描述了用于表示设备树的基本结构

1、编译器指令

可以从DTS文件中包含其他源文件。包含文件的名称应以“.dtsi”结尾。包含的文件又可以包含其他文件。

/include/ "FILE"

2、Labels

源格式允许将标签附加到设备树中的任何节点或属性值Phandle路径引用可以通过引用标签自动生成,而不是显式指定 phandle 值或节点的完整路径。标签仅用于设备树源格式,不会编码到DTB二进制文件中。

标签长度为1~31个字符,只能由表6.1中的字符组成,且不能以数字开头。

标签是通过在标签名称后附加一个冒号(‘:’)来创建的。引用是通过在标签名称前加上与号(‘&’)来创建的。

3、节点和属性定义

Devicetree节点使用节点名称单元地址进行定义,大括号标记节点定义的开始和结束。它们前面可能有一个标签

[label:] node-name[@unit-address] { [properties definitions] [child nodes]};

节点可能包含属性定义和/或子节点定义。如果两者都存在,则属性应位于子节点之前。

之前定义的节点可能会被删除

/delete-node/ node-name; /delete-node/ &label;

属性定义是以下形式的名称值对

[label:] property-name = value;

除了具有以下形式的空(零长度)值的属性

[label:] property-name;

之前定义的属性可能会被删除。

/delete-property/ property-name;

属性值可以定义为32位整数单元的数组、以null结尾的字符串、字节串或这些的组合。

单元格数组由围绕空格分隔的 C 样式整数列表的尖括号表示。例子:

interrupts = <17 0xc>;

值可以表示为括号内的算术、按位或逻辑表达式。

Arithmetic operators+ add - subtract * multiply / divide % modulo

Bitwise operators& and | or ^ exclusive or ~ not << left shift >> right shift

Logical operators&& and || or ! not

Relational operators< less than > greater than <= less than or equal >= greater than or equal == equal != not equal

Ternary operators ?: (condition ? value_if_true : value_if_false)

一个64位值用两个32位单元表示。例子:

clock-frequency = <0x00000001 0x00000000>;

以空字符结尾的字符串值使用双引号表示(属性值被视为包含终止NULL字符)。例子:

compatible = "simple-bus";

字节串包含在方括号[]中,每个字节由两个十六进制数字表示。每个字节之间的空格是可选的。例子:

local-mac-address = [00 00 12 34 56 78];

或等效地:

local-mac-address = [000012345678];

值可能有几个以逗号分隔的组件,它们连接在一起。例子:

compatible = "ns16550", "ns8250"; example = <0xf00f0000 19>, "a strange property format";

在元胞数组中,对另一个节点的引用将扩展到该节点的phandle。引用可以是&后跟节点的标签。例子:

interrupt-parent = < &mpic >;

或者它们可能是&后跟花括号中的节点的完整路径。例子:

interrupt-parent = < &{/soc/interrupt-controller@40000} >;

在元胞数组之外,对另一个节点的引用将扩展到该节点的完整路径。例子:

ethernet0 = &EMAC0;

标签也可以出现在属性值的任何组件之前或之后,或者在元胞数组的单元格之间,或者在字节串的字节之间。例子:

reg = reglabel: <0 sizelabel: 0x1000000>; prop = [ab cd ef byte4: 00 ff fe]; str = start: "string value" end: ;

4、文件布局

版本1 DTS文件具有整体布局:

/dts-v1/; [memory reservations] / {[property definitions] [child nodes]};

/dts-v1/;

应存在以将文件标识为版本1 DTS(没有此标记的dts文件将被dtc视为处于过时的版本0中,除了其他小的但不兼容的更改之外,它使用不同的整数格式)。

内存预留为devicetree blob的内存预留表定义了一个条目。它们具有以下形式:/memreserve/ < address> < length>;其中

< address>< length>64C风格的整数。

/ { };部分定义了设备树的根节点。支持C风格(/* . . . */)C++风格(//)注释。

如果觉得《Linux 驱动开发 十:《Devicetree Specification》翻译》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。