imx6的kernel3.4.15启动流程
//最开始的定义为 DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)") .smp = smp_ops(imx_smp_ops), .map_io = imx6q_map_io, .init_irq = imx6q_init_irq, //中断的板级初始化 .init_machine = imx6q_init_machine, // .init_late = imx6q_init_late, .dt_compat = imx6q_dt_compat, //比较得到设备树 MACHINE_END //后面函数都是在start_kernel中 setup_arch setup_machine_fdt DT_MACHINE_START //在这里定义一个machine描述符,编译的时候会放入.arch.info.init段中 MACHINE_END of_flat_dt_match_machine //找到最合适的machine描述符 early_init_dt_scan_nodes //找到几个比较重要的节点 early_init_dt_scan_chosen //找到 chosen 节点,并将值放入boot_command_line中 early_init_dt_scan_root //扫描根节点,获取 {size,address}-cells信息,并保存在dt_root_size_cells和dt_root_addr_cells全局变量中 early_init_dt_scan_memory //扫描DTB中的 memory node,并把相关信息保存在meminfo中,全局变量meminfo保存了系统内存相关的信息 paging_init(mdesc) // devicemaps_init(mdesc) mdesc->map_io //这里就是调用了DT_MACHINE_START中的imx6q_map_io unflatten_device_tree //需要将DTB转换成节点是 device_node 的树状结构,也就是把所有节点保存在C代码中的device_node中 __unflatten_device_tree fdt_magic //检查设备树magic fdt_totalsize //检测大小 fdt_version //检测版本 fdt_check_header //检测头 unflatten_dt_node //第一轮的scan,主要目的是为了获取设备树的大小 dt_alloc //将获取的大小在内存中申请一段内存(device_node数量的大小) unflatten_dt_node //第二轮scan,将设备树中所有信息挂在上一步申请内存中(以结构体device_node为链表) arm_dt_init_cpu_maps //获取cpu的节点 init_IRQ machine_desc->init_irq() //这里也就是上面DT_MACHINE_START中的 imx6q_init_irq imx_gpc_check_dt irqchip_init of_irq_init //遍历Device Tree,找到interrupt controller,并挂在intc_desc,然后系统开始匹配中断,一旦匹配上,进行中断初始化 time_init //时钟初始化,非常重要,在这里面对各种时钟倍频,分频操作 of_clk_init matches = &__clk_of_table; //__clk_of_table就是保存clk结构体的内存,拿到后依次运行,我们在文件中定义了CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init); rest_init kernel_init kernel_init_freeable do_basic_setup driver_init of_core_init for_each_of_allnodes //从根节点轮训所有节点 __of_attach_node_sysfs //sys/firmware/devicetree/base目录下面为设备树展开成sysfs的目录和二进制属性文件,所有的node节点就是一个目录,所有的property属性就是一个二进制属性文件。 do_initcalls while(0~7) //会依次初始化0~7,其中3是架构,6是设备 do_initcall_level(3) //在代码中有arch_initcall(customize_machine) customize_machine machine_desc->init_machine() //这里就是DT_MACHINE_START定义的imx6q_init_machine of_platform_populate(NULL, of_default_bus_match_table, NULL, parent); //加载platform设备 for_each_child_of_node //轮训根节点 of_platform_bus_create //创建platform总线, 这里会把i2c adapter之类的设备进行了初始化 imx6q_enet_init imx_anatop_init imx6q_csi_mux_init imx6q_pm_init //电源管理初始化 imx6q_axi_init do_initcall_level(6) //在代码中的device_initcall/module_init/device_initcall都是这个等级的,为设备驱动 do_initcall_level(7) //最低优先级的,late_initcall为这个等级,其中有late_initcall(init_machine_late) init_machine_late machine_desc->init_late() //这里就是DT_MACHINE_START定义的 init_late try_to_run_init_process("/sbin/init")//尝试运行sbin/init try_to_run_init_process("/etc/init") try_to_run_init_process("/bin/init") try_to_run_init_process("/bin/sh") kthreadd 从上面流程可以看出chosen、memory、cpus节点未挂在device_node上