|
[导读] 新版的U-Boot以及内核都引入了设备树,那么这究竟是棵什么样的树呢?长啥样?有啥用?为啥弄个这样的树?本文基于对设备树标准的理解,来学习整理一下相关的要点,供大家参考。 Linux为啥要设备树? 在Linux3.x之前的内核源码中,存在大量对板级细节信息描述的代码。这些代码充斥在/arch/arm/plat-xxx和/arch/arm/mach-xxx目录,而且更严重的问题是,由于ARM商业生态模式,基于ARM IP授权模式,产生越来越多ARM核芯片。如此一来这类辣鸡代码越来越多,维护变得愈加困难。于是在2011年3月17这天,Linux之父Linus Torvalds飙了,邮件中骂到:“this whole ARM thing is a f*cking pain in the ass”。
自此之后,Linux内核引入了设备树机制以描述计算机板机底层硬件信息。
设备树(device tree)是一种描述特定计算机的硬件组件的数据结构,以便操作系统的内核或者引导程序可以使用和管理那些组件,包括一个或多个CPU,内存,总线和外围设备 。为什么说这个数据结构是树呢? 设备树是通过Open Firmware项目从基于SPARC的工作站和服务器发展而来,由http://www.devicetree.org/组织维护,目前的发展至V0.3版。 来看看设备树标准中的例子:该图显示了一个简单的设备树的示例表示,该树几乎完整到足以启动一个简单的操作系统,描述了平台类型,CPU,内存和1个UART。看这个图,正是一种树形数据结构。
节点 设备树数据结构,本质上由一系列带属性的节点组成,节点由节点名、单元地址以及属性组成。描述节点的语法为: node-name@unit-address
那么上图的节点是哪些呢?移除掉属性简化一下:
节点的单元地址特定于节点所在的总线类型。单元地址必须与节点的r一般与reg属性中指定的第一个地址匹配。如果节点不具有reg属性,则必须省略@ unit-address,并且节点名称仅会将节点与树中同一级别的其他节点区分开。特定总线的绑定可以为reg和unit-address的格式指定其他更具体的要求。 节点名称,一般按照功能描述进行命令,以提升可读性,比如:
路径名path name 通过指定从根节点到所有后代节点到所需节点的完整路径,可以唯一标识设备树中的节点。按照下述约定进行描述: /node-name-1/node-name-2/node-name-N比如上图中CPU1的路径为: /cpus/cpu@1属性语法 属性用于描述节点的特征,由属性名及值组成。
phandle = <1>; interrupt-controller; }; 定义的phandle值为1。另一个设备节点可以使用一个phandle值1引用pic节点: another-device-node {interrupt-parent = <1>; };
compatible = "simple-bus"; #address-cells = <1>; #size-cells = <1>; ranges = <0x0 0xe0000000 0x00100000>; serial@4600 { device_type = "serial"; compatible = "ns16550"; reg = <0x4600 0x100>; clock-frequency = <0>; interrupts = <0xA 0x8>; interrupt-parent = <&ipic>; }; }; 其中: <0x0 0xe0000000 0x00100000>;此属性值指定对于1024 KB的地址空间范围,以物理0x0寻址的子节点映射到物理0xe0000000的父地址。通过这种映射,可以通过地址为0xe0004600的加载或存储,偏移量0x4600(在reg中指定)和在range中指定的0xe0000000映射来寻址串行设备节点。
总结一下 本文总结了Linux设备树出现的缘由,以及设备树节点常规概念:节点、属性,以及标准属性。设备树还有中断以及中断映射、设备绑定、二进制格式等概念,后续有时间在学习整理。 |
微信公众号
手机版