zoukankan      html  css  js  c++  java
  • S3C2440移植linux3.4.2内核之内核框架介绍及简单修改

    uboot启动内核分析

      进入cmd_bootm.c,找到对应的bootm命令对应的do_bootm():

    int do_bootm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
    {
    boot_os_fn *boot_fn;             //boot_fn是个数组函数
     ... ..
    
    boot_fn(0, argc, argv, &images); //调用数组函数
     ... ...
    }
    

      boot_os_fn是个typedef型,如下图所示:
    在这里插入图片描述
      由于定义了宏CONFIG_BOOTM_LINUX,最终会跳转到do_bootm ->do_bootm_linux()
      代码如下所示:

    int do_bootm_linux(int flag, int argc, char *argv[], bootm_headers_t *images)
    {
             /* No need for those on ARM */
             if (flag & BOOTM_STATE_OS_BD_T || flag & BOOTM_STATE_OS_CMDLINE)
                       return -1;
             if (flag & BOOTM_STATE_OS_PREP) {
                       boot_prep_linux(images);
                       return 0;
             }
             if (flag & BOOTM_STATE_OS_GO) {
                       boot_jump_linux(images);
                       return 0;
             }
    
     
             boot_prep_linux(images);      //该函数会将各个tag参数保存在指定位置,比如:内存tag、bootargs环境变量tag、串口tag等
             boot_jump_linux(images);      //该函数会跳转到内核起始地址
             return 0;
    }
    

      最终跳转到do_bootm ->do_bootm_linux-> boot_jump_linux()

    static void boot_jump_linux(bootm_headers_t *images)
    {
             unsigned long machid = gd->bd->bi_arch_number;     //获取机器ID
             char *s;
             void (*kernel_entry)(int zero, int arch, uint params);
             unsigned long r2;
             kernel_entry = (void (*)(int, int, uint))images->ep;  //设置kernel_entry()的地址为0x30000000
             s = getenv("machid");                     //判断环境变量machid是否设置,若设置则使用环境变量里的值   
             if (s) {       
                       strict_strtoul(s, 16, &machid);      //重新获取机器ID
                       printf("Using machid 0x%lx from environment
    ", machid);  //使用环境变量的machid
             }
         ... ...
            r2 = gd->bd->bi_boot_params;     //获取tag参数地址, gd->bd->bi_boot_params在setup_start_tag()函数里被设置 
            kernel_entry(0, machid, r2);     //跳转到0x30000000,r0=0,r1=机器ID,r2=tag参数地址
    }
    

       上面的machid默认值为MACH_TYPE_SMDK2410(也就是193),我们也可以在环境变量里设置machid变量
    最终,便跳到内核执行代码,步骤如下所示:
      1)根据R1(机器ID),来判断内核是否支持该机器,若支持则初始化机器相关函数
      2)解析TAG参数,初始化串口,设置内存等
      3)挂载根文件系统,并执行应用程序

    简单配置内核

      修改Makefile,修改配置

    tar xjf linux-3.4.2.tar.bz2 
    cd linux-3.4.2/
    vi Makefile 
    

    在这里插入图片描述
      改为

    ARCH            ?= arm
    CROSS_COMPILE   ?= arm-linux-
    

      配置编译

    cd arch/arm/configs                //由于我们板子是arm板,进入该目录
    ls  *2440*                            //找到有mini2440_defconfig、
    ls  *2410*                            //找到有s3c2410_defconfig
    
    cd ../../..
    make s3c2410_defconfig                //配置2410, 更新.config配置文件 
    make uImage                          //编译,生成uImage
    cp arch/arm/boot/uImage /work/nfs_root/           //拷贝
    cd /work/nfs_root/ 
    mv uImage uImage_new
    

    在这里插入图片描述
      进入.config查看支持的CPU

    vi .config
    

    在这里插入图片描述
      如上图所示,有我们的2440

    编译内核

    make uImage
    

      报错如下

    Can't use 'defined(@array)'(Maybe you should just omit the defined? )at kernel/timeconst pl line 373
    /root/working/Hi3520D SDK V2.0.3.0/osdrv/kernel/linux-30y/kernel/Makefile:140
    recipe for target kernel/timeconst h failed make【1】:*** 【kernel/timeconst h】 Error 255
    Makefile:945:recipe for target kernel ' failed
    【kernel】 Error 2
    

    解决办法
      将 kernel/timeconst.pl中第373行的 defined0去掉只留下@val就可以了

    vim kernel/timeconst.pl +373
    

      进入uboot烧写

    nfs 32000000 192.168.2.106:/work/nfs_root/uImage_new
    bootm 32000000  
    

      如下图所示,发现串口输出乱码:
    在这里插入图片描述

    设置机器ID

      uboot传递进来的机器ID可以通过环境变量machid来设置
      所以任意设置一个ID,这样再次启动内核时,内核识别不出来,就会打印出所有设备对应的机器ID。下面开始测试机器ID是否正确,进入uboot,输入:

    set machid 33333
    tftp 32000000 uImage
    bootm 32000000
    

      如下图所示,由于内核不支持这个机器ID,所以打印出内核能支持的ID表:
    在这里插入图片描述
      ID所对应的文件为arch/arm/mach-s3c24xx/Mach-smdk2440.c
    在这里插入图片描述
      MACHINE_START为一个结构体,根据不同的机器ID找到对应的MACHINE_START,调用初始化函数。
      由于我们板子是2440,所以测试7cf(mini2440)以及16a(smdk2440)这两个机器ID,是否支持我们开发板。
      但是依旧乱码,可能是波特率设置不正确。重新设置下环境变量的波特率

    set bootargs root=/dev/mtdblock3 console=ttySAC0,115200 
    

      再次烧写启动,发现7cf(mini2440)这个ID,有串口输出正常。下面看下16a(smdk2440)为什么串口乱码,进入mach-smdk2440.c( 位arch/arm/mach-s3c24xx)找到问题出在smdk2440_map_io():

    static void __init smdk2440_map_io(void)
    {
             s3c24xx_init_io(smdk2440_iodesc, ARRAY_SIZE(smdk2440_iodesc));
             s3c24xx_init_clocks(16934400);             //初始化时钟clock
             s3c24xx_init_uarts(smdk2440_uartcfgs, ARRAY_SIZE(smdk2440_uartcfgs));
    }
    

    修改晶振

      由于我们板子上的晶振是12Mhz,而mdk2440_map_io()里,初始化的时钟是基于16934400hz的晶振。所以将:

    s3c24xx_init_clocks(16934400);             //初始化时钟clock
    

      改为:

    s3c24xx_init_clocks(12000000);             //初始化时钟clock
    

      然后重新编译uImage:

    make  s3c2410_defconfig             //将mach-s3c2440.c配置进内核
    make  uImage
    cp uImage /work/nfs_root/ uImage_new
    

      进入uboot,输入:

    set machid 16a
    nfs 32000000 192.168.1.30:/work/nfs_root/uImage_new
    bootm 32000000
    

      启动内核打印正常。
    在这里插入图片描述
      下一节S3C2440移植linux3.4.2内核之修改分区以及制作根文件系统
    我们将修改分区和制作根文件系统。

    有任何问题,均可通过公告中的二维码联系我

  • 相关阅读:
    正则表达式
    字节流和字符流小练习
    File汇总
    java一不容易就容易错的知识点汇总
    a++和++a区别
    线程安全的3种方式
    bs4和css选择器的基本使用
    清点作业情况
    cookie和session的使用
    用post请求制作翻译
  • 原文地址:https://www.cnblogs.com/dongxb/p/14207492.html
Copyright © 2011-2022 走看看