原创 为AM335x移植Linux内核主线代码(5)booting-without-of.txt学习笔记中

2014-10-22 17:48 1427 12 14 分类: MCU/ 嵌入式 文集: Linux Kernel的DTS

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.
 

文章评论2条评论)

登录后参与讨论

DiracFatCat 2014-10-23 10:48

没关系~

用户403664 2014-10-23 10:41

还没看到上,估计你得重发一次。。。。抱歉了
相关推荐阅读
DiracFatCat 2018-09-05 12:14
【博客大赛】卡尔曼滤波学习笔记(11)从位置估计速度
卡尔曼滤波器,不仅仅是一个低通滤波器,否则也不会持续发展50年。 示例:桑先生需要测试高速列车的性能。测试的目的是判断列车在直线上能否保持80m/s的速度。速度和位置每0.1秒测量一次,但是由于...
DiracFatCat 2018-08-31 19:32
【博客大赛】卡尔曼滤波学习笔记(10)一个简单的示例
《Kalman Filtering: Theory and Practice Using MATLAB》第三章,看不懂,暂时略过。《Kalman Filtering: Theory and Pract...
DiracFatCat 2018-07-19 15:09
对sed命令的练习
sed是流编辑器。它每次处理一个输入,因此很有效率。官方手册:https://www.gnu.org/software/sed/manual/sed.html学习Linux命令,当然要阅读官方手册,所...
DiracFatCat 2018-06-19 15:10
【博客大赛】卡尔曼滤波学习笔记(八)可观测性和可控制性 ...
可观测性是指,在给定模型的情况下,动力学系统的状态是否由它的输入输出唯一确定。可观测性是系统模型的特征。如果传感器矩阵H是可逆的,则本系统可观测,因为有:如果传感器矩阵H某些时候是不可逆的,则本系统仍...
DiracFatCat 2018-06-19 10:56
【博客大赛】卡尔曼滤波学习笔记(七)Z变换
如果我们仅仅对离散线性系统感兴趣,那么就使用下面这个表达式:如果u是常量,那么可以写成:为了简化表达式,我们可以将上面写成:离散线性时不变系统的Φ求解,可以使用Z变换。(* 由于本人已经忘记了Z变换的...
DiracFatCat 2018-06-19 10:54
【博客大赛】卡尔曼滤波学习笔记(六)拉普拉斯变换
对于线性时变/时不变系统,求解Φ(t)有多种方式,拉普拉斯变换是其中一种。(* 由于本人已经忘记了拉普拉斯变换的内容,因此本节待续。)...
我要评论
2
12
关闭 站长推荐上一条 /2 下一条