设备树使用手册.docx

上传人:b****4 文档编号:5509834 上传时间:2022-12-17 格式:DOCX 页数:23 大小:29.16KB
下载 相关 举报
设备树使用手册.docx_第1页
第1页 / 共23页
设备树使用手册.docx_第2页
第2页 / 共23页
设备树使用手册.docx_第3页
第3页 / 共23页
设备树使用手册.docx_第4页
第4页 / 共23页
设备树使用手册.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

设备树使用手册.docx

《设备树使用手册.docx》由会员分享,可在线阅读,更多相关《设备树使用手册.docx(23页珍藏版)》请在冰豆网上搜索。

设备树使用手册.docx

设备树使用手册

设备树使用手册

 

本文将介绍如何为一个新机器编写设备树。

我们准备提供一个有关设备树概念的概述和如何使用这些设备树来描述一个机器。

完整的设备树数据格式的技术说明书请参考ePAPR规范。

ePAPR规范涵盖了比本文基本主题更丰富的细节,要查阅本文没有涉及到的高级用法请参考该规范.

 

       目录

1.基本数据格式

2.基本概念

2.1模型机

2.2初始结构

2。

3中央处理器

2.4节点名称

2。

5设备

2。

6理解compatible属性

3。

如何编址

3。

1CPU 编址

3。

2内存映射设备

3。

3非内存映射设备

3.4范围(地址转换)

4。

中断的工作方式

5。

设备特定数据

6.特殊的节点

6.1aliases节点

6。

2chosen 节点

7。

高级主题

7。

1高级模型机

7.2PCI 主桥

7.2。

1PCI 总线编号

7.2.2PCI 地址转换

7.3高级中断映射

8。

附注

基本数据格式

设备树是一个包含节点和属性的简单树状结构.属性就是键-值对,而节点可以同时包含属性和子节点。

例如,以下就是一个.dts格式的简单树:

/{

node1{

      a-string—property=”Astring”;

      a—string—list—property=”firststring","secondstring";

      a-byte—data—property=[0x010x230x340x56];

       child-node1{

          first-child-property;

          second—child-property=〈1〉;

          a—string-property=”Hello,world”;

       };

       child-node2{

       };

   };

   node2{

       an-empty-property;

       a-cell-property=〈1234>;/*eachnumber(cell)isauint32*/

       child—node1{

       };

   };

};

这棵树显然是没什么用的,因为它并没有描述任何东西,但它确实体现

了节点的一些属性:

■一个单独的根节点:

“/”

■两个子节点:

“node1”和“node2”

■两个node1的子节点:

“child-node1”和“child-node2”

■一堆分散在树里的属性。

属性是简单的键-值对,它的值可以为空或者包含一个任意字节流。

然数据类型并没有编码进数据结构,但在设备树源文件中任有几个基本的数据表示形式。

■文本字符串(无结束符)可以用双引号表示:

string—property="astring"

■‘Cells’是32位无符号整数,用尖括号限定:

cell—property=〈0xbeef1230xabcd1234〉

■二进制数据用方括号限定:

binary-property=[0x010x230x450x67];

■不同表示形式的数据可以使用逗号连在一起:

mixed-property=”astring”,[0x010x230x450x67],<0x12345678>;

■逗号也可用于创建字符串列表:

string-list=”redfish",”bluefish”;

 

基本概念

我们将以一个简单机开始,然后通过一步步的建立一个描述这个简单机

的设备树,来了解如何使用设备树。

2.1模型机

考虑下面这个假想的机器(大致基于ARMVersatile),制造商为“Acme”,

并命名为“Coyote’sRevenge":

 ■ 一个32位ARMCPU   

 ■ 处理器本地总线连接到内存映射的串行口、spi总线控制器、i2c控制器、中断控

制器和外部总线桥

 ■  256MBSDRAM起始地址为0

 ■两个串口起始地址:

0x101F1000和0x101F2000

 ■ GPIO控制器起始地址:

0x101F3000

 ■ 带有以下设备的SPI控制器起始地址:

0x10170000

   ■ MMC插槽的SS管脚连接至GPIO#1

 ■ 外部总线桥挂载以下设备

   ■ SMCSMC91111以太网设备连接到外部总线,起始地址:

