您的位置:首页 > 运维架构 > Linux

设备树(五)linux内核主线booting-without-of.txt

2015-11-17 17:34 393 查看
A node has 2 names. The actual node name is generally contained in a

property of type "name" in the node property list whose value is a zero

terminated string and is mandatory for version 1 to 3 of the format

definition (as it is in Open Firmware). Version 16 makes it optional as

it can generate it from the unit name defined below.

***********************************************

练习题:观察一颗device-tree,看看它有什么特点?

/ {

model = "TI AM335x maria_am335x";

compatible = "ti,maria_am335x", "ti,am33xx";

cpus {

cpu@0 {

cpu0-supply = <&dcdc2_reg>;

};

};

memory {

device_type = "memory";

reg = <0x80000000 0x20000000>; /* 512 MB */

};

leds {

pinctrl-names = "default";

pinctrl-0 = <&user_leds_s0>;

compatible = "gpio-leds";

led@2 {

label = "maria_335x:red:usr_led0";

gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;

linux,default-trigger = "";

default-state = "off";

};

};

};

每个大括号都认为是一个node,根node是"/"。

led@2也是一个node。

每个node都有两个name。在verrion 1 to 3中,actual node name存储在特征

名字里;而在version 16之后的版本,会自动从unit name中生成。

***********************************************

There is also a "unit name" that is used to differeniate nodes with the

same name at the same level, it is usually made of the node names, the

"@" sign, and a "unit address", which definition is specific to the bus

type the node sits on.

The unit name doesn't exist as a property per-se but is included in the

device-tree structure. It is typically used to represent "path" in the

device-tree. More details about the actual format of these will be below.

***********************************************

练习题:观察一颗device-tree,看看它有什么特点?

led@2 {

label = "maria_335x:red:usr_led0";

gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;

linux,default-trigger = "";

default-state = "off";

};

led@2就是unit name,除了2之外,还另外定义了3个led节点。

ps:Cadsoft Eagle软件,也是使用@这种方式区分不同的原理图Pin脚!

***********************************************

The kernel generic code does not make any formal use of the unit address

(though some board support code may do) so the only real requirement here

for the unit address is to ensure uniqueness of the node unit name at a

given level of the tree. Nodes with no notion of address and no possible

sibling of the same name (like /memory or /cpus) may omit the unit

address in the context of this specification, or usr the "@0" default

unit address. The unit name is used to define a node "full path", which

is the concatenation of all parent node unit names separated with "/".

The root node doesn't have a defined name, and isn't required to have

a name property either if you are using version 3 or earlier of the

format. It also has no unit address (no @ symbol followed by a unit

address). The root node unit name is thus an empty string. The full

path to the root node is "/".

***********************************************

练习题:观察一颗device-tree,看看它有什么特点?

/ {

model = "TI AM335x maria_am335x";

compatible = "ti,maria_am335x", "ti,am33xx";

cpus {

cpu@0 {

cpu0-supply = <&dcdc2_reg>;

};

};

};

"/"就是根node。

它不包含任何其它的字符。

***********************************************

Every node which actually represents an actual device (that is, a node

which isn't only a virtual "container" for more nodes, like "/cpus"

is) is also required to have a "compatible" property indicating the

specific hardware and an optional list of devices it is fully backwards

compatible with.

***********************************************

练习题:观察一颗device-tree,看看它有什么特点?

leds {

pinctrl-names = "default";

pinctrl-0 = <&user_leds_s0>;

compatible = "gpio-leds";

led@2 {

label = "maria_335x:red:usr_led0";

gpios = <&gpio1 16 GPIO_ACTIVE_LOW>;

linux,default-trigger = "";

default-state = "off";

};

};

关键字compatible,是驱动程序调用实际硬件的关键。

在drivers/leds/leds-gpio.c中,有一个函数:

static const struct of_device_id of_gpio_leds_match[] = {

{ .compatible = "gpio-leds", },

{},

};

driver/leds/leds-gpio.c是驱动文件,从这里就可以看出,dtb文件是怎样

和驱动程序联系起来的。这个文件底下有熟悉的关键字:

MODULE_AUTHOR

MODULE_DESCRIPTION

MODULE_LICENSE

MODULE_ALIAS

是的,它是一个模块文件,生成的设备以及它的read/write/ioctl等等函数正

是应用程序所需要的!

***********************************************

Finally, every node that can be referenced from a property in another

node is required to have either a "phandle" or a "linux,phandle"

property. Real Open Firmware implementations provide a unique "phandle"

value for every node that the "prom_init()" trampoline code turns into

"linux,phandle" properties. However, this is made optional if the

flattened device tree is used directly. An example of a node referencing

