• 分析内核源码,设备树【转】


    转自: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>;
    };



    在看看解析设备树这一块

  • 相关阅读:
    团队项目心得(一)
    《effective c++》读书笔记(上)
    前端进度报告(2018.5.17)
    DeltaFish 校园物资共享平台 第五次小组会议
    项目--用户调研
    DeltaFish 校园物资共享平台 第四次小组会议
    DeltaFish 校园物资共享平台 第三次小组会议
    创建校园二手交易及资源共享平台的问卷调查
    项目平台统一(前后端IDE、代码风格)
    DeltaFish 校园物资共享平台 第二次小组会议
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/8534724.html
Copyright © 2020-2023  润新知