设备树和Platform架构--2--设备树编译

本小节讲解
(1)设备树编译
(2)uboot对设备树的相关操作;
参考:https://blog.csdn.net/woyimibayi/article/details/77574736

1 Device Tree编译

Device Tree文件的格式为dts,包含的头文件格式为dtsi,dts文件是一种人可以看懂的编码格式。但是uboot和linux不能直接识别,他们只能识别二进制文件,所以需要把dts文件编译成dtb文件。dtb文件是一种可以被kernel和uboot识别的二进制文件。把dts编译成dtb文件的工具是dtc。Linux源码目录下scripts/dtc目录包含dtc工具的源码。在Linux的scripts/dtc目录下除了提供dtc工具外,也可以自己安装dtc工具,linux下执行:sudo apt-get install device-tree-compiler安装dtc工具。其中还提供了一个fdtdump的工具,可以反编译dtb文件。dts和dtb文件的转换如图1所示。

dtc工具的使用方法是:dtc –I dts –O dtb –oxxx.dtb xxx.dts,即可生成dts文件对应的dtb文件了。

 

图1 dts和dtb文件转换

2 Device Tree头信息

fdtdump工具使用,Linux终端执行ftddump –h,输出以下信息:

fdtdump -h    #查看帮助

Usage: fdtdump [options] <file>

Options: -[dshV]

 -d, --debug   Dump debuginformation while decoding the file

 -s, --scan    Scan for an embeddedfdt in file

 -h, --help    Print this help andexit

 -V, --version Print version and exit

本文采用s5pv21_smc.dtb文件为例说明fdtdump工具的使用。Linux终端执行fdtdump –sd s5pv21_smc.dtb > s5pv21_smc.txt,打开s5pv21_smc.txt文件,部分输出信息如下所示:

// magic:                             0xd00dfeed

// totalsize:                         0xce4 (3300)

// off_dt_struct:                   0x38

// off_dt_strings:                 0xc34

// off_mem_rsvmap:            0x28

// version:                           17

// last_comp_version:         16

// boot_cpuid_phys:            0x0

// size_dt_strings:               0xb0

// size_dt_struct:                 0xbfc

以上信息便是Device Tree文件头信息,存储在dtb文件的开头部分。在Linux内核中使用struct fdt_header结构体描述。struct fdt_header结构体定义在scripts\dtc\libfdt\fdt.h文件中。

 

struct  fdt_header  {

    fdt32_t  magic;             /* magic word FDT_MAGIC */

    fdt32_t  totalsize;         /* total size of DT block */

    fdt32_t  off_dt_struct;        /* offset to  structure */

    fdt32_t  off_dt_strings;       /* offset to  strings */

    fdt32_t  off_mem_rsvmap;       /* offset to  memory reserve map */

    fdt32_t  version;               /* format version */

    fdt32_t  last_comp_version;    /* last compatible  version */

 

    /*  version 2 fields below */

    fdt32_t  boot_cpuid_phys;   /* Which physical CPU  id we're booting on */

    /*  version 3 fields below */

    fdt32_t  size_dt_strings;   /* size of the  strings block */

 

    /*  version 17 fields below */

    fdt32_t  size_dt_struct;       /* size of the  structure block */

};

 

fdtdump工具的输出信息即是以上结构中每一个成员的值,struct fdt_header结构体包含了Device Tree的私有信息。例如: fdt_header.magic是fdt的魔数,固定值为0xd00dfeed,fdt_header.totalsize是fdt文件的大小。使用二进制工具打开s5pv21_smc.dtb验证。s5pv21_smc.dtb二进制文件头信息如图2所示。从图2中可以得到Device Tree的文件是以大端模式储存。并且,头部信息和fdtdump的输出信息一致。

图2头信息

Device Tree中的节点信息举例如图3所示。

  

图3设备树全景试图

上述.dts文件并没有什么真实的用途,但它基本表征了一个Device Tree源文件的结构。1个root结点"/";root结点下面含一系列子结点,本例中为"node@0"和"node@1";结点"node@0"下又含有一系列子结点,本例中为"child-node@0";各结点都有一系列属性。这些属性可能为空,如" an-empty-property";可能为字符串,如"a-string-property";可能为字符串数组,如"a-string-list-property";可能为Cells(由u32整数组成),如"second-child-property",可能为二进制数,如"a-byte-data-property"。
Device Tree源文件的结构分为header、fill_area、dt_struct及dt_string四个区域:
(1)header为头信息;
(2)fill_area为填充区域,填充数字0;
(3)dt_struct存储节点数值及名称相关信息;
(4)dt_string存储属性名。

