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

改动自:http://www.cnblogs.com/lknlfy/archive/2012/05/06/2486479.html

内核的启动过程?

3)内核的启动过程?

arch/arm/kernel/head.S —> 内核的启动汇编

r0 = 0 。 r1 = machine nr, r2 = atags pointer. 机器码 启动參数地址,machine 来自于u-boot传參,当中u-boot的机器码定义在

“u-boot-Digilent-Dev-master/arch/arm/include/asm/mach-types.h” 中例如以下

head.S中

b    secondary_start_kernel —>跳转到C语言的入口函数

//linux内核的机器码列表文件:arch/arm/tools/mach-types

init/main.c —> start_kernel //C语言的程序入口

// 操作系统的管理思想 : 内存管理、任务管理、设备管理、文件管理

setup_arch(&command_line); //体系初始化 —> arch/arm/kernel/setup.c setup_command_line(command_line); //

arch/arm/kernel/setup.c –> setup_arch()中

mdesc = setup_machine(machine_arch_type); //配置当前的机器类型,machine_arch_type就是机器码的类型,这里就是赋值MACH_XILINX_EP107

MACH_XILINX_EP107在这个宏在/arch/arm/tools/mach-types中

SMDK2410 的初始化代码在哪里? —> 遍历查找arch/arm文件夹下的的相应机器码的初始化文件 —-> \Linux-Digilent-Dev-master\arch\arm\mach-zynq\arm\common.c

//跟该机器码相应的设备初始化功能列表:

    DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
    /* 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
    zynq_init_machine--->  当前的zybo的机器初始化主函数。如需上点后初始化该板子的其它外设,能够在本函数内加入相应的初始化功能。

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

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

DT_MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
    /* 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

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

#define DT_MACHINE_START(_name, _namestr)               \
static const struct machine_desc __mach_desc_##_name    \
 __used                                                  __attribute__((__section__(".arch.info.init"))) = {            .nr             = ~0,                                   .name           = _namestr,

#endif

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

void __init setup_arch(char **cmdline_p)
{
    const struct machine_desc *mdesc;

    setup_processor();
    mdesc = setup_machine_fdt(__atags_pointer);
    if (!mdesc)
        mdesc = setup_machine_tags(__atags_pointer, __machine_arch_type);
    machine_desc = mdesc;
    machine_name = mdesc->name;

    if (mdesc->reboot_mode != REBOOT_HARD)
        reboot_mode = mdesc->reboot_mode;

    init_mm.start_code = (unsigned long) _text;
    init_mm.end_code   = (unsigned long) _etext;
    init_mm.end_data   = (unsigned long) _edata;
    init_mm.brk    = (unsigned long) _end;

    /* populate cmd_line too for later use, preserving boot_command_line */
    strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
    *cmdline_p = 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);

    if (mdesc->restart)
        arm_pm_restart = mdesc->restart;

    unflatten_device_tree();

    arm_dt_init_cpu_maps();
    psci_init();
    ......................

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

函数的參数machine_arch_type的值是什么呢?继续看:

这是在u-boot中MACHINE定义

#  define machine_arch_type     MACH_TYPE_XILINX_EP107

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

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

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

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

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

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

可是它没有被显式调用,而是放在了arch_initcall这个宏里。去看看它怎么定义的在./include/linux/init.h:

再看__define_initcall宏:在./arch/um/include/shared/init.h中

嗯。它被链接到了.initcall段里,如今简单看看./include/asm-generic/vmlinux.lds.h:这个链接脚本里关于initcall的定义:

能够看到customize_machine()被放到了.initcall3.init里。说了那么多定义,到底它在哪里被调用啊?好吧,它是在/init/main.c里一个叫do_initcalls()的函数里被调用,去看看:

看到第1行。非常熟悉吧。在for循环里依次调用了从__early_initcall_end開始到__initcall_end结束的全部函数。customize_machine()也是在其间被调用。

好了,到这里差点儿相同该结束了,最后总结一下这些函数调用顺序:

start_kernel()—>setup_arch()—>do_initcalls()—>customize_machine()—>zynq_init_machine()

时间: 2024-11-09 00:09:18

[Zedboard Linux系统移植]-从MACHINE_START開始的相关文章

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

转自:http://www.cnblogs.com/lknlfy/archive/2012/05/06/2486479.html 内核的启动过程? 3)内核的启动过程? arch/arm/kernel/head.S -> 内核的启动汇编 r0 = 0 , r1 = machine nr, r2 = atags pointer. 机器码 启动参数地址,machine 来自于u-boot传参,其中u-boot的机器码定义在 "u-boot-Digilent-Dev-master/arch/ar

