参考设备树内容
/dts-v1/; / { model = "this is my devicethree!"; #address-cells = <1>; #size-cells = <1>; chosen { bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200"; }; cpu: cpu@1 { device_type = "cpu"; compatible = "arm,cortex-a35","arm,armv8"; reg = <0x0 0x1>; }; aliases{ led1 = "/gpio22020101"; }; node1{ #address-cells = <1>; #size-cells = <1>; gpio@22020101{ reg=<0x20110102 0x40>; }; }; node2{ node1-child{ pinnum = <0 1 2 3 4>; }; }; gpio@22020101{ reg=<0x20110101 0x40>; status="okay"; }; };
编译得到dtb文件
/home/alientek/linux/IMX6ULL/linux/temp/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek/scripts/dtc/dtc -I dts -O dtb -o my_device_tree.dtb my_device_tree.dts
使用软件查看生成的dtb文件
DTB文件格式
DTB文件格式主要分为四个部分:header(头部),memory reservation block(内存预留块),structure block(结构块),strings block(字符串块)。free space(自由空间)
不一定存在。
分布 |
struct fdt_header
free space
memory reservation block
free spacestructure block
free spacestrings block
free space
1.header头部
struct fdt_header { uint32_t magic; /* magic word FDT_MAGIC */ // FDT_MAGIC 魔数 uint32_t totalsize; /* total size of DT block */ // DT块的总大小 uint32_t off_dt_struct; /* offset to structure */ // 结构体的偏移量 uint32_t off_dt_strings; /* offset to strings */ // 字符串的偏移量 uint32_t off_mem_rsvmap; /* offset to memory reserve map */ // 内存保留映射的偏移量 uint32_t version; /* format version */ // 格式版本 uint32_t last_comp_version; /* last compatible version */ // 最后兼容版本 /* version 2 fields below */ uint32_t boot_cpuid_phys; /* Which physical CPU id we're booting on */ // 我们正在启动的物理CPU ID /* version 3 fields below */ uint32_t size_dt_strings; /* size of the strings block */ // 字符串块的大小 /* version 17 fields below */ uint32_t size_dt_struct; /* size of the structure block */ // 结构块的大小 };
注意:所有成员类型均为32u,为大端模式
1.magic
magic的值必须是0xd00dfeed。打开文件。
2.totalsize
totalsize表示dtb文件的大小。例子中dtb文件大小为676字节。如下图所示:
totalsize的类型为u32,,所以676字节转换成16进制是0x000002a4。打开文件dtb。
3.off_dt_struct
off_dt_struct表示structure block(结构块)在dtb文件中的偏移地址。dtb文件中off_dt_struct的值是0x00000038。
所以structure block(结构块)从下图开始
4.off_dt_strings字符串的偏移量
off_dt_strings表示(字符串块)在dtb文件中的偏移地址。dtb文件中off_dt_strings的值为0x0000024c。
所以strings block(字符串块)从下图位置开始。
5.off_mem_rsvmap 内存保留映射的偏移量
off_mem_rsvmap表示memory reservation block(内存预留块)在dtb文件中的偏移地址,dtb文件中off_mem_rsvmap的值是0x00000028。
所以memory reservation block(内存预留块)从下图位置开始。
6.version 格式版本
version表示设备树数据结构的版本,version的值为0x0000011,对应版本为17。
7.last_comp_version最后兼容版本
last_comp_version表示向后兼容的版本,17版本向后兼容16版本,所以last_comp_version的值为16。
8.boot_cpuid_phys 我们正在启动的物理CPU ID
cpu的id值,它的值应该与设备树文件中CPU节点下的reg属性值相等。boot_cpuid_phys为0。
9.size_dt_strings字符串块的大小
size_dt_strings表示strings block(字符串块)的大小。size_dt_strings的值为0×000000058。
size_dt_strings的偏移为Ox0000024c,大小为0×00000058,0×25C+58=2a4,所以可以知道strings block(字符串块)在dtb文件中的范围。如下图所示
10.size_dt_struct 结构块的大小
size_dt_struct表示structure blockl(结构块)的大小。size_dt_struct的值为0×00000214。
off_dt_struct的偏移值是0×00000038。所以结构块在dtb文件中的范围,如下图所示:0×00000038+0×00000214=24c
2.memory reservation block(内存预留块)
如果在dts文件中使用memreserve描述保留的内存,保留内存的大小就会在这部分保存。
memreserve的使用方法:
/memreserve/ <address> <length>;
eg
//reserve memory region 0x10000000 .0x4000 /memreserve/ 0x10000000 0x4000;
在内存保留块的存储格式:
struct fdt_reserve_entry { uint64_t address; // 地址 uint64_t size; // 大小 };
3.structure block(结构块)
结构块描述的是设备树的结构,也就是设备树的节点。那如何表示一个节点的开始和结束呢。
使用0x00000001表示节点的开始,然后跟上节点名字(根节点的名字用0表示),然后
使用0x00000003表示一个属性的开始(每表示一个节点,都要用0x00000003表示开始),
属性的名字和值用结构体表示。
struct fdt_property { uint32_t tag; // 标签 uint32_t len; // 长度 uint32_t nameoff; // 名称偏移量 char data[0]; // 数据 };
len表示属性值的长度,nameoff表示属性名字在字符串块中的偏移。使用0x00000002表示
节点的结束。使用表示根节点的结束。也就是整个结构块的结束。
例子中以下节点在dtb中是如何表示的呢?
/ { model = "this is my devicethree!"; #address-cells = <1>; #size-cells = <1>; chosen { bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200"; };
如下图所示:
4.strings block(字符串块)
字符串块用来存放属性的名字,比如compatible,reg等。通过分析dtb的头部,我们已经知道字符串块的位置,如model在dtb中的表示:
0x6D6F6465表示的是model的acell码,表示完一个字符串,用00结尾。