zoukankan      html  css  js  c++  java
  • I.Mx6 3.0.35 MACHINE_START 分析

    1、在/arch/arm 目录下有许多与具体处理器相关的目录,对于I.Mx6q 对应的目录就是 arch/arm/mach-mx6/

    在里面找到与具体板子相关的文件 board-mx6q_sabresd.c ,这个文件大部分内容是对平台设备(如nand,串口,spi,nor等)

    的结构体的初始化。在这个文件的最后有一个非常重要的宏:

    /*
     * initialize __mach_desc_MX6Q_SABRESD data structure.
     */
    MACHINE_START(MX6Q_SABRESD, "Freescale i.MX 6Quad/DualLite/Solo Sabre-SD Board")
        /* Maintainer: Freescale Semiconductor, Inc. */
        .boot_params = MX6_PHYS_OFFSET + 0x100,
        .fixup = fixup_mxc_board,
        .map_io = mx6_map_io,
        .init_irq = mx6_init_irq,
        .init_machine = mx6_sabresd_board_init,
        .timer = &mx6_sabresd_timer,
        .reserve = mx6q_sabresd_reserve,
    MACHINE_END

    MACHINE_START 的定义在 arch/arm/include/asm/mach/arch.h 中,如下:

    /*
     * Set of macros to define architecture features.  This is built into
     * a table by the linker.
     */
    #define MACHINE_START(_type,_name)            
    static const struct machine_desc __mach_desc_##_type    
     __used                            
     __attribute__((__section__(".arch.info.init"))) = {    
        .nr        = MACH_TYPE_##_type,        
        .name        = _name,
    
    #define MACHINE_END                
    };

    其定义了一个 struct machine_desc 类型的结构体变量。

    2、那么这个结构体变量在哪里被调用,从而调用它里面的成员和成员函数呢?

    在 arch/arm/kernel/setup.c 中查看 setup_arch()

    void __init setup_arch(char **cmdline_p)
    {
        struct machine_desc *mdesc;
    
        unwind_init();
    
        setup_processor();
        mdesc = setup_machine_fdt(__atags_pointer);
        if (!mdesc)
            mdesc = setup_machine_tags(machine_arch_type);
        machine_desc = mdesc;
        machine_name = mdesc->name;
    
        if (mdesc->soft_reboot)
            reboot_setup("s");
    
        ...
    }

    在该函数中setup_machine_xxx() 函数的作用就是找到我们想要的 struct machine_desc 类型的变量,也就是在

    board-mx6q_sabresd.c 中定义的那个变量。

    3、setup_arch() 函数是在哪里调用的?

    在 init/main.c 的 start_kernel() 中,定义如下:

    asmlinkage void __init start_kernel(void)
    {
        ...
    
        tick_init();
        boot_cpu_init();
        page_address_init();
        printk(KERN_NOTICE "%s", linux_banner);
        setup_arch(&command_line);
        mm_init_owner(&init_mm, &init_task);
        mm_init_cpumask(&init_mm);
        setup_command_line(command_line);
        setup_nr_cpu_ids();
        setup_per_cpu_areas();
        smp_prepare_boot_cpu();    /* arch-specific boot-cpu hooks */
    
            ...
    }

    4、到这里,知道了在 /init/main.c 的 start_kernel() 函数里调用了setup_arch(),在 setup_arch() 里找到了具体的

    struct machine_desc 类型的变量,但是在哪里通过这个变量调用里面的成员或成员函数的呢?

    在 arch/arm/kernel/setup.c 中有如下定义 :

    static int __init customize_machine(void)
    {
        /* customizes platform devices, or adds new ones */
        if (machine_desc->init_machine)
            machine_desc->init_machine();
        return 0;
    }
    arch_initcall(customize_machine);

    在 include/linux/init.h 中有如下定义:

    #define arch_initcall(fn)        __define_initcall("3",fn,3)

    在 arch/arm/kernel/vmlinux.lds.h 中有如下定义:

    #define INITCALLS                            
        *(.initcallearly.init)                        
        VMLINUX_SYMBOL(__early_initcall_end) = .;            
          *(.initcall0.init)                        
          *(.initcall0s.init)                        
          *(.initcall1.init)                        
          *(.initcall1s.init)                        
          *(.initcall2.init)                        
          *(.initcall2s.init)                        
          *(.initcall3.init)                        
          *(.initcall3s.init)                        
          *(.initcall4.init)                        
          *(.initcall4s.init)                        
          *(.initcall5.init)                        
          *(.initcall5s.init)                        
        *(.initcallrootfs.init)                        
          *(.initcall6.init)                        
          *(.initcall6s.init)                        
          *(.initcall7.init)                        
          *(.initcall7s.init)

    #define INIT_CALLS                            
            VMLINUX_SYMBOL(__initcall_start) = .;            
            INITCALLS                        
            VMLINUX_SYMBOL(__initcall_end) = .;

    可以看到 customize_machine() 被放到了.initcall3.init里。

    5、customize_machine()在哪里被调用的?

    在/init/main.c 的 do_initcalls() 的函数中,定义如下:

    static void __init do_initcalls(void)
    {
        initcall_t *fn;
    
        for (fn = __early_initcall_end; fn < __initcall_end; fn++)
            do_one_initcall(*fn);
    }

    在for 循环里依次调用了从__early_initcall_end开始到__initcall_end结束的所有函数。customize_machine() 也是在其间被调用。

    6、总体调用顺序

    start_kernel()--->setup_arch()--->do_initcalls()--->customize_machine()--->mx6_sabresd_board_init()

  • 相关阅读:
    Metricbeat
    Flask安装与基本配置
    web框架
    git
    占位
    算法
    面试
    CMDB
    order by关键字排序优化
    动态主机配置协议-DHCP
  • 原文地址:https://www.cnblogs.com/aqing1987/p/4364190.html
Copyright © 2011-2022 走看看