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上
相關文章
相關標籤/搜索