another node via "phandle" is when laying out the interrupt tree which

will be described in a further version of this document.

The "phandle" property is a 32-bit value that uniquely identified a node

followed by the node unit name. You are free to use whatever values or

system of values, internal pointers, or whatever to generate these, the

only requirement is that every node for which you provide that property

has a unique value for it.

Here is an example of a simple device-tree. In this example, an "o"

designates a node followed by the node unit name. Properties are

presented with their name followed by their content. "content" represents

an ASCII string (zero terminated) value, while <content> represents an

32-bit value, specified in decimal or hexadecimal (the latter prefixed

0x). The various nodes in this example will be discussed in a later

chapter. At this point, it is only meant to give you a idea of what a

device-tree looks like. I have purposelly kept the "name" and

"linux,phandle" properties which aren't necessary in order to give you

a better idea of what the tree looks like in practice.

/ o device-tree

|- name = "device-tree"

|- model = "MyBoardName"

|- compatible = "MyBoardFamilyName"

|- #address-cells = <2>

|- #size-cells = <2>

|- linux,phandle = <0>

|

o cpus

| | - name = "cpus"

| | - linux,phandle = <1>

| | - #address-cells = <1>

| | - #size-cells = <0>

| |

| o PowerPC,970@0

| |- name = "PowerPC,970"

| |- device_type = "cpu"

| |- reg = <0>

| |- clock-frequency = <0x5f5e1000>

| |- 64-bit

| |- linux,phandle = <2>

|

o memory@0

| |- name = "memory"

| |- device_type = "memory"

| |- reg = <0x00000000 0x00000000 0x00000000 0x20000000>

| |- linux,phandle = <3>

|

o chosen

|- name = "chosen"

|- bootargs = "root=/dev/sda2"

|- linux,phandle = <4>

This tree is almost a minimal tree. It pretty much contains the minimal

set of required nodes and properties to boot a linux kernel; that is,

some basic model information at the root, the CPUs, and the physical

memory layout. It also includes misc information passed through /chosen,

like in this example, the platform type (mandatory) and the kernel

command line arguments (optional).

The /cpus/PowerPC,970@1/64-bit property is an example of a property

without a value. All other properties have a value. The significance of

the #address-cells and #size-cells properties will be explained in

chapter IV which defined precisely the required nodes and properties and

their content.

***********************************************

练习题:phandle的特点是什么呢?

答:关于phandle,俺是真心没看懂-_-!!!

***********************************************

3) Device tree "structure" block

The structure of the device tree is a linearized tree structure. The

"OF_DT_BEGIN_NODE" token starts a new node, and the "OF_DT_END_NODE"

ends that node definition. Child nodes are simply defined before

"OF_DT_END_NODE" (that is nodes within the node). A 'token' is a 32 bit

value. The tree has to be "finished" with a OF_DT_END token

Here's the basic structure of a single node:

* token OF_DT_BEGIN_NODE (that is 0x00000001)

* for version 1 to 3, this is the node full path as a zero

terminated string, starting with "/". For version 16 and later,

this is the node unit name only (or an empty string for the

root node)

* [align gap to next 4 bytes boundary]

* for each property:

* token OF_DT_PROP (that is 0x00000003)

* 32-bit value of property value size in bytes (or 0 if

no value)

* 32-bit value of offset in string block of property name

* property value data if any

* [align gap to next 4 bytes boundary]

* [child nodes data if any]

* token OF_DT_END_NODE (that is 0x00000002)

So the node content can be summarized as a start token, a full path, a

list of properties, a list of child nodes, and an end token. Every child

node is a full node structure itself as defined above.

***********************************************

练习题:token在哪里?

答:在Linux Kernel的源代码中,grep -rn OF_DT_BEGIN_NODE

在下面的文件中存在:

arch/powerpc/platforms/powermac/bootx_init.c

arch/powerpc/include/asm/prom.h

arch/powerpc/kernel/prom_init.c

而在dts文件中并没有出现,说明这些token并不是给用户编写程序使用的,而是经过编译

器编译之后在dtb文件里面被内核识别。

***********************************************

NOTE: The above definition requires that all property definitions for a

particular node MUST precede any subnode definitions for that node.

Although the structure would not be ambiguous if properties and subnodes

were intermingled, the kernel parser requires that the properties come

first (up until at least 2.6.22). Any tools manipulating a flattened

tree must take care to preserve this constraint.

4) Device tree "strings" block

In order to save space, property names, which are generally redundant,

are stored separately in the "strings" block. This block is simply the

whole bunch of zero terminated strings for all property definitions in

the structure block will contain offset values form the beginning of

the string block.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: