linux dtb?linux嵌入式软件开发

本篇文章给大家谈谈linux dtb,以及linux嵌入式软件开发对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

Linux内核DTB文件启动的几种方式

Device Tree简介

Linus Torvalds在2011年提出Device Tree概念,作为一种硬件描述数据结构,它源于OpenFirmware。在Linux2.6中,ARM架构的板级硬件细节过多地被硬编码在内核中。Device Tree引入后,许多硬件细节可以直接传递给Linux,减少内核中的冗余编码。

Device Tree由结点和属性组成,描述硬件信息如CPU、总线、设备的连接关系。Bootloader将Device Tree传递给内核,内核识别并展开硬件,创建如platform_device、i2c_client等设备对象。

Device Tree编译

Device Tree文件(dts)需编译为dtb格式,便于Linux和Bootloader识别。编译工具是dtc,可以通过在Linux源码目录下执行命令安装。

早期Linux内核启动

早期Linux内核通过硬编码的方式描述硬件信息,如在arch/arm/mach-xxx文件中。zImage文件需要通过u-boot转换为uImage后,通过bootm命令启动。

设备树启动

Linux-3.x后内核统一启用Device Tree,硬件信息描述在dts文件中。编译内核时使用make dtbs生成dtb文件。启动时需要加载uImage和dtb文件。

设备树和uImage合并

dtb文件将硬件信息与内核分离,通过合并uImage和dtb文件,可为不同硬件开发板提供统一内核。例如,使用cat命令合并文件后,使用mkimage生成uImage文件。

u-boot FIT image合并

使用FIT Image格式合并uImage和dtb文件。FIT Image利用Device Tree Source files语法,通过mkimage命令生成itb文件。u-boot需要配置支持FIT Image启动。

总结

Device Tree提供了一种灵活的硬件描述方式,使内核与硬件解耦。通过合并uImage和dtb文件,或使用FIT Image格式,可简化启动流程,支持不同硬件开发板。

请教linux启动过程中dtb的作用

dtb文件作用的描述是,使用dtb可以减少linux内核版本的数量。同一份linux内核代码可以在多个板卡上运行,每个板卡可以使用自己的dtb文件。

1,在linux内核启动过程中会解析dtb文件,根据dtb文件中设备列表进行加注各个外设的驱动模块。

2,PC机在启动时会自动扫描外设,而在嵌入式中,linux内核启动过程中只是解析dtb文件,从而加载对应的模块。

3,编译linux内核时必须选择某外设模块,并且dtb中包括该外设的信息。在linux内核启动过程中才能自动加载该模块。

要使用dtb,需要uboot启动内核时,在bootm命令中指定dtb的位置,格式为:

bootm uImage_addr ramdisk_addr dtb_addr

如果没有ramdisk,就需要写成bootm uImage_addr- dtb_addr,用“-”表示没有ramdisk

linux设备驱动程序——设备树(0)-dtb格式

设备树的一般操作方式是:开发人员根据开发需求编写dts文件,然后使用dtc将dts编译成dtb文件。

dts文件是文本格式的文件,而dtb是二进制文件,在linux启动时被加载到内存中,接下来我们需要来分析设备树dtb文件的格式。

为什么要了解设备树dtb文件的格式

dtb作为二进制文件被加载到内存中,然后由内核读取并进行解析,如果对dtb文件的格式不了解,那么在看设备树解析相关的内核代码时将会寸步难行,而阅读源代码才是了解设备树最好的方式,所以,如果需要更透彻的了解设备树解析的细节,第一步就是需要了解设备树的格式。

dtb格式总览

dtb的格式是这样的:

dtb header

但凡涉及到数据的记录,就一定会有一个总的描述部分,就像磁盘的超级块,书的目录,dtb当然也不例外,这个描述头部就是dtb的header部分,通过这个header部分,用户可以快速地了解到整个dtb的大致信息。

header可以用这么一个结构体来描述:

magic

设备树的魔数,魔数其实就是一个用于识别的数字,表示设备树的开始,linux dtb的魔数为 0xd00dfeed.

totalsize

这个设备树的size,也可以理解为所占用的实际内存空间。

off_dt_struct

offset to dt_struct,表示整个dtb中structure部分所在内存相对头部的偏移地址

off_dt_strings

offset to dt_string,表示整个dtb中string部分所在内存相对头部的偏移地址

