第十四课--MicroWRT 内核树介绍

来自Microduino Wikipedia
跳转至: 导航搜索

本节教程主要介绍Linux 内核树的概念,在3.x的linux 系统中,为了是kernel 程序保持整洁,将许多和开发板相关的代码去掉了,然后引入了 内核树的概念。下面就让我们了解一下内核树,这里只是一个简单介绍,详细的资料在网上会找到很多。


Device Tree Source诞生

在过去的linux内核里,如:ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码, 相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾, 如板上的platform设备、resource、i2c_board_info、spi_board_info 以及各种硬件的platform_data。 Device Tree是一种描述硬件的数据结构,它起源于 OpenFirmware (OF)。在Linux 2.6中, ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx,采用Device Tree后, 许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。 Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。 所谓属性,其实就是成对出现的name和 value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中):

  • CPU的数量和类别
  • 内存基地址和大小
  • 总线和桥
  • 外设连接
  • 中断控制器和中断使用情况
  • GPIO控制器和GPIO使用情况
  • Clock控制器和Clock使用情况

它基本上就是画一棵电路板上CPU、总线、设备组成的树,Bootloader会将这棵树传递给内核,然后内核可以识别这棵树, 并根据它展开出Linux 内核中的platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ等资源, 也被传递给了内核, 内核会将这些资源绑定给展开的相应的设备。

Device Tree组成和结构

.dts文件是一种ASCII 文本格式的Device Tree描述,此文本格式非常人性化,适合人类的阅读习惯。 基本上,在mips Linux,一个.dts文件对应一个mips的machine,一般放置在/target/linux/ramips/dts目录。 由于一个SoC可能对应多 个machine(一个SoC可以对应多个产品和电路板),势必这些.dts文件需包含许多共同的部分,Linux内核为了简化, 把SoC公用的部分或者 多个machine共同的部分一般提炼为.dtsi,类似于C语言的头文件。其他的machine对应的.dts就include这个.dtsi。 譬如, 对于MT762n而言,mt7620n.dtsi就被WRTNODE.dts,WRTNODE.dts所引用,WRTNODE.dts 有如下一行:

 /include/ "mt7620n.dtsi" 

当然,和C语言的头文件类似,.dtsi也可以include其他的.dtsi,譬如几乎所有的ARM SoC的.dtsi都引用了skeleton.dtsi。 .dts(或者其include的.dtsi)基本元素即为前文所述的结点和属性。 例如:m25p80的spi flash

m25p80@0 {
              #address-cells = <1>; 
              #size-cells = <1>; 
              #compatible = "mx25l6405d"; 
              compatible = "w25q128"; 
              reg = <0 0>; 
              linux,modalias = "m25p80", "w25q128"; 
              spi-max-frequency = <10000000>; 
              partition@0 { 
                  label = "u-boot"; 
                  reg = <0x0 0x30000>; 
                  read-only; 
              }; 
              partition@30000 { 
                  label = "u-boot-env"; 
                  reg = <0x30000 0x10000>; 
                  read-only; 
              }; 
              factory: partition@40000 { 
                  label = "factory"; 
                  reg = <0x40000 0x10000>; 
                  read-only; 
              }; 
              partition@50000 { 
                  label = "firmware"; 
                  reg = <0x50000 0xfb0000>; 
              }; 
          };

m25p80@0 为结点, partition@0, factory: partition@40000 是他的子结点。 compatible 属性的组织形式为<manufacturer>,<model>,别名其实就是去掉compatible 属性中逗号前的manufacturer前缀。 关于这一点,可查看drivers/spi/spi.c的源代码,函数spi_match_device()暴露了更多的细节, 如果别名出现在设备spi_driver的id_table里面,或者别名与spi_driver的name字段相同,SPI设备和驱动都可以匹配上。