(一)Linux系统移植之环境搭建

Linux系统移植 环境搭建 交叉编译工具链:为了编译.链接.处理和调试跨平台体系结构的程序代码.配置的步骤: 解压到/usr/local/arm目录下,执行命令"tar -xvf arm-2014.05-29-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2 -C /usr/local/arm" 配置系统环境变量,把解压的交叉编译工具链的路径添加到环境变量PATH中,在~/.bashrc中添加一行" export PATH=$

linux系统移植流程

linux系统移植流程   "Ctrl" + "+" :放大:"Ctrl" + "-" :缩小:"Ctrl" + "0" :原始大小. linux系统移植流程,布布扣,bubuko.com

MiniCRT 64位 linux 系统移植记录:64位gcc的几点注意

32位未修改源码与修改版的代码下载: git clone git@github.com:youzhonghui/MiniCRT.git MiniCRT 64位 linux 系统移植记录 MiniCRT是<程序员的自我修养:链接,转载于库>的作者俞甲子写的小型的C运行时库.里面提供了printf,malloc,free,fopen等比较常用的函数实现. 之所以要捣鼓这个东西,是因为要自己写一个链接器,链接标准库的时候出了麻烦,一些符号在整个libc中都找不到定义,标准库又太大,研究源码,翻文档都

嵌入式 Linux 系统移植——BSP分析

嵌入式 Linux 系统移植--BSP分析 一.BSP简介 嵌入式系统由硬件环境.嵌入式操作系统和应用程序组成,硬件环境是操作系统和应用程序运行的硬件平台,它随应用的不同而有不同的要求.硬件平台的多样性是嵌入式系统的主要特点,如何使嵌入式操作系统在不同的硬件平台上有效地运行,是嵌入式系统开发中需要解决的关键问题.解决的方法是在硬件平台和操作系统之间提供硬件相关层来屏蔽这些硬件的差异,给操作系统提供统一的运行环境,硬件相关层就是嵌入式系统中的板级支持包 BSP(Board Support Pack

嵌入式linux系统移植开发视频教程

深入浅出嵌入式linux系统移植开发(环境搭建.uboot的移植.嵌入式内核的配置与编译) 课程讲师:韩老师 课程分类:Linux 适合人群:中级 课时数量:56课时 用到技术:嵌入式Linux开发模式 涉及项目:基于tftp烧写系统 咨询qq:1840215592 课程介绍: 本课程重点是给大家讲解嵌入式linux系统移植的开发方法,采用理论与实践,硬件与软件相结合的方法. 1.在每节开始之前先简单回顾上一节所讲的主要内容,并对本节所讲的内容先进行概述,讲解概念.技术要点,设计实现思路等内容,

【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)

深入浅出嵌入式linux系统移植开发 (环境搭建.uboot的移植.嵌入式内核的配置与编译) 亲爱的网友,我这里有套课程想和大家分享,如果对这个课程有兴趣的,可以加我的QQ2059055336和我联系. 课程内容简介 本课程重点是给大家讲解嵌入式linux系统移植的开发方法,采用理论与实践,硬件与软件相结合的方法. 1.在每节开始之前先简单回顾上一节所讲的主要内容,并对本节所讲的内容先进行概述,讲解概念.技术要点,设计实现思路等内容,最后总结本次课程的要掌握的要点. 2.在讲课的过程中对关键技术

[Zedboard u-boot Linux系统移植]-Embedded Linux&#174; Hands-on Tutorial for the ZedBoard?

本文翻译自Embedded Linux? Hands-on Tutorial for the ZedBoard? 本文主要是详细讲解zedboard硬件系统搭建,u-boot,linux-kernel移植,linaro文件系统移植.过程中需要生成的文件有system.bit,fsbl.elf,u-boot.elf,devicetree.dtb,uImage(zImage和uImage区别请看),linaro文件系统(linaro.org可以下载).具体的步骤可以参考Embedded Linux?

linux系统移植和根文件系统制作

1.1 Linux内核基础知识 在动手进行Linux内核移植之前,非常有必要对Linux内核进行一定的了解,下面从Linux内核的版本和分类说起. 1.1.1  Linux版本 Linux内核的版本号可以从源代码的顶层目录下的Makefile中看到,比如2.6.29.1内核的Makefile中: VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 29 EXTRAVERSION = .1 其中的“VERSION”和“PATCHLEVEL”组成主版本号,比如2.4.2.5.