[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_ENDDT_: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()
[Zedboard Linux系统移植]-从MACHINE_START開始的更多相关文章
- 【课程分享】深入浅出嵌入式linux系统移植开发 (环境搭建、uboot的移植、嵌入式内核的配置与编译)
		深入浅出嵌入式linux系统移植开发 (环境搭建.uboot的移植.嵌入式内核的配置与编译) 亲爱的网友,我这里有套课程想和大家分享,假设对这个课程有兴趣的,能够加我的QQ2059055336和我联系 ... 
- MiniCRT 64位 linux 系统移植记录:64位gcc的几点注意
		32位未修改源码与修改版的代码下载: git clone git@github.com:youzhonghui/MiniCRT.git MiniCRT 64位 linux 系统移植记录 MiniCRT ... 
- 非常详细的ok6410的linux系统移植…
		目录 Linux 3.3.5系统移植 2 LED驱动移植 8 按键驱动移植 9 LCD驱动移植 11 DM9000网卡驱动移植 14 搭建NFS网络文件系统 25 移植触摸屏驱动 38 移植Qt4.8 ... 
- 嵌入式linux系统移植(一)
		内容: 交叉编译环境 bootloader功能子系统 内核核心子系统 文件系统子系统要点: 搭建交叉编译环境 bootloader的选择和移植 kernel的配置.编译.移植和调 ... 
- Linux系统移植的重要文件
		移植linux内核的关键文件: arch/arm/mach-s5p6818/cpu.c cpu_init_machine() ... 
- Linux系统移植(1) ------搭建交叉编译环境
		本人的开发环境是ubuntu12.05的64版本,运行在11.00的虚拟机上.首先说明为什么需要搭建交叉编译环境.我们知道,我们的开发一般在PC机上,是基于X86架构的,而我们的开发板却是基于ARM架 ... 
- 嵌入式Linux系统移植——uboot常用命令
		flash的一般分区: 其它数据 环境变量 可执行程序.如bootloader print(可缩写为:pri):打印查看uboot这个软件中集成的环境变量setenv.saveenv:设置.保存环境变 ... 
- linux 系统移植uboot
		这里使用的版本为:u-boot-2014.04 查看并修改位置如下:u-boot-2014.04/include/configs/at91sam9x5ek.h(1)查看一下Linux内核在NandFl ... 
- 2440开发板linux系统移植3G拨号上网收发短信(三)
		一.用text查看模式 下面的“发”是指我敲的命令,“收”是指回车后显示的信息包括其他接收的信息. ~ >: microcom -s 115200 /dev/ttyUSB1 发:at 收:OK ... 
随机推荐
- 简单Json序列化和反序列化
			序列化是什么: 序列化就是将一个对象的状态(各个属性量)保存起来,然后在适当的时候再获得.序列化分为两大部分:序列化和反序列化.序列化是这个过程的第一部分,将数据分解成字节流,以便存储在文件中或在网络 ... 
- PoPo数据可视化周刊第一期
			PoPo数据可视化 聚焦于Web数据可视化领域, 发现前端可视化领域有意思的内容. 涵盖前端可视化领域最新资讯, 开源可视化库的发布更新消息, 可视化案例分析与讲解, 可视化技术文章, 可视化大神的日 ... 
- BZOJ4598: [Sdoi2016]模式字符串(点分治 hash)
			题意 题目链接 Sol 直接考虑点分治+hash匹配 设\(up[i]\)表示\(dep \% M = i\)的从下往上恰好与前\(i\)位匹配的个数 \(down\)表示\(dep \% M = i ... 
- CSS Align bottom
			<html> <head> <meta http-equiv="Content-Type" content="text/html; char ... 
- Spring与Web整合
			一 概述 1.整合目的 将所有对象的创建与管理任务交给Spring容器,降低程序的耦合度. 2.整合途径 将Spring容器注入到Web容器中. 3.具体实现 使用ServletContextList ... 
- PHP实用系统函数之数组篇
			PHP中十分实用的系统函数 array array_merge 说明:array array_merge ( array $array1 [, array $... ] ) 将一个或多个数组的单元合 ... 
- line-height和height的区别
			line-height 是指每行的高度, 假如定义p标签的行高为line-heigth:20px; 文字在浏览器中显示为一行时,这个p标签的高度会为20px,如果为两行,则p标签的高度为40px; l ... 
- 工具Sequel Pro简介
			从图中可以看到,sequel工作界面主要分成三部分,左边侧边显示的是当前所连接的数据库中存在的数据表,右侧上半部分则是用于写sql的地方,在Mac环境下按command+R键会执行你所写的sql,右侧 ... 
- Maximum Subarray  连续子数组最大和
			Find the contiguous subarray within an array (containing at least one number) which has the largest ... 
- 从golang-gin-realworld-example-app项目学写httpapi (八)
			https://github.com/gothinkster/golang-gin-realworld-example-app/blob/master/common/unit_test.go 单元测试 ... 
