//最開始的定義爲 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上