一.? 简介
每个节点都有
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…
以后就再也没有其他信息输出了。