例如:a-string-property存储在dt_string区,"A string"及node1就存储在dt_struct区域。

我们可以给一个设备节点添加lable,之后可以通过&lable的形式访问这个lable,这种引用是通过phandle(pointer handle)进行的。例如,图3中的node1就是一个lable,node@0的子节点child-node@0通过&node1引用node@1节点。像是这种phandle的节点,在经过DTC工具编译之后,&node1会变成一个特殊的整型数字n,假设n值为1,那么在node@1节点下自动生成两个属性,属性如下:
linux,phandle = <0x00000001>;
phandle = <0x00000001>;

node@0的子节点child-node@0中的a-reference-to-something = <&node1>会变成a-reference-to-something = < 0x00000001>。此处0x00000001就是一个phandle得值,每一个phandle都有一个独一无二的整型值,在后续kernel中通过这个特殊的数字间接找到引用的节点。通过查看fdtdump输出信息以及dtb二进制文件信息,得到struct fdt_header和文件结构之间的关系信息如所示。

 

   

图4 struct fdt_header和文件结构之间的关系

3 Device Tree文件结构

通过以上分析,可以得到Device Tree文件结构如图5所示。dtb的头部首先存放的是fdt_header的结构体信息,接着是填充区域,填充大小为off_dt_struct – sizeof(struct fdt_header),填充的值为0。接着就是struct fdt_property结构体的相关信息。最后是dt_string部分。

图5 Device Tree文件结构

Device Tree源文件的结构分为header、fill_area、dt_struct及dt_string四个区域。fill_area区域填充数值0。节点(node)信息使用struct fdt_node_header结构体描述。属性信息使用struct fdt_property结构体描述。各个结构体信息如下:

 

struct fdt_node_header  {

    fdt32_t  tag;

    char  name[0];

};

 

struct  fdt_property  {

    fdt32_t  tag;

    fdt32_t  len;

    fdt32_t  nameoff;

    char  data[0];

};

 

struct fdt_node_header描述节点信息,tag是标识node的起始结束等信息的标志位,name指向node名称的首地址。tag的取值如下:

 

#define FDT_BEGIN_NODE   0x1    /*  Start node: full name */

#define FDT_END_NODE  0x2    /*  End node */

#define FDT_PROP          0x3    /*  Property: name off, size, content */

#define FDT_NOP            0x4    /* nop */

#define FDT_END            0x9

 

FDT_BEGIN_NODE和FDT_END_NODE标识node节点的起始和结束,FDT_PROP标识node节点下面的属性起始符,FDT_END标识Device Tree的结束标识符。因此,对于每个node节点的tag标识符一般为FDT_BEGIN_NODE,对于每个node节点下面的属性的tag标识符一般是FDT_PROP。

描述属性采用struct fdt_property描述,tag标识是属性,取值为FDT_PROP;len为属性值的长度(包括‘\0’,单位:字节);nameoff为属性名称存储位置相对于off_dt_strings的偏移地址。

例如:compatible ="samsung,goni", "samsung,s5pv210";compatible是属性名称,"samsung,goni", "samsung,s5pv210"是属性值。compatible属性名称字符串存放的区域是dt_string。"samsung,goni", "samsung,s5pv210"存放的位置是fdt_property.data后面。因此fdt_property.data指向该属性值。fdt_property.tag的值为属性标识,len为属性值的长度(包括‘\0’,单位:字节),此处len = 29。nameoff为compatible字符串的位置相对于off_dt_strings的偏移地址,即&compatible = nameoff +off_dt_strings。

dt_struct在Device Tree中的结构如图6所示。节点的嵌套也带来tag标识符的嵌套。

图6 dt_struct结构图

4 U-Boot对Device Tree处理

//TODO


(1)uboot中可以修改设备树的内容,对设备树重新修改;

(2)uboot在启动内核时,会设置r0,r1,r2三个寄存器:
       r0一般设置为0;
       r1一般设置为machine id (在使用设备树时该参数没有被使用); 
       r2一般设置ATAGS或DTB的开始地址

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值