以下内容从正点原子文档种摘取。
一、使用设备树之前设备匹配方法
在没有使用设备树以前,uboot
会向 Linux
内核传递一个叫做 machine id
的值,machine id
也就是设备 ID
,告诉 Linux
内核自己是个什么设备,看看 Linux
内核是否支持。Linux
内核是 支持很多设备的,针对每一个设备(板子),Linux
内核都用 MACHINE_START
和 MACHINE_END
来定义一个 machine_desc
结构体来描述这个设备。比如在文件 arch/arm/mach-imx/machmx35_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,
.name = "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_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
,内容如下所示:
第 287
行就是 MACH_TYPE_MX35_3DS
的值,为 1645
。
前面说了,uboot
会给 Linux
内核传递 machine id
这个参数,Linux
内核会检查这个 machine id
,其实就是将 machine id
与示例代码中的这些 MACH_TYPE_XXX
宏进行对比,看 看有没有相等的,如果相等的话就表示 Linux
内核支持这个设备,如果不支持的话那么这个设 备就没法启动 Linux
内核。
二、使用设备树以后的设备匹配方法
当 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
成员变量,此成员变量保存着本设备兼容属性,示例代码中设置 .dt_compat = imx6ul_dt_compat
,imx6ul_dt_compat
表里面有 "fsl,imx6ul"
和 "fsl,imx6ull"
这两个兼容值。
只要某个设备(板子)根节点 “/”
的 compatible
属性值与 imx6ul_dt_compat
表中的任何一个值相等,那么就表示 Linux
内核支持此设备。