深入理解 Linux 宏定义 MACHINE_START

宏定义 MACHINE_START

在arm-linux中的/arch/arm目录下,有许多与具体处理器相关的目录,里面有与具体板子相关的文件,这个文件大部分内容是对平台设备的结构体初始化(例如串口,LCD,Nand falsh等),这里以 arm-s5pv210为例说明,对应的板级文件是mach-x210.c,在这个文件中宏定义 MACHINE_START专门用来初始化基础硬件设备。定义如下:

MACHINE_START(SMDKV210, "SMDKV210")
	.phys_io	    = S3C_PA_UART & 0xfff00000,
	.io_pg_offst	= (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params	= S5P_PA_SDRAM + 0x100,
	.init_irq	    = s5pv210_init_irq,
	.map_io		    = smdkc110_map_io,
	.init_machine	= smdkc110_machine_init,
	.timer		    = &s5p_systimer,
MACHINE_END

MACHINE_START的定义在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				                        \
};

展开这个宏定义后

static const struct machine_desc  __mach_desc_SMDKV210
__used
__attribute__((__section__(".arch.info.init"))) = {
	.nr		      = MACH_TYPE_SMDKV210,
	.name		  = "SMDKV210",
	.phys_io	  = S3C_PA_UART & 0xfff00000,
	.io_pg_offst  = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
	.boot_params  = S5P_PA_SDRAM + 0x100,
	.init_irq	  = s5pv210_init_irq,
	.map_io		  = smdkc110_map_io,
	.init_machine = smdkc110_machine_init,
	.timer		  = &s5p_systimer,
};

这里定义了一个 machine_desc 类型结构体变量,这个类型的变量放在内核代码段.arch.info.init中,在内核启动时,被函数 lookup_machine_type 取出函数指针(此函数用汇编实现,在汇编文件中)。

ENTRY(lookup_machine_type)
	stmfd	sp!, {r4 - r6, lr}
	mov	r1, r0
	bl	__lookup_machine_type
	mov	r0, r5
	ldmfd	sp!, {r4 - r6, pc}

然后在 setup_arch 中执行machine_desc 中的成员函数, 程序流程为:

start_kernel(void)
  --> setup_arch(&command_line);
  --> setup_machine(machine_arch_type); //machine_arch_type?
   --> lookup_machine_type()

通过 lookup_machine_type() 函数取出函数指针后,在 setup_arch 函数中给函数指针赋值,如下:

	init_arch_irq = mdesc->init_irq;
	system_timer = mdesc->timer;
	init_machine = mdesc->init_machine;

然后在 setup.c 文件中发现下面的函数 和宏定义:

static void (*init_machine)(void) __initdata;
static int __init customize_machine(void)
{
	/* customizes platform devices, or adds new ones */
	if (init_machine)
		init_machine();
	return 0;
}
arch_initcall(customize_machine);

#define arch_initcall(fn)		__define_initcall("3",fn,3)

成员函数 init_machine 但是它没有被显式调用,而是放在了 arch_initcall 这个宏定义中,系统启动时会扫描这个段去调用执行它。


machine_desc 成员分析


1、MACH_TYPE_SMDKV210

MACH_TYPE_SMDKV210 它是uboot传递过来的,动态保存在generated/mach-types.h中,在 arch \ arm \ include \ asm \ mach-type.h 中包含了 这个文件。
SMDKV210 宏在 / arch / arm / tools / mach-types 文件里定义,所以MACH_TYPE_SMDKV210 的值是 2456。

2、.init_machine

.init_machine这个成员是一个函数指针,值为 smdkc110_machine_init,这个函数也在 mach-x210.c 中定义。

http://blog.csdn.net/charliewangg12/article/details/41483261

你可能感兴趣的:(linux,arm开发)