当前位置:首页 > 操作系统 > MacOs

[Zedboard Linux系统移植]-从MACHINE_START開始

) /* 64KB way size, 8-way associativity, parity disabled */ .l2c_aux_val = 0x00000000, .l2c_aux_mask = 0xffffffff, .smp = smp_ops(zynq_smp_ops), .map_io = zynq_map_io, .init_irq = zynq_irq_init, .init_machine = zynq_init_machine, .init_late = zynq_init_late, .init_time = zynq_timer_init, .dt_compat = zynq_dt_match, .reserve = zynq_memory_init, .restart = zynq_system_reset, MACHINE_END
<code>    zynq_init_machine--->  当前的zybo的机器初始化主函数。如需上点后初始化该板子的其它外设,能够在本函数内加入相应的初始化功能。
</code>

玩过或者移植过arm-linux的都应该知道在/arch/arm文件夹下有很多与详细处理器相关的文件夹。当然对于zynq的话所相应的文件夹就是mach-zynq。在里面找到与详细板子相关的文件Linux-Digilent-Dev-masterarcharmmach-zynqarmcommon.c,没错。就是它。不管是出于想移植到新的内核还是出于想深入学习某一款arm等,对这个文件的学习是不可缺少的。

这个文件大部分内容是对平台设备的结构体初始化。在这个文件的最后有一个非常重要的宏:

<code>DT_MACHINE_START(XILINX_EP107, <span class="hljs-string">"Xilinx Zynq Platform"</span>)
    <span class="hljs-comment">/* 64KB way size, 8-way associativity, parity disabled */</span>
    <span class="hljs-preprocessor">.l</span>2c_aux_val    = <span class="hljs-number">0x00000000</span>,
    <span class="hljs-preprocessor">.l</span>2c_aux_mask   = <span class="hljs-number">0xffffffff</span>,
    <span class="hljs-preprocessor">.smp</span>        = smp_ops(zynq_smp_ops),
    <span class="hljs-preprocessor">.map</span>_io     = zynq_map_io,
    <span class="hljs-preprocessor">.init</span>_irq   = zynq_irq_init,
    <span class="hljs-preprocessor">.init</span>_machine   = zynq_init_machine,
    <span class="hljs-preprocessor">.init</span>_late  = zynq_init_late,
    <span class="hljs-preprocessor">.init</span>_time  = zynq_timer_init,
    <span class="hljs-preprocessor">.dt</span>_compat  = zynq_dt_match,
    <span class="hljs-preprocessor">.reserve</span>    = zynq_memory_init,
    <span class="hljs-preprocessor">.restart</span>    = zynq_system_reset,
MACHINE_END</code>

DT_:qMACHINE_START的定义在arch/arm/include/asm/mach/arch.h,例如以下:

<code><span class="hljs-preprocessor">#<span class="hljs-keyword">define</span> DT_MACHINE_START(_name, _namestr)               </span>
<span class="hljs-keyword">static</span> <span class="hljs-keyword">const</span> <span class="hljs-keyword">struct</span> machine_desc __mach_desc_<span class="hljs-preprocessor">##_name    </span>
 __used                                                  __attribute__((__section__(<span class="hljs-string">".arch.info.init"</span>))) = {            .nr             = ~<span class="hljs-number">0</span>,                                   .name           = _namestr,

<span class="hljs-preprocessor">#<span class="hljs-keyword">endif</span></span></code>

噢,事实上就是定义了一个struct machine_desc类型结构体变量,这个结构体还定义了其它一些成员,接下来着重关注.init_machine这个成员,它是一个函数指针,值为zynq_init_machine,这个函数也在common.c中定义。内容是什么呢?呵呵,由于在这里仅仅给出大体流程,详细内容先不分析。如今最关心的是这个结构体变量在哪里被调用,从而调用它里面的成员和成员函数呢?先来看/arch/arm/kernel/setup.c里面的setup_arch()函数:

<code><span class="hljs-literal">void</span> __init setup_arch(char <span class="hljs-subst">**</span>cmdline_p)
{
    const struct machine_desc <span class="hljs-subst">*</span>mdesc;

    setup_processor();
    mdesc <span class="hljs-subst">=</span> setup_machine_fdt(__atags_pointer);
    <span class="hljs-keyword">if</span> (<span class="hljs-subst">!</span>mdesc)
        mdesc <span class="hljs-subst">=</span> setup_machine_tags(__atags_pointer, __machine_arch_type);
    machine_desc <span class="hljs-subst">=</span> mdesc;
    machine_name <span class="hljs-subst">=</span> mdesc<span class="hljs-subst">-></span>name;

    <span class="hljs-keyword">if</span> (mdesc<span class="hljs-subst">-></span>reboot_mode <span class="hljs-subst">!=</span> REBOOT_HARD)
        reboot_mode <span class="hljs-subst">=</span> mdesc<span class="hljs-subst">-></span>reboot_mode;

    init_mm<span class="hljs-built_in">.</span>start_code <span class="hljs-subst">=</span> (unsigned long) _text;
    init_mm<span class="hljs-built_in">.</span>end_code   <span class="hljs-subst">=</span> (unsigned long) _etext;
    init_mm<span class="hljs-built_in">.</span>end_data   <span class="hljs-subst">=</span> (unsigned long) _edata;
    init_mm<span class="hljs-built_in">.</span>brk    <span class="hljs-subst">=</span> (unsigned long) _end;

    <span class="hljs-comment">/* populate cmd_line too for later use, preserving boot_command_line */</span>
    strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
    <span class="hljs-subst">*</span>cmdline_p <span class="hljs-subst">=</span> cmd_line;

    parse_early_param();

    early_paging_init(mdesc, lookup_processor_type(read_cpuid_id()));
    setup_dma_zone(mdesc);
    sanity_check_meminfo();
    arm_memblock_init(mdesc);

    paging_init(mdesc);
    request_standard_resources(mdesc);

    <span class="hljs-keyword">if</span> (mdesc<span class="hljs-subst">-></span>restart)
        arm_pm_restart <span class="hljs-subst">=</span> mdesc<span class="hljs-subst">-></span>restart;

    unflatten_device_tree();

    arm_dt_init_cpu_maps();
    psci_init();
    <span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><span class="hljs-attribute">...</span><span class="hljs-built_in">.</span></code>

这个函数在/init/main.c的start_kernel()函数里被调用。看到第10行,这里的setup_machine()函数的作用就是找到我们想要的struct machine_desc类型的变量,也就是在common.c里定义那个变量。

函数的參数machine_arch_type的值是什么呢?继续看:
这是在u-boot中MACHINE定义
[Zedboard Linux系统移植]-从MACHINE_START開始 - 文章图片

<code><span class="hljs-preprocessor">#  <span class="hljs-keyword">define</span> machine_arch_type     MACH_TYPE_XILINX_EP107</span></code>

也就是说參数machine_arch_type的值为2520。

在setup_machine()函数里主要调用了lookup_machine_type()函数来查找相应的type,应该是出于效率的原因。这个函数是通过汇编实现的,在此就不给出详细代码了。

到这里,知道了在/init/main.c的start_kernel()函数里调用了setup_arch(),在setup_arch()里找到了详细的struct machine_desc类型的变量,可是在哪里通过这个变量调用里面的成员或成员函数的呢?继续找。

还是在setup.c里,看到了这样一个函数:

<code>static int __init customize_machine(void)
{
    /*
     * customizes platform devices, <span class="hljs-keyword">or</span> adds new ones
     * On DT based machines, we fall <span class="hljs-keyword">back</span> <span class="hljs-keyword">to</span> populating <span class="hljs-keyword">the</span>
     * machine <span class="hljs-keyword">from</span> <span class="hljs-keyword">the</span> device tree, <span class="hljs-keyword">if</span> no callback <span class="hljs-keyword">is</span> provided,
     * otherwise we would always need an init_machine callback.
     */
    <span class="hljs-keyword">if</span> (machine_desc->init_machine)
        machine_desc->init_machine();
<span class="hljs-comment">#ifdef CONFIG_OF</span>
    <span class="hljs-keyword">else</span>
        of_platform_populate(NULL, of_default_bus_match_table,
                    NULL, NULL);
<span class="hljs-comment">#endif</span>
<span class="hljs-command">    return</span> <span class="hljs-number">0</span>;
}</code>

最终看到了,成员函数init_machine就是在这里被调用的。

可是它没有被显式调用,而是放在了arch_initcall这个宏里。去看看它怎么定义的在./include/linux/init.h:[Zedboard Linux系统移植]-从MACHINE_START開始 - 文章图片
再看__define_initcall宏:在./arch/um/include/shared/init.h中
[Zedboard Linux系统移植]-从MACHINE_START開始 - 文章图片
嗯。它被链接到了.initcall段里,如今简单看看./include/asm-generic/vmlinux.lds.h:这个链接脚本里关于initcall的定义:
[Zedboard Linux系统移植]-从MACHINE_START開始 - 文章图片
能够看到customize_machine()被放到了.initcall3.init里。说了那么多定义,到底它在哪里被调用啊?好吧,它是在/init/main.c里一个叫do_initcalls()的函数里被调用,去看看:
[Zedboard Linux系统移植]-从MACHINE_START開始 - 文章图片
看到第1行。非常熟悉吧。在for循环里依次调用了从__early_initcall_end開始到__initcall_end结束的全部函数。customize_machine()也是在其间被调用。
好了,到这里差点儿相同该结束了,最后总结一下这些函数调用顺序:
start_kernel()—>setup_arch()—>do_initcalls()—>customize_machine()—>zynq_init_machine()

[Zedboard Linux系统移植]-从MACHINE_START開始

标签:

本文系统来源:http://www.cnblogs.com/mengfanrong/p/5352047.html


【说明】本文章由站长整理发布,文章内容不代表本站观点,如文中有侵权行为,请与本站客服联系(QQ:254677821)!

相关教程推荐

其他课程推荐