linux设备树?linux便携式设备

这篇文章给大家聊聊关于linux设备树,以及linux便携式设备对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。

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文件格式的讨论就到此为止啦。

为什么linux在x86上不需要设备树,在aarch64上需要设备树

为何Linux在x86架构上无需设备树,而在Aarch64架构上需要设备树?这个问题涉及到两种架构下设备管理的不同机制。

在ARM处理器的Aarch64架构上,由于大部分设备无法自动检测到,需要一种方式让系统得知设备信息。起初,设备信息是由程序硬编码提供的,后来引入了设备树的概念。设备树为系统提供了一个描述硬件配置的层次结构,使得内核在启动时能够根据设备树配置设备。

相比之下,x86/64架构上的许多设备基于PCI/PCIe总线,能够自动枚举并发现这些设备,无需设备树直接告知系统。确实,存在一些设备无法自动枚举或自发现,但这些情况由特定的内核代码处理,使用的术语是“平台设备”。在ARM领域,设备树的概念还未普及时,平台设备的概念已存在。后来,Intel与多家厂商合作开发了ACPI(高级配置与电源管理接口),进一步增强了系统对设备信息的获取能力。

因此,可以看到,虽然x86平台没有明确的设备树机制,但通过ACPI等手段,系统同样能够获取到必要的硬件信息。然而,Aarch64架构需要设备树来管理设备配置,以确保系统在启动时能够正确识别和配置硬件资源。这反映了不同架构下硬件管理策略的差异。

linux设备树驱动exynos4412怎么写

linux设备树驱动exynos4412怎么写

系统调用是操作系统内核和应用程序之间的接口,设备驱动程序是操作系统内核和机器硬件之间的接口。设备驱动程序为应用程序屏蔽了硬件的细节,这样在应用程序看来,硬件设备只是一个设备文件,应用程序可以象操作普通文件一样对硬件设备进行操作。设备驱动程序是内核的一部分,它完成以下的功能:

1、对设备初始化和释放。

2、把数据从内核传送到硬件和从硬件读取数据。

3、读取应用程序传送给设备文件的数据和回送应用程序请求的数据。

4、检测和处理设备出现的错误。

在Linux操作系统下有三类主要的设备文件类型,一是字符设备,二是块设备,三是网络设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。

已经提到,用户进程是通过设备文件来与实际的硬件打交道。每个设备文件都都有其文件属性(c/b),表示是字符设备还是块设备?另外每个文件都有两个设备号,第一个是主设备号,标识驱动程序,第二个是从设备号,标识使用同一个设备驱动程序的不同的硬件设备,比如有两个软盘,就可以用从设备号来区分他们。设备文件的的主设备号必须与设备驱动程序在登记时申请的主设备号一致,否则用户进程将无法访问到驱动程序。

最后必须提到的是,在用户进程调用驱动程序时,系统进入核心态,这时不再是抢先式调度。也就是说,系统必须在你的驱动程序的子函数返回后才能进行其他的工作。如果你的驱动程序陷入死循环,不幸的是你只有重新启动机器了,然后就是漫长的fsck。

读/写时,它首先察看缓冲区的内容,如果缓冲区的数据未被处理,则先处理其中的内容。

阅读剩余
THE END