zoukankan      html  css  js  c++  java
  • 分析内核源码,设备树【转】

    转自:http://blog.csdn.net/fight_onlyfor_you/article/details/78092204

    U-Boot需要将设备树在内存中的存储地址传给内核。该树主要由三大部分组成:头(Header)、结构块(Structure block)、字符串块(Strings block)。

    设备树在内存中的存储布局图如下


    1.1 头(header

    1.2 结构块(struct block

     扁平设备树结构块是线性化的树形结构,和字符串块一起组成了设备树的主体,以节点形式保存目标板的设备信息

      在结构块中,节点起始标志为32位常值宏OF_DT_BEGIN_NODE,节点结束标志为宏OF_DT_END_NODE

      子节点定义在节点结束标志前。一个节点的基本结构如下所示:

     (1). 节点起始标志OF_DT_BEGIN_NODE(即0x0000_0001);
     (2). 节点路径或者节点单元名(version < 3以及节点路径表示,version > 16时以节点单元名表示);
     (3). 填充字节保证四字节对齐;
     (4). 节点属性。

      每个属性以常值宏OF_DT_PROP 开始,后面依次为属性值的字节长度、属性名在字符串块中的偏移值, (5). 如果存在子节点,则定义子节点

     (6). 节点结束标志OF_DT_END_NODE(即0x0000_0002)。

    1.3 字符串块(Strings block)

    1.4 设备树源码 DTS 表示

           设备树源码文件(.dts)以可读可编辑的文本形式描述系统硬件配置设备树,支持 C/C++方式的注释,该结构有一个唯一的根节点“/”,每个节点都有自己的名字并可以包含多个子节点。设备树的数据格式遵循了 Open Firmware IEEE standard 1275。这个设备树中有很多节点,每个节点都指定了节点单元名称。每一个属性后面都给出相应的值。以双引号引出的内容为 ASCII 字符串,以尖括号给出的是 32 位的16进制值。这个树结构是启动 Linux 内核所需节点和属性简化后的集合,包括了根节点的基本模式信息、CPU 和物理内存布局,它还包括通过/chosen 节点传递给内核的命令行参数信息。

     

    1.5 machine_desc结构

          内核提供了一个重要的结构体struct machine_desc ,这个结构体在内核移植中起到相当重要的作用,内核通过machine_desc结构体来控制系统体系架构相关部分的初始化。machine_desc结构体通过MACHINE_START宏来初始化,在代码中, 通过在mian->setup_arch中调用setup_machine_fdt来获取。


    1.6 设备节点结构体


    1.7 属性结构体


    三、设备树初始化及解析

    分析Linux内核的源码,可以看到其对扁平设备树的解析流程如下

    of_allnodes 源码如下
    在init目录下的main.c中的start_kernel函数中

    进入这个setup_arch
    其余代码先省略


    查看setup_machine_fdt函数
     


    这里调用了early_init_dt_scan_nodes函数


    来看看这个函数


    看看这个fdt_next_node函数


    上面还有一个很重要的地方


    这里,这里对这个initial_boot_parems进行赋值,这里这个指针指向了设备树的虚拟起始地址


    在这里进行偏移,详细信息看这里的代码


    chosen属性

    chosen 节点并不代表一个真实的设备,只是作为一个为固件和操作系统之间传递数据的地方,比如引导参数。chosen 节点里的数据也不代表硬件。通常,chosen 节点在.dts 源文件中为空,并在启动时填充。在我们的示例系统中,固件可以往 chosen 节点添加以下信息:
    chosen {
        bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200"; //节点属性
        linux,initrd-start = <0x85500000>; //节点属性
        linux,initrd-end = <0x855a3212>; //节点属性
    };

    1.2 根节点"/"
           设备树有且仅有一个根节点,即“/”,根节点下包含很多子节点,例入下图,根节点为"/",根节点的子节点为"chosen",根节点的属性包含"compatible","#address-cells","#size-cells","interrupt-parent"等。属性model指明了目标板平台或模块的名称,属性compatible值指明和目标板为同一系列的兼容的开发板名称。对于大多数32位平台,属性#address-cells和#size-cells的值一般为1。#address-cells = <1>; 1表示地址32位,2表示地址64位。#size-cells = <1>;1表示rangs的每部分占一个cell,依此类推 
     {
        compatible = "sprd,spx15";
        #address-cells = <1>;
        #size-cells = <1>;
        interrupt-parent = <&gic>;


        chosen {
            bootargs = "loglevel=8 console=ttyS1,115200n8 init=/init root=/dev/ram0 rw";
            linux,initrd-start = <0x85500000>;
            linux,initrd-end = <0x855a3212>;
        };
    }
    所以本函数就是读取根节点的"#address-cells","#size-cells"属性

    1.3 memory节点
          memory节点用于描述目标板上物理内存范围,一般称作/memory节点,可以有一个或多个。当有多个节点时,需要后跟单元地址予以区分;只有一个单元地址时,可以不写单元地址,默认为0。此节点包含板上物理内存的属性,一般要指定device_type(固定为"memory")和reg属性。其中reg的属性值以<起始地址 空间大小>的形式给出,如下示例中目标板内存起始地址为0x80000000,大小为0x20000000字节。 
    memory {
        device_type = "memory";
        reg = <0x80000000 0x20000000>;
    };



    在看看解析设备树这一块

  • 相关阅读:
    cf B. Sereja and Suffixes
    cf E. Dima and Magic Guitar
    cf D. Dima and Trap Graph
    cf C. Dima and Salad
    最短路径问题(floyd)
    Drainage Ditches(网络流(EK算法))
    图结构练习—BFSDFS—判断可达性(BFS)
    Sorting It All Out(拓扑排序)
    Power Network(最大流(EK算法))
    Labeling Balls(拓扑)
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/8534724.html
Copyright © 2011-2022 走看看