off_mem_rsvmap

offset to memory reserve map,dtb中memory reserve map所在内存相对头部的偏移地址,

version

设备树的版本,截至目前的最新版本为17.

last_comp_version

最新的兼容版本

boot_cpuid_phys

这部分仅在版本2中存在,后续版本不再使用。

size_dt_strings

表示整个dtb中string部分的大小

size_dt_struct

表示整个dtb中struct部分的大小

alignment gap

中间的alignment gap部分表示对齐间隙,它并非是必须的,它是否被提供以及大小由具体的平台对数据对齐和的要求以及数据是否已经对齐来决定。

memory reserve map

memory reserve map:描述保留的内存部分,这个map的数据结构是这样的:

这部分存储了此结构的列表,整个部分的结尾由一个数据为0的结构来表示(即physical_address和size都为0,总共16字节)。

这一部分的数据并非是节点中的memory子节点,而是在设备开始之前(也就是第一个花括号之前)定义的,例如:

这一部分的作用是告诉内核哪一些内存空间需要被保留而不应该被系统覆盖使用,因为在内核启动时常常需要动态申请大量的内存空间,只有提前进行注册,用户需要使用的内存才不会被系统征用而造成数据覆盖。

值得一提的是,对于设备树而言,即使不指定保留内存,系统也会默认为设备树保留相应的内存空间。

同时,这一部分需要64位(8字节)对齐。

device-tree structure

device-tree structure:每个节点都会被描述为一个struct,节点之间可以嵌套,因此也会有嵌套的struct。

structure的的结构是这样的:

device-tree strings

device-tree strings:在dtb中有大量的重复字符串,比如"model","compatile"等等,为了节省空间,将这些字符串统一放在某个地址,需要使用的时候直接使用索引来查看。

需要注意的是,属性部分格式为key= value,key部分被放置在strings部分,而value部分的字符串并不会放在这一部分,而是直接放在structure中。

dtb文件解析示例

光说不练假把式,下面我就使用一个简单的示例来剖析dtb的文件格式。

下述示例仅仅是一个演示demo,不针对任何平台,为了演示方便,编写了一个非常简单的dts文件。/dts-v1/;/{

编译当前dts文件,获取对应的dtb文件。

鉴于dtb文件为二进制文件,普通编辑器打开显示乱码,我们使用ultraEdit查看,它将数据以16进制形式显示:

整个dtb文件还是比较简单的,图中的红色框出的部分为header部分的数据,可以看到:

整个头部为40字节,16进制为0x28,从头部信息中off_mem_rsvmap部分可以得到,reserve memory起始地址为0x28,上文中提到,这一部分使用一个16字节的struct来描述,以一个全为0的struct结尾。

后16字节全为0,可以看出,这里并没有设置reserve memory。

structure部分

上文回顾:每一个属性都是以 key= value的形式来描述,value部分可选。

偏移地址来到0x00000038(0x28+0x10),接下来8个字节为00000003,根据上述structure中的描述,这是OF_DT_PROP,即标示属性的开始。

接下来4字节为00000018,表明该属性的value部分size为24字节。

接下来4字节是当前属性的key在string部分的偏移地址,这里是00000000,由头部信息中off_dt_strings可以得到,string部分的开始为00000174,偏移地址为0,所以对应字符串为"compatible".

之后就是value部分,这部分的数据是字符串,可以直接从图片右侧栏看出,总共24字节的字符串"hd,test_dts","hd,test_xxx",因为字符串之间以0结尾,所以程序可以识别出这是两个字符串。

可以看出,到这里,compatible="hd,test_dts","hd,test_xxx";这个属性就被描述完了,对于属性的描述还是非常简单的。

按照固有的规律,接下来就是对#address-cells=<0x1>的解析,然后是#size-cells=<0x1>...

然后就是递归的子节点chosen,memory@80000000等等都是按照上文中提到的structure解析规则来进行解析,最后以00000002结尾。

与根节点不同的是,子节点有一个unit name,即chosen,memory@80000000这些名称,并非节点中的.name属性。

而整个结构的结束由00000009来描述。

一般而言,在32位系统中,dtc在编译dts文件时会自动考虑对齐问题,所以对于设备树的对齐字节,我们只需要有所了解即可,并不会常接触到。

好了,关于linux设备树dtb文件格式的讨论就到此为止啦。

阅读剩余
THE END