深入了解Linux DTSI文件:硬件描述与设备树的关系 (linux dtsi文件)

Linux操作系统中的设备树(Device Tree)是描述硬件细节的一种数据结构,它用于描述操作系统每个子系统中的设备。设备树源文件(.dts或.dtb文件)是一种文本或二进制文件,其中包含设备树的详细描述。Linux内核的设备树是使用DTSI文件定义的,本文将深入了解DTSI文件对硬件描述和设备树的关系。

DTSI文件是Device Tree Source Include的缩写,它是用于定义设备树中设备的通用硬件描述文件。通常情况下,软件开发人员使用DTSI文件来描述芯片或模块中所包含的所有设备。这使得DTSI文件成为设备树源文件中非常重要的元素。由于芯片和模块通常会使用相同的设备,因此DTSI文件还可以被重复使用,以避免编写重复代码。

DTSI文件中的语法与常规的Device Tree Source Files(DTS文件)非常相似,但DTSI文件作为可重用的硬件描述文件,它通常包含较少的具体设备信息和较多的基础设施信息。与DTS文件一样,DTSI文件的语法由Device Tree Compiler(DTC)工具统一识别。

DTSI文件中的设备描述通常不是直接的硬件描述,而是包含了指向其他DTSI文件的路径。这些路径用来描述硬件层次结构,设备树编译器使用这些路径来自动为每个设备构建设备树。

DTSI文件与设备树的关系可以通过一个例子来理解。假设我们需要为嵌入式设备设计一个新的板子,这个板子有多个设备,比如GPIO、网络接口、显示器等。为了让操作系统识别这些设备,我们需要使用设备树描述它们。此时,我们可以使用一个DTSI文件来描述通用设备(比如GPIO),使用另一个DTSI文件来描述特定设备(比如网络接口),并将这些DTSI文件添加到板子的DTS文件中。这样做可以让我们重用代码,而不是每次都从头编写硬件描述。

DTSI文件中还可以定义设备树的属性与标签。这些属性和标签可以使操作系统了解设备的详细情况并进行适当的驱动程序匹配。例如,在我们的板子上,我们可以定义GPIO设备的引脚数、电压等级和信号类型等属性,以便操作系统可以选择适当的GPIO驱动程序。

DTSI文件对Linux设备树描述非常重要。它提供了硬件描述的通用管理方式,使得设备树可以非常灵活地管理硬件信息。DTSI文件的健壮性和可重用性使得它成为嵌入式设备开发中不可或缺的组成部分。理解DTSI文件的语法和作用,将有助于更好地利用Linux设备树,并能更好地管理硬件资源。

相关问题拓展阅读:

linux下dts文件中断号怎么设置

使用chmod 这个命令来对文件夹修改权限例如对tmp目录下面的aaa文件夹修改权限r 是读权限 用数字表示是 4 w 是写权丛档限 用数字表示是 2x 是执行权限 用睁颤数字表示是 1chmod 644 /tmp/aaa6代表是所有者权限渗早乱4 代表是用户组权限4代表是其他用户权限

编译linux内核设备树文件使用什么命令

Linux源码的arch/powerpc/boot/dts/目录下存放了很多大弊dts文件,可以作为参考文件。另外dtc编译器在内核源码2.6.25版亩仔本之后已经被包含进去。在2.6.26版本之后,生成blob的简单规则已经加入makefile,如下命令:迅仿汪

  $ make ARCH=powerpc canyonlands.dtb

  也可以根据自己的硬件修改好dts文件后,用下面类似命令生成dtb文件。

  $ dtc -f -I dts -O dtb -R 8 -S 0x3000 test.dts > mpc836x_mds.dtb

  $ mkimage -A ppc -O Linux -T flat_dt -C none -a 0xe 0 -d mpc836x_mds.dtb mpc836x_mds.dtu

如何在ARM Linux上使用FDT和initrd

这文章算是最近工作的备忘。

FDT是ARM

Linux最新的设备驱动程序信息表,使用FDT的内核,就不用像过去的内核那样,一个板子加一个mach的C文件,所有的设备信息可以记录在一个树状信息文件里面。

目前这方面资料比较少,我以AM335x处理器为例激哗洞概括一下FDT的使用:

FDT仅仅是一个信息的目录和参数表,要使用某个功能内核中还必须有相应的驱动程序代码

FDT的源文件位置在:arch/arm/boot/dts,例如,TI的Beagle bone black,源文件是arch/arm/boot/dts/am335x_boneblack.dts

FDT在make ARCH=arm的时候就会自动生成,也可用make ARCH=arm

dtbs来生成,例如TI的Beagle bone black生成的文件是arch/arm/boot/dts/am335x_boneblack.dtb,这是一个二进制文件

要想新增你自定义的FDT,请修改arch/arm/boot/dts/Makefile,并在相应的Kconfig中增加config选项,例如,TI的Beagle

bone black,Kconfig的位置在arch/arm/mach-omap2/Kconfig

FDT的dtb文件由u-boot传递给内核,u-boot必须把这个文件拷贝到内核解压地址之后的某个位置,确保内核解压的时候不会覆盖,然后使用“bootm

– ”来启动内核

如果dtb文件不正确,对于3.10以上的内核,可能什么显示都没有,3.8内核,可能就显示到Uncompressing kernel……done

FDT的编写规则说明在Documentation/devicetree/bindings,不同的设备有相应的txt文件说明,其中的“compatible”可以作为关键字搜索驱动程序的源文件,例如,AM335x的GPIO,用“ti,omap4-gpio”为关键字,可以找到其代码位于drivers/gpio/gpio-omap.c

FDT可以包明枯含子文件,比如am335x_boneblack.dts就包含了am33xx.dtsi,am335x-bone-common.dtsi

以一个例子来说明编写规则,我的板子上,I2C0上挂了一个音频CODEC,其地址是0x18,型号是TLV320AIC3104IRH。

先找到i2c0节点的位置,这在arch/arm/boot/dts/am33xx.dtsi中:

i2c0: i2c@44e0b000

{

compatible =

“ti,omap4-i2c”;

#address-cells =

;

#size-cells =

;

ti,hwmods =

“i2c1”;

reg = ;

interrupts =

;

status =

“disabled”;

};

要在这个节点上挂东西,可以直接在am33xx.dtsi中挂,可以写成这样:

i2c0: i2c@44e0b000

{

compatible =

“ti,omap4-i2c”;

#address-cells =

;

#size-cells =

;

ti,hwmods =

“i2c1”;

reg = ;

interrupts =

;

status =

“okay”;

tlv320aic3x: tlv320aic3x@18 {

compatible = “ti,tlv320aic3x”;

reg = ;

status = “okay”;

AVDD-supply = ;

IOVDD-supply = ;

DRVDD-supply = ;

DVDD-supply = ;

};

};

其中compatible字串“ti,tlv320aic3x”是在Documentation/devicetree/bindings里面全文搜索“tlv320aic”获得的,“tlv320aic3x:

tlv320aic3x@18”遵循的是“标识符:名称@地址”的格式,前面的“i2c0:

i2c@44e0b000”也是这个格式。这里的标识符可以在芦绝包含这个文件的文件或这个文件的其他位置引用,因此,可以使用arch/arm/boot/dts/am335x-boneblack.dts包含arch/arm/boot/dts/am33xx.dtsi,然后在am335x-boneblack.dts里写:

&i2c0 {

status = “okay”;

tlv320aic3x: tlv320aic3x@18 {

compatible = “ti,tlv320aic3x”;

reg = ;

status = “okay”;

AVDD-supply = ;

IOVDD-supply = ;

DRVDD-supply = ;

DVDD-supply = ;

};

};

&i2c0表示引用了i2c0这个标识符,然后把括号里的内容挂载到标识符下,如果属性的名字相同,例如status出现两次,前面是“disabled”后面是“okay”,以后面的为准,引用标识符的次数不受限制。

也许一开始会觉得FDT的工作过程很神秘,但你只要用compatible的字串去全文搜索一下C文件,然后仔细阅读一下,就会发现很简单,没过几分钟你就可以自定义FDT节点的属性了。反倒是这些操作过程我没找到什么文档说,比较头痛,所以我把这些写出来,希望能给大家帮助。

下面说说initrd,initrd的用处是给内核一个初始的基本文件系统,用来加载内核模块之类的东西。很多人觉得嵌入式系统不需要initrd,也可以把initrd作为最终的根文件系统。我用initrd是用来校验真正的根文件系统,因为在嵌入式设备上,无法预测用户到底什么时候关机,可能会造成文件系统问题。

initrd可以用buildroot,像制作正常文件系统一样做,最后把根下的linuxrc换成一个例如下面这样的文件:

#!/bin/sh

/bin/echo Now Check SD Card

/in/fsck.ext4 /dev/mmcblk0p5

虽然Documentation/initrd.txt里面说,内核会执行initrd里面的/in/init,但在我用的linux-3.8.13上,init/do_mounts_initrd.c里面,执行的是/linuxrc,不知道是不是文档没有更新过来。具体的调用顺序是,kernel_init(init/main.c)

> kernel_init_freeable(init/main.c)

> prepare_namespace(init/do_mounts.c)

> initrd_load(init/do_mounts_initrd.c) > handle_initrd

(init/do_mounts_initrd.c)。

在使用initrd的时候有几点需要注意的:

不建议在initrd上挂载别的东西,会引起未知的问题,貌似看到个文章说这个,找不到了

因为上面的这条,而且在initrd的时候,内核还没有挂载devtmpfs,因此建议使用静态设备节点,以AM335x为例(内核参数console=/dev/ttyO0,115200n8),必须的节点有:

/dev/null

/dev/console

/dev/ttyO0

这些节点可以用fakeroot之后mknod在buildroot的output/target/dev里创建,除了/dev/console,buildroot会自己创建,其他也可以写到buildroot的system/device_table.txt里面让buildroot自动创建:

#

/dev/null

c

/dev/ttyO0 c

如果你用的是Atmel的处理器,上面的ttyO0可能是ttyS0,如果是三星的,可能是ttySAC0,而且major和minor也会不一样,请自行解决。如果你像我一样要检验SD卡,那就还必须加上SD卡的分区对应的节点。

/linuxrc可以是个程序也可以是个脚本,脚本的话,命令写绝对路径,而且记得把/linuxrc的mode改为755

使用initrd只需要用u-boot把buildroot制作的文件系统映像拷贝到内存里,然后传递initrd=,这样的参数给内核,例如initrd=0x,8M,最终的root参数可以不变,例如root=/dev/mmcblk0p5,这表示最终的root是SD卡上扩展分区中的之一个逻辑分区。给两个内核参数的例子:

console=ttyO0,115200n8 root=/dev/mmcblk0p5 initrd=0x,8M vram=16M

consoleblank=0

console=ttyO0,115200n8 initrd=0x,8M root=/dev/nfs rw

nfsroot=192.168.5.226:/home/cdu/nfsroot

ip=192.168.5.222:192.168.5.226:192.168.5.1:255.255.255.0:core335x:eth0:off

vram=16M consoleblank=0

之一个不解释了,第二个表示使用initrd,同时使用nfsroot。

关于linux dtsi文件的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » 深入了解Linux DTSI文件:硬件描述与设备树的关系 (linux dtsi文件)