0x10100000

   ■ i2c控制器起始地址:

0x10160000,并挂载以下设备

     ■ MaximDS1338实时时钟。

响应至从地址1101000(0x58)

   ■  64MBNOR闪存起始地址0x30000000

2。

2初始结构

第一步就是要为这个模型机构建一个基本结构,这是一个有效的设备树最基本的结构。

在这个阶段你需要唯一的标识该机器.

/{

   compatible="acme,coyotes—revenge";

};

compatible指定了系统的名称.它包含了一个“<制造商>,<型号>”形式

的字符串。

重要的是要指定一个确切的设备,并且包括制造商的名子,以避免命名空间冲突。

由于操作系统会使用compatible的值来决定如何在机器上运行,所以正确的设置这个属性变得非常重要。

理论上讲,兼容性(compatible)就是操作系统需要的所有数据都唯一标识一个机器。

如果机器的所有细节都是硬编码的,那么操作系统则可以在顶层的compatible属性中具体查看“acme,coyotes—revenge”。

2。

3中央处理器

接下来就应该描述每个CPU了。

先添加一个名为“cpus"的容器节点,然后为每个CPU分别添加子节点。

具体到我们的情况是一个ARM的双核CortexA9系统.

/{

  compatible="acme,coyotes—revenge";

   cpus{

      cpu@0{

          compatible="arm,cortex—a9”;

       };

      cpu@1{

         compatible="arm,cortex-a9";

       };

   };

};

每个cpu节点的compatible属性是一个“<制造商〉,〈型号〉”形式的字符串,并指定了确切的cpu,就像顶层的compatible属性一样.稍后将会有更多的属性添加进cpu节点,但我们先得讨论一些更过的基本概念。

2。

4节点名称

现在应该花点时间来讨论命名约定了.每个节点必须有一个“<名称>[@<

设备地址〉]”形式的名字。

<名称>就是一个不超过31位的简单ascii字符串。

通常,节点的命名应该根据它所体现的是什么样的设备.比如一个3com以太网适配器的节点就应该命名为ethernet,而不应该是3com509.

如果该节点描述的设备有一个地址的话就还应该加上设备地址(unit-address)。

通常,设备地址就是用来访问该设备的主地址,并且该地址也在节点的reg属性中列出.本文档中我们将在稍后涉及到reg属性。

同级节点命名必须是唯一的,但只要地址不同,多个节点也可以使用一样的通用名称(例如serial@101f1000和serial@101f2000).关于节点命名的更多细节请参考ePAPR规范2.2.1节。

2.5设备

系统中每个设备都表示为一个设备树节点。

所以接下来就应该为这个设备树填充设备节点。

现在,知道我们讨论如何进行寻址和中断请求如何处理之前这些新节点将一直为空。

/{

  compatible=”acme,coyotes—revenge”;

  cpus{

    cpu@0{

      compatible="arm,cortex-a9”;

    };

    cpu@1{

      compatible=”arm,cortex-a9”;

    };

  };

   serial@101F0000{

    compatible="arm,pl011”;

  };

  serial@101F2000{

    compatible="arm,pl011";

  };

  gpio@101F3000{

    compatible="arm,pl061”;

  };

  interrupt—controller@10140000{

    compatible="arm,pl190”;

  };

  spi@10115000{

    compatible=”arm,pl022”;

  };

  external-bus{

    ethernet@0,0{

      compatible=”smc,smc91c111";

    };

    i2c@1,0{

      compatible=”acme,a1234—i2c—bus”;

      rtc@58{

        compatible=”maxim,ds1338”;

      };

    };

    flash@2,0{

      compatible=”samsung,k8f1315ebm",”cfi-flash”;

    };

  };

};

在此树中,已经为系统中的每个设备添加了节点,而且这个·层次结构

也反映了设备与系统的连接方式。

例如,外部总线上的设备就是外部总线节

点的子节点,i2c设备就是i2c总线节点的子节点。

通常,这个层次结构表

现的是CPU视角的系统视图。

现在这棵树还是无效的,因为它缺少关于设备之间互联的信息.稍后将添加这些信息。

在这颗树中,应该注意这些事情:

 ■ 每个设备节点都拥有一个compatible属性.

 ■ 闪存(flash)节点的compatible属性由两个字符串构成。

欲知为何,请阅读下一节。

 ■ 正如前面所述,节点的命名应当反映设备的类型而不是特定的型号。

请查阅ePAPR规范第2。

2。

2节里定义的通用节点名,应当优先使用这些节点名。

2.6理解compatible属性

树中每个表示一个设备的节点都需要一个compatible属性.compatible属性是操作系统用来决定使用哪个设备驱动来绑定到一个设备上的关键因素。

compatible是一个字符串列表,之中第一个字符串指定了这个节点所表示的确切的设备,该字符串的格式为:

"〈制造商>,〈型号〉”。

剩下的字符串的则表示其它与之相兼容的设备.

例如,FreescaleMPC8349片上系统(SoC)拥有一个实现了美国国家半导体ns16550的寄存器接口的串行设备,那么MPC8349的串行设备的compatible属性就应该是:

compatible="fsl,mpc8349-uart”,"ns16550".在这里,mpc8349—uart指定了确切的设备,而 ns16550则说明这是与美国国家半导体ns16550 UART 的寄存器级兼容。

注:

ns16550并没有制造商前缀,这仅仅是历史原因造成的。

所有的新compatible值都应该使用制造商前缀.

这种做法可以使现有的设备驱动能够绑定到新设备上,并仍然唯一的指定确切的设备。

警告:

不要使用带通配符的compatible值,比如“fsl,mpc83xx-uart”或类似情况。

芯片提供商无不会做出一些能够轻易打破你通配符猜想的变化,这时候在修改已经为时已晚了。

相反,应该选择一个特定的芯片然后是所有后续芯片都与之兼容。

 

如何编址

可编址设备使用以下属性将地址信息编码进设备树:

 ■ reg

 ■ #address—cells

■ #size-cells

每个可编址设备都有一个元组列表的reg,元组的形式为:

reg=<地址1长度1[地址2 长度2][地址3 长度3]。

..〉。

每个元组都表示一个该设备使用的地址范围。

每个地址值是一个或多个32位整型数列表,称为cell。

同样,长度值也可以是一个cell列表或者为空。

由于地址和长度字段都是可变大小的变量,那么父节点的#address-cells和#size—cells属性就用来声明各个字段的cell的数量.换句话说,正确解释一个reg属性需要用到父节点的#address-cells和#size-cells的值。

要知道这一切是如何运作的,我们将给模型机添加编址属性,就从CPU开始。

3.1CPU 编址

CPU节点表示了一个关于编址的最简单的例子。

每个CPU都分配了一个唯一的ID,并且没有CPUid相关的大小信息。

  

cpus{

     #address—cells=<1>;

    #size-cells=〈0〉;

    cpu@0{

      compatible="arm,cortex—a9”;

       reg=〈0>;

    };

    cpu@1{

      compatible=”arm,cortex-a9”;

       reg=<1〉;

    };

};

在cpu节点中,#address-cells设置为1,#size-cells设置为0。

这意味着子节点的reg值是一个单一的uint32,这是一个不包含大小字段的地址,为这两个cpu分配的地址是0和1。

cpu节点的#size—cells为0是因为只为每个cpu分配一个单独的地址。

你可能还会注意到reg的值和节点名字是相同的.按照惯例,如果一个节点有reg属性,那么该节点的名字就必须包含设备地址,这个设备地址就是reg属性里第一个地址值。

3.2内存映射设备

与cpu节点里单一地址值不同,应该分配给内存映射设备一个地址范围。

#size-cells声明每个子节点的reg元组中长度字段的大小.在接下来的例子中,每个地址值是1cell(32位),每个长度值也是1cell,这是典型的32位系统.64位的机器则可以使用值为2的#address—cells和#size—cells来获得在设备树中的64位编址。

/{

   #address-cells=<1〉;

  #size-cells=〈1〉;

  ...

  serial@101f0000{

    compatible=”arm,pl011”;

     reg=<0x101f00000x1000>;

  };

  serial@101f2000{

    compatible="arm,pl011";

     reg=〈0x101f20000x1000>;

  };

  gpio@101f3000{

    compatible="arm,pl061";

     reg=<0x101f30000x1000

        0x101f40000x0010〉;

  };

  interrupt-controller@10140000{

    compatible=”arm,pl190";

     reg=<0x101400000x1000〉;

  };

  spi@10115000{

    compatible=”arm,pl022";

     reg=〈0x101150000x1000>;

  };

  ...

};

每个设备都被分配了一个基址以及该区域的大小.这个例子中为GPIO分配了两个地址范围:

0x101f3000..。

0x101f3fff和0x101f4000。

0x101f400f.

一些挂在总线上的设备有不同的编址方案。

例如一个带独立片选线的设备也可以连接至外部总线。

由于父节点会为其子节点定义地址域,所以可以选择不同的地址映射来最恰当的描述该系统.下面的代码展示了设备连接至外部总线并将其片选号编码进地址的地址分配.

external-bus{

     #address-cells=<2>

    #size—cells=〈1〉;

    ethernet@0,0{

      compatible="smc,smc91c111";

       reg=<000x1000>;

    };

    i2c@1,0{

      compatible="acme,a1234-i2c-bus”;

       reg=〈100x1000〉;

      rtc@58{

        compatible=”maxim,ds1338”;

      };

    };

    flash@2,0{

      compatible="samsung,k8f1315ebm",”cfi—flash";

       reg=〈200x4000000〉;

    };

  };

外部总线的地址值使用了两个cell,一个用于片选号;另一个则用于片选基址的偏移量。

而长度字段则还是单个cell,这是因为只有地址的偏移部分才需要一个范围量.所以,在这个例子中,每个reg项都有三个cell:

片选号、偏移量和长度.

由于地址域是包含于一个节点及其子节点的,所以父节点可以自由的定义任何对于该总线来说有意义的编址方案。

那些在直接父节点和子节点以外的节点通常不关心本地地址域,而地址应该从一个域映射到另一个域。

3。

3非内存映射设备

其他的设备没有被映射到处理机总线上。

虽然这些设备可以有一个地址范围,但他们并不是由CPU直接访问。

取而代之的是,父设备的驱动程序会代表CPU执行简介访问。

以i2c设备为例,每个设备都分配了一个地址,但并没有与之关联的长度或范围信息。

这看起来和CPU的地址分配很像

    i2c@1,0{

      compatible="acme,a1234—i2c—bus”;

       #address—cells=<1〉;

       #size—cells=<0〉;

      reg=〈100x1000〉;

      rtc@58{

        compatible=”maxim,ds1338”;

         reg=<58〉;

      };

    };

3。

4范围(地址转换)

我们已经讨论了如何给设备分配地址,但目前来说这些地址还只是设备节点的本地地址,我们还没有描述如何将这些地址映射成CPU可使用的地址

根节点始终描述的是CPU视角的地址空间。

根节点的子节点已经使用的是CPU的地址域,所以它们不需要任何直接映射。

例如,serial@101f0000设备就是直接分配的0x101f0000地址。

那些非根节点直接子节点的节点就没有使用CPU地址域。

为了得到一个内存映射地址,设备树必须指定从一个域到另一个域地址转换地方法,而ranges属性就为此而生。

下面就是一个添加了ranges属性的示例设备树。

/{

  compatible="acme,coyotes—revenge”;

  #address—cells=<1〉;

  #size-cells=<1〉;

  。

.。

  external-bus{

    #address-cells=〈2〉

    #size-cells=〈1〉;

     ranges=〈00 0x10100000 0x10000  //Chipselect1,Ethernet

         10 0x10160000 0x10000  //Chipselect2,i2ccontroller

         20 0x30000000 0x1000000〉;//Chipselect3,NORFlash

    ethernet@0,0{

      compatible="smc,smc91c111”;

      reg=〈000x1000〉;

    };

    i2c@1,0{

      compatible="acme,a1234-i2c-bus”;

      #address—cells=〈1>;

      #size-cells=<0〉;

      reg=〈100x1000〉;

      rtc@58{

        compatible=”maxim,ds1338";

        reg=<58〉;

      };

    };

    flash@2,0{

      compatible=”samsung,k8f1315ebm","cfi—flash";

      reg=<200x4000000〉;

    };

  };

};

ranges是一个地址转换列表。

ranges表中的每一项都是一个包含子地址、父地址和在子地址空间中区域大小的元组。

每个字段的值都取决于子节点的#address-cells

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 医药卫生

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

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