MACHINE_START MACHINE_END 宏
一、定义[cpp]
#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框起了一个machine_desc结构体的声明并根据MACHINE_START宏的参数初始化其.nr和.name成员
并将该结构体标记编译到.arch.info.init段
在MACHINE_START和MACHINE_END宏之间可以初始化machine_desc结构体的剩余成员
machine_desc结构体的定义
[cpp]
struct machine_desc {
unsigned int nr; /* architecture number 编号 */
const char *name; /* architecture name 名字 */
unsigned long boot_params; /* tagged list */
unsigned int nr_irqs; /* number of IRQs 中断数 */
unsigned int video_start; /* start of video RAM */
unsigned int video_end; /* end of video RAM */
unsigned int reserve_lp0 :1; /* never has lp0 */
unsigned int reserve_lp1 :1; /* never has lp1 */
unsigned int reserve_lp2 :1; /* never has lp2 */
unsigned int soft_reboot :1; /* soft reboot */
void (*fixup)(struct machine_desc *,struct tag *, char **,struct meminfo *);
void (*reserve)(void); /* reserve mem blocks */
void (*map_io)(void); /* IO mapping function io映射函数 */
void (*init_irq)(void); /* 中断初始化函数 */
struct sys_timer *timer; /* system tick timer 滴答定时器 */
void (*init_machine)(void); /* 初始化函数 */
};
使用例子:
[cpp]
MACHINE_START(SMDKC110, "SMDKC110")
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkc110_map_io,
.init_machine = smdkc110_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
这里smdkc110_machine_init就是对应的板级初始化函数,s5pv210_init_irq就是板级中断初始化函数,smdkc110_map_io就是板级io初始化函数...
二、调用关系
MACHINE_START宏将machine_desc标记编译到.arch.info.init段,而/arch/arm/kernel/vmlinux.lds中
[cpp]
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
在linux启动函数start_kernel中调用了setup_arch(&command_line);
[cpp]
void __init setup_arch(char **cmdline_p)
{
struct tag *tags = (struct tag *)&init_tags;
struct machine_desc *mdesc; //声明了一个machine_desc结构体指针
char *from = default_command_line;
init_tags.mem.start = PHYS_OFFSET;
unwind_init();
setup_processor();
mdesc = setup_machine(machine_arch_type); //0根据machine_arch_type获取machine_desc
machine_name = mdesc->name; //设置名字
if (mdesc->soft_reboot) //需要软重启?
reboot_setup("s");
if (__atags_pointer)
tags = phys_to_virt(__atags_pointer);
else if (mdesc->boot_params) { //处理启动参数
#ifdef CONFIG_MMU
if (mdesc->boot_params < PHYS_OFFSET ||
mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
printk(KERN_WARNING"Default boot params at physical 0x%08lx out of reach\n",mdesc->boot_params);
} else
#endif
{
tags = phys_to_virt(mdesc->boot_params);
}
}
#if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
if (tags->hdr.tag != ATAG_CORE)
convert_to_tag_list(tags);
#endif
if (tags->hdr.tag != ATAG_CORE)
tags = (struct tag *)&init_tags;
if (mdesc->fixup) //若存在fixup方法则调用其方法
mdesc->fixup(mdesc, tags, &from, &meminfo);
if (tags->hdr.tag == ATAG_CORE) {
if (meminfo.nr_banks != 0)
squash_mem_tags(tags);
save_atags(tags);
parse_tags(tags);
}
init_mm.start_code = (unsigned long) _text;
init_mm.end_code = (unsigned long) _etext;
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = (unsigned long) _end;
/* parse_early_param needs a boot_command_line */
strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
/* populate cmd_line too for later use, preserving boot_command_line */
strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = cmd_line;
parse_early_param();
arm_memblock_init(&meminfo, mdesc); //这里可能会调用reserve方法