一. 简介
 每个节点都有  compatible  属性,根节点 “ /” 也不例外。 imx6ull-alientek-emmc.dts 设备树 文件中的根 节点下也有一个  compatible  属性。 
 
 
本文继续学习设备树文件的语法。具体学习根节点 "/" 下的 compatile属性的作用。
二. 设备树根节点下的compatile属性的作用
下面以 imx6ull-alientek-emmc.dts设备树文件为例,imx6ull-alientek-emmc.dts 文件中根 节点的 compatible 属性内容如下所示:
/ {model = "Freescale i.MX6 ULL 14x14 EVK Board";compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";chosen {stdout-path = &uart1;};
........................................
}; 可以看出, compatible  有两个值:“ fsl,imx6ull-14x14-evk ” 和 “ fsl,imx6ull ”。 
 
前面我们说了, 设备节点的 compatible 属性值是为了匹配 Linux 内核中的驱动程序,那么根节点中的 compatible 属性是为了做什么工作的?
 通过根节点的  compatible  属性可以知道我们所使用的设备,一般第 一个值描述了所使用的硬件设备名字,例如,这里使用的是“ imx6ull-14x14-evk ”这个设备,第二 个值描述了设备所使用的  SOC (即芯片),例如,这里使用的是 “ imx6ull ” 这颗  SOC 。 
 
 Linux  内核会通过根  节点的  compoatible  属性查看是否支持此设备,如果支持的话设备就会启动 Linux  内核。 
 
 
 
 
 接下来 我们就来学习一下  Linux  内核在使用设备树前后是如何判断是否支持某款设备的。  
 
 
 
1. 使用设备树之前设备匹配方法
 在没有使用设备树以前, uboot  会向  Linux  内核传递一个叫做  machine id  的值, machine id 也就是设备  ID ,告诉  Linux  内核自己是个什么设备,看看  Linux  内核是否支持。 
 
 Linux  内核是支持很多设备的,针对每一个设备 ( 板子 ) , Linux 内核都用  MACHINE_START 和 MACHINE_END  来定义一个  machine_desc  结构体来描述这个设备,例如,在文 件  arch/arm/mach-imx/mach- mx35_3ds.c  中有如下定义:  
 
 
MACHINE_START(MX35_3DS, "Freescale MX35PDK")/* Maintainer: Freescale Semiconductor, Inc */.atag_offset = 0x100,.map_io = mx35_map_io,.init_early = imx35_init_early,.init_irq = mx35_init_irq,.init_time	= mx35pdk_timer_init,.init_machine = mx35_3ds_init,.reserve = mx35_3ds_reserve,.restart	= mxc_restart,
MACHINE_END 上述代码就是定义了 “ Freescale MX35PDK ” 这个设备,其中  MACHINE_START  和MACHINE_END  定义在文件  arch/arm/include/asm/mach/arch.h  中,内容如下:  
 
#define MACHINE_START(_type,_name)			\
static const struct machine_desc __mach_desc_##_type	\__used							\__attribute__((__section__(".arch.info.init"))) = {	\.nr		= MACH_TYPE_##_type,		\.name		= _name,#define MACHINE_END				\
};
 根据  MACHINE_START  和  MACHINE_END  的宏定义,展开后如下: 
 
 
static const struct machine_desc __mach_desc_MX35_3DS__used						__attribute__((__section__(".arch.info.init"))) = {	.nr		= MACH_TYPE_MX35_3DS,			//机器ID	.name		= "Freescale MX35PDK",.atag_offset = 0x100,.map_io = mx35_map_io,.init_early = imx35_init_early,.init_irq = mx35_init_irq,.init_time	= mx35pdk_timer_init,.init_machine = mx35_3ds_init,.reserve = mx35_3ds_reserve,.restart	= mxc_restart,
};
 可以看出,这里定义了一个  machine_desc  类型的结构体变量 __mach_desc_MX35_3DS  , 这 个 变 量 存 储 在 “  .arch.info.init  ” 段 中 。 
  第  4  行 的  MACH_TYPE_MX35_3DS  就 是 “  Freescale MX35PDK  ” 这 个 板 子 的  machine id  。  
 
 MACH_TYPE_MX35_3DS  定义在文件  include/generated/mach-types.h  中,此文件定义了大量的  
  machine id ,内容如下所示:  
 
#define MACH_TYPE_EBSA110 0
..........
#define MACH_TYPE_WRT350N_V2           1633
#define MACH_TYPE_OMAP_LDP             1639
#define MACH_TYPE_MX35_3DS             1645
............... 前面说了, uboot  会给  Linux  内核传递  machine id  这个参数, Linux  内核会检查这个  machine  id ,其实就是将  machine id  与 上面的这些  MACH_TYPE_XXX  宏进行对比,看 看有没有相等的,如果相等,就表示  Linux  内核支持这个设备,如果不支持,那么这个设 备就没法启动  Linux  内核。  
 
2. 使用设备树以后的设备匹配方法
 当  Linux  内 核 引 入 设 备 树 以 后 就 不 再 使 用  MACHINE_START  了 , 而 是 换 用了 
 
 DT_MACHINE_START 。 DT_MACHINE_START  也定义在文件  arch/arm/include/asm/mach/arch.h  里面,定义如下:  
 
 
#define DT_MACHINE_START(_name, _namestr)		\
static const struct machine_desc __mach_desc_##_name	\__used							\__attribute__((__section__(".arch.info.init"))) = {	\.nr		= ~0,				\.name		= _namestr,#endif 可以看出, DT_MACHINE_START  和  MACHINE_START  基本相同,只是 .nr  的设置不同,在  DT_MACHINE_START  里面,直接将  .nr  设置为  ~0  。说明引入设备树以后,不会再根据  machine  
 
 id  来检查  Linux  内核是否支持某个设备了。 
 
 
 打开文件  arch/arm/mach-imx/mach-imx6ul.c ,有如下所示内容:  
 
 
static const char *imx6ul_dt_compat[] __initconst = {"fsl,imx6ul","fsl,imx6ull",NULL,
};DT_MACHINE_START(IMX6UL, "Freescale i.MX6 Ultralite (Device Tree)").map_io		= imx6ul_map_io,.init_irq	= imx6ul_init_irq,.init_machine	= imx6ul_init_machine,.init_late	= imx6ul_init_late,.dt_compat	= imx6ul_dt_compat,
MACHINE_END 可以看出,machine_desc  结构体中有个  .dt_compat  成员变量,此成员变量保存着本设备兼容属性。 
 
上面的 mach-imx6ul.c 文件中的结构体设置 .dt_compat = imx6ul_dt_compat , imx6ul_dt_compat  表里面有  "fsl,imx6ul"   和  "fsl,imx6ull" 这两个兼容值。 只要某个设备 ( 板子 ) 的设备树文件的根节点 “ / ” 的  compatible  属性值与  imx6ul_dt_compat  表中的任何一个值相等,那么就表示  Linux  内核支持此设备。 
 
 
 imx6ull-alientek-emmc.dts  中根节点的  compatible  属性值如下: 
 
 
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull"; 可以看出,mach-imx6ul.c 文件 中 “fsl,imx6ull” 与  imx6ul_dt_compat  中的 “ fsl,imx6ull ” 匹配,因此  I.MX6U-ALPHA  开发板可以正常启动  Linux  内核。 
 
 
 
 
 如果将  imx6ull-alientek-emmc.dts  根节点的  compatible  属性改为其他的值,比如:  
 
 
compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ullll" 重新编译 .dts 设备树文件,并用新的 DTS  启动  Linux  内核,开发板重启后,结果如下 :  
 
 
 

 当我们修改了根节点  compatible  属性内容以后,因为  Linux  内核找不到对应的设备,因此,Linux  内核无法启动。在  uboot  输出  Starting kernel… 以后就再也没有其他信息输出了。