zoukankan      html  css  js  c++  java
  • linux4.10.8 内核移植(一)---环境搭建及适配单板。

    一、环境搭建

      源码包下载:git clone https://www.kernel.org/pub/linux/kernel/v4.x/linux-4.10.8.tar.gz

      或者直接去kernel.org上面进行下载。

      交叉编译工具链制作:

      这个已经在u-boot移植中已经做过了:http://www.cnblogs.com/kele-dad/p/6910040.html

    二、内核启动过程

    2.1 Windows 和 Linux 系统的启动区别

      

      由bootloader确定启动哪块单板。

    2.2 修改makefile

      下面的行注释掉:

      

      修改ARCH:

      

      修改交叉编译工具链:

      

    2.3 选择默认配置

      找到默认配置:

      

      

      进入arm架构中:

      

      可以看到我们的架构中有 mini2440的架构,同时也有s3c2410的配置文件。

      进入内核根目录,配置成2410:

      

      打开.config 文件

      

      查看CPU,可以看到有2440的CPU:

      

      同时也支持 mini2440 的单板:

      

    2.4 编译

       执行:make uImage

      进行编译:

      

      编译提示错误,那是因为没有安装u-boot 依赖包。

      

      提示要安装新包

      

      再执行编译:

      

      编译成功。

     2.5 烧写

      通过nfs进行烧写,nfs配置如文档:http://www.cnblogs.com/kele-dad/p/7082765.html

      

      启动内核:bootm 32000000

      

      看一下打印信息,有条错误,无法识别机器ID。下面打印出来了很多机器ID。

      现在我们要根据我们的机器ID 去u-boot 源码中看一下启动内核的代码了。

      进入Cmd_bootm.c (common),搜索bootm,找到下面这行代码:

      

      上面代码调用了 do_bootm 函数,进入函数中查看: 

     1 U_BOOT_CMD
     2     do_bootm
     3         do_bootm_subcommand
     4             do_bootm_subcommand
     5                 do_bootm_states
     6                     boot_os_fn *boot_fn;
     7                     bootm_start
     8                     bootm_find_os
     9                     bootm_find_other
    10                     bootm_load_os
    11                     boot_fn = bootm_os_get_boot_func(images->os.os);
    12         do_bootm_states

      在do_bootm_states 中有一个结构体,boot_os_fn:

     1 static boot_os_fn *boot_os[] = {
     2     [IH_OS_U_BOOT] = do_bootm_standalone,
     3 #ifdef CONFIG_BOOTM_LINUX
     4     [IH_OS_LINUX] = do_bootm_linux,
     5 #endif
     6 #ifdef CONFIG_BOOTM_NETBSD
     7     [IH_OS_NETBSD] = do_bootm_netbsd,
     8 #endif
     9 #ifdef CONFIG_LYNXKDI
    10     [IH_OS_LYNXOS] = do_bootm_lynxkdi,
    11 #endif
    12 #ifdef CONFIG_BOOTM_RTEMS
    13     [IH_OS_RTEMS] = do_bootm_rtems,
    14 #endif
    15 #if defined(CONFIG_BOOTM_OSE)
    16     [IH_OS_OSE] = do_bootm_ose,
    17 #endif
    18 #if defined(CONFIG_BOOTM_PLAN9)
    19     [IH_OS_PLAN9] = do_bootm_plan9,
    20 #endif
    21 #if defined(CONFIG_BOOTM_VXWORKS) && 
    22     (defined(CONFIG_PPC) || defined(CONFIG_ARM))
    23     [IH_OS_VXWORKS] = do_bootm_vxworks,
    24 #endif
    25 #if defined(CONFIG_CMD_ELF)
    26     [IH_OS_QNX] = do_bootm_qnxelf,
    27 #endif
    28 #ifdef CONFIG_INTEGRITY
    29     [IH_OS_INTEGRITY] = do_bootm_integrity,
    30 #endif
    31 #ifdef CONFIG_BOOTM_OPENRTOS
    32     [IH_OS_OPENRTOS] = do_bootm_openrtos,
    33 #endif
    34 };

      在此结构体中调用的是 do_bootm_linux 函数,进入查看 Bootm.c (archarmlib)

     1 int do_bootm_linux(int flag, int argc, char * const argv[],
     2            bootm_headers_t *images)
     3 {
     4     /* No need for those on ARM */
     5     if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
     6         return -1;
     7 
     8     if (flag & BOOTM_STATE_OS_PREP) {
     9         boot_prep_linux(images);
    10         return 0;
    11     }
    12 
    13     if (flag & (BOOTM_STATE_OS_GO | BOOTM_STATE_OS_FAKE_GO)) {
    14         boot_jump_linux(images, flag);
    15         return 0;
    16     }
    17 
    18     boot_prep_linux(images);
    19     boot_jump_linux(images, flag);
    20     return 0;
    21 }

      在最后一句中执行 boot_jump_linux 函数:

     1 /* Subcommand: GO */
     2 static void boot_jump_linux(bootm_headers_t *images, int flag)
     3 {
     4     unsigned long machid = gd->bd->bi_arch_number;
     5     char *s;
     6     void (*kernel_entry)(int zero, int arch, uint params);
     7     unsigned long r2;
     8     int fake = (flag & BOOTM_STATE_OS_FAKE_GO);
     9 
    10     kernel_entry = (void (*)(int, int, uint))images->ep;
    11 
    12     s = getenv("machid");
    13     if (s) {
    14         if (strict_strtoul(s, 16, &machid) < 0) {
    15             debug("strict_strtoul failed!
    ");
    16             return;
    17         }
    18         printf("Using machid 0x%lx from environment
    ", machid);
    19     }
    20     bootstage_mark(BOOTSTAGE_ID_RUN_OS);
    21     announce_and_cleanup(fake);
    22 
    23     if (IMAGE_ENABLE_OF_LIBFDT && images->ft_len)
    24         r2 = (unsigned long)images->ft_addr;
    25     else
    26         r2 = gd->bd->bi_boot_params;
    27 
    28     if (!fake) {
    29             kernel_entry(0, machid, r2);
    30     }
    31 }

      从环境变量中获取mach_id ,然后进入 kernel。如果没有从环境变量获取,就采用默认值,此函数的第一句就是默认值。看看默认值是多少。

      machid = gd->bd->bi_arch_number;

      在Jz2440.c (boardsamsungjz2440) 中 设置了默认ID:

     1 int board_init(void)
     2 {
     3     /* arch number of JZ2440 board */
     4     gd->bd->bi_arch_number = MACH_TYPE_JZ2440;
     5 
     6     /* adress of boot parameters */
     7     gd->bd->bi_boot_params = 0x30000100;
     8 
     9     icache_enable();
    10     dcache_enable();
    11 
    12     return 0;
    13 }

      同时在Board_f.c (common) 的 setup_machine中也有设置ID:

    1 static int setup_machine(void)
    2 {
    3 #ifdef CONFIG_MACH_TYPE
    4     gd->bd->bi_arch_number = CONFIG_MACH_TYPE; /* board id for Linux */
    5 #endif
    6     return 0;
    7 }

      CONFIG_MACH_TYPE 这个宏我们没有设置。

      那么我们的上一个设置ID的函数是有效的。

      在Mach-types.h (archarmincludeasm) 中设置的ID为194。

      

      然后在内核处,进入arch/arm/s3c24x0/ 目录,里面有很多我们的支持s3c24x0的板子,进入smdk2440的单板文件 mach-smdk2440.c:

    MACHINE_START(S3C2440, "SMDK2440")
        /* Maintainer: Ben Dooks <ben-linux@fluff.org> */
        .atag_offset    = 0x100,
    
        .init_irq    = s3c2440_init_irq,
        .map_io        = smdk2440_map_io,
        .init_machine    = smdk2440_machine_init,
        .init_time    = smdk2440_init_time,
    MACHINE_END

      在MACHINE_START中,就是根据mchine ID找到单板文件的。MACHINE_START的定义如下:

      

      展开后, .nr = MACH_TYPE_S3C2440,查找一下这个宏。

      

      generated 是临时生成的文件目录。可以看一下 mach-types.h:

      这是smdk2440的机器码

      

      这是mini2440的机器码

      

      可以对照我们的u-boot打印看出来:

      

      16进制转换成10进制就可以算出来了。

      根据以上的内容,我们可以在u-boot 中设置我们的 mach_id 的环境变量来启动内核,或者我们可以直接修改 u-boot 的默认ID值和这里的机器ID匹配即可。

      修改成mini2440的机器ID。直接修改u-boot源码:

      把mini2440改成如下:

      

      jz2440改成如下:

      

      这两个定义的机器码进行了对调而已。

      在 include/configs/jz2440.h 中设置启动参数,要加上波特率设置,否则会有乱码。mini2440的内核文件中设置的波特率为115200,smdk2440的为16M。

      

      然后编译烧写u-boot。

      进入u-boot 记得 print查看一下环境变量,如果 波特率没有改变过来 就重新设置一下:

      

      保存一下。然后烧入内核

       

      启动内核:

      

      已经有打印信息了。

  • 相关阅读:
    团队开发5
    团队开发4
    团队开发3
    团队开发2
    团队开发1
    团队计划会议
    寒假学习进度---完结篇
    寒假学习进度十七
    寒假学习进度十六
    python后续学习
  • 原文地址:https://www.cnblogs.com/kele-dad/p/7082682.html
Copyright © 2011-2022 走看看