基于高通MSM 8x60的I2C驱动终极讲解(3)

上一节分解到平台设备已经注册,挂载到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平台设备注册函数得以执行。现在整个执行流程算是跟踪完了。

你可能感兴趣的:(基于高通MSM 8x60的I2C驱动终极讲解(3))