原文:eLinux.org
翻译:@sdfd
校订:@lzufalcon
设备树数据可以表示成几种不同的格式。它是由 Open FirmWare1封装平台信息的设备树格式发展而来,被移植到 Linux 操作系统中。使用 .dts
源文件和 .dtsi
头文件创建和维护一个典型的设备树。Linux 编译器会对其进行预处理。
设备树源码被编译成一个 .dtb
的二进制文件。.dtb
二进制文件的数据格式通常参考扁平设备树(FDT)。Linux 操作系统通过设备树数据去寻找并在系统中注册设备。FDT 在启动时的很早时刻存取,但是为了在启动后期和系统完全启动后更有效率的存取,它被扩展进内核内部的数据结构中。
目前,Linux 内核可以支持 ARM,x86,Microblaze,PowerPC 和 Sparc 架构读取设备树信息。拓展设备树对其他平台的支持,通过内核架构统一处理平台描述是我们所关注的。
扁平设备树(FDT)仅仅是一个数据结构。
它描述了一个机器设备的硬件配置。它是从 Open FirmWare 设备树格式中发展而来。其格式可以体现和描述大多数板级硬件设计,包括:
像 initrd 镜像一样,FDT 也可以被静态的链接进内核或者在 boot 启动时传递给内核。
arch/arm/mach-*
),而把精力放在设备驱动开发上。
一些平台板子相关的特性使用 C 数据结构从 bootloader 向内核传递数据。著名的有嵌入式 PowerPC 在 FDT 数据结构之前支持的标准。
PowerPC 示范的经验提示我们使用自定义的 C 数据结构对于少量的数据确实是有利的解决方案。但是它引起了长期的可维护问题,而且总体上来说它没有尝试去解决描述板级配置的问题。随着这种特有情况的发展,没有办法决定什么版本的数据结构合金内核代码中。PowerPC 的板级信息结构用 #ifdef
搞得一团糟,修改的很丑陋,它还仅仅是传递一小点像内存大小和网卡 MAC 地址这样的数据。
ATAGs 以优雅的方式--通过定义友好的命名空间传递个体的数据项(内存区域,初始化地址等),操作系统能可靠的解析这些参数。然而,只有一打或者只有 ATAG 被定义是不能足够的表达对板子设计的描述。使用 ATAGs 本质上需要一个分离的机器号去配置每一个板子变体,即使他们给予相同的设计。
尽管如此,ATAG 仍是一个理想的向内核传递 FDT 镜像的方法,其同时被用来传递启动地址。
固件由差异化系统描述表(DSDT)提供高级配置与电源接口硬件描述的配置文件。ACPI 应用于 x86 兼容机系统,其由经典 IBM PC BIOS 发展而来。
可扩展固件接口 是一个从平台固件到操作系统传递控制命令的规范接口。它由英特尔设计,被用来代替 PC 的 BIOS 接口。
ARM 控制着 UEFI 社区的成员。这就不难想象 UEFI 由 ARM 实现。
Open FirmWare 是 Sun 公司在 20 世纪 80 年代后期设计的一个固件接口规范,移植到了很多架构中。它指定一个运行时操作系统的客户端接口,交叉平台的设备接口,用户接口和描述机器布局的设备树。
FDT 之于 Open FirmWare 就像 DSDT 之于 ACPI。FDT 重用了 Open FirmWare 已经确定了的设备树布局。事实上,Linux PowerPC 支持使用相同的代码库同时支持 Open FirmWare 和 FDT 平台。
大多数竞品的解决方案像上面列出的包括机器描述和运行时服务的功能丰富的固件接口。相反的,FDT 只是一个数据结构,并不指定任何固件接口细节。使用 FDT 端口的板子的典型的启动过程是由类似 U-Boot 这样的简单的固件实现的,其不提供任何形式的运行时服务。
功能丰富的接口的共同的设计目标是提供一个抽象的启动接口,其只受不同硬件平台的差异的影响,其至少要能初始化操作系统自己本地的设备驱动。一个想法是在新的硬件上启动老的操作系统镜像,像 Linux 的 LiveCD 镜像不需要明确知道硬件配置那样,但是需要依赖固件给其提供信息。
典型的嵌入式固件设计目标是:a)尽可能快的启动系统 b)升级系统镜像 c)可能还需要在初始化板子时提供一些低等级的 debug 调试支持。关注点倾向于系统一旦从内核直接驱动硬件启动后就远离固件(不需要依赖固件运行时服务)。事实上,不建议进行固件升级,因为固件升级可能带来板子无法启动的风险。嵌入式系统中的 ACPI,UEFI 和 Open FirmWare 解决方法通常启动的并不快,虽然可能更好一点,比需要的更复杂一点。就这一点而言,FDT 的方法因其简单而更有优势。如:FDT 提供类似的表示方法去描述硬件,但是它可以工作在现存的固件上,也可以升级而不需要刷新固件。
设备树主要的wiki在: http://www.devicetree.org/Main_Page 对设备树的概念进行了很好的介绍,并用源码来更形象的表述这些概念。(但是在于其他的资源比较的时候请检查页面底部最新的修改日期(当前是 2010.10.23)) 在 Linux 内核文档目录可以找到设备树的参考资料:Documentation/devicetree
。请参考https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree
一些很有用的文件:
-name
属性 包含一个名字对应其他性质的一个命令列表请看 Linux 设备树指南
在 Linux 源码树种描述设备树支持的文档(2006年的信息):Documentation/powerpc/booting-without-of.txt
设备树编译器(dtc)-在人类可编辑的设备树源码“dts”格式和用于内核或者汇编源码的紧凑的设备树二进制“dtb”之间转换。Dtc 也是 dtb 的逆编译器。
scripts/dtc/
中维护git clone git://git.kernel.org/pub/scm/utils/dtc/dtc.git
Xilinx EDK 设备树生成器-从 Xilinx FPGA 的设计文件中生成 FDT
设备树生成器是一个 Xilinx EDK 工具,拥有 BSP 自动生成的特性
你可以设置 CONFIG_PROC_DEVICETREE
使你可以在系统启动后从 /proc 中看到设备树信息。当此项被设置成“Y”后重新编译内核,然后启动内核,输入命令cd /proc/device-tree
对于新的不存在 CONFIG_PROC_DEVICETREE
选项的内核,当 CONFIG_PROC_FS
被设置成”Y”时会创建 /proc/device-tree
。你也可以尝试 CONFIG_DEBUG_DRIVER=Y
。
另外,通常你可以在一个独立的 c 文件中设置#define DEBUG 1
,在此文件中添加日常活动的调试语句。这将激活源码中任何 pr_debug()
语句。
或者,你可以增加以下语句到 drivers/of/Makefile
中:
CFLAGS_base.o := -DDEBUG
CFLAGS_device.o := -DDEBUG
CFLAGS_platform.o := -DDEBUG
CFLAGS_fdt.o := -DDEBUG
设备树 irc 通道是在 freenode.net 上的 #devicetree。
2013年7月更新
http://vger.kernel.org/vger-lists.html#devicetree
存档:http://www.spinics.net/lists/devicetree/
2013年7月之前
https://lists.ozlabs.org/listinfo/devicetree-discuss
存档: http://news.gmane.org/gmane.linux.drivers.devicetree
译者注:第一个无版权的引导固件,它可兼容不同的处理器和总线,是 PowerPC 和 CHRP(共用硬件参考平台)所必需的,其由 IEEE 1275-1994 标准定义。
↩