上一节分解到平台设备已经注册,挂载到BSP板级结构体的.init_machine成员中啦,但是这个成员什么时间调用呢,也就是我们的驱动是在什么时候注册进系统的呢,现在就来跟踪下,看.init_machine 函数什么时候调用的。
要想知道整个流程是什么样的,这个还要从老掉牙的start_kernel()函数说起该函数是整个kernel的起始入口点:
asmlinkage void __init start_kernel(void)
{
......
setup_arch(&command_line);
......
rest_init();
.......
}
其中的setup_arch()函数如下:
void __init setup_arch(char **cmdline_p)
{
struct machine_desc *mdesc
;
/*通过机器码获取板级结构体,这个结构体就是在BSP文件中的那个大的结构体*/
mdesc = setup_machine(machine_arch_type);
........
init_machine = mdesc->init_machine;
}
其中init_machine是一个函数指针,该函数指针的初始化如下
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);
其中牵涉到arch_initcall宏,把该宏展开,如下
#define arch_initcall(fn) __define_initcall("3",fn,3)
#define __define_initcall(level,fn,id) \
static initcall_t __initcall_##fn##id __used \
__attribute__((__section__(".initcall" level ".init"))) = fn
展开后的结果如下:
static initcall_t __initcall_customize_machine3__used __attribute__((__section__(".initcall3.init"))) = customize_machine
其中typedef int (*initcall_t)(void);
把该函数放到".initcall3.init"段内
该段在如下函数中执行:
static noinline void __init_refok rest_init(void) __releases(kernel_lock)
{
......
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
.........
}
其中kernel_init函数如下:
static int __init kernel_init(void * unused)
{
.......
do_basic_setup();
.........
}
其中的do_basic_setup()函数如下:
static void __init do_basic_setup(void)
{
......
do_initcalls();
.........
}
其中do_initcalls()函数如下:
static void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++)
do_one_initcall(*fn);
}
int do_one_initcall(initcall_t fn)
{
ret.result = fn();
return ret.result;
}
该函数依次执行段中得,函数,也即刚才的init_machine函数,也就是咱们的I2C平台设备注册函数得以执行。现在整个执行流程算是跟踪完了。