基于FL2440的3.6.6内核移植记录

一、前期准备工作

成功启动的提示信息,可以看出我的编译环境

Booting Linux on physical CPU 0
Linux version 3.6.6 (anzyelay@ubuntu) (gcc version 4.9.4 20151028 (prerelease) (Linaro GCC 4.9-2016.02) ) #24
 Mon Jul 18 16:17:22 CST 2016
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
CPU: VIVT data cache, VIVT instruction cache
Machine: LXA2440
Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C24XX Clocks, Copyright 2004 Simtec Electronics
S3C244X: core 400.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: root= init=/linuxrc load_ramdisk=0 console=ttySAC0,115200 mem=65536K devfs=mount display
=lcd480 root=/dev/nfs nfsroot=192.168.10.5:/home/anzyelay/Desktop/arm/rootfs ip=192.168.10.110:::::eth0
1.1 内核下载

官网地址选相应的内核下载,我这里参考也选了3.6.6,下载后解压出来,如下:

anzyelay@ubuntu:arm$ tar -xf linux-3.6.6.tar.xz
anzyelay@ubuntu:arm$ ls
anzyelay@ubuntu:arm$ ls
linux-3.6.6          linux-3.6.6.tar.xz  
    anzyelay@ubuntu:arm$ 
1.2 编译器的下载和配置

可到Linaro官网选择相应版本下载
解压出来保存/usr/local/arm/4.9.4下,保存位置仅做参考,可自行更改,配置修改这里不做说明了,更改文件

anzyelay@ubuntu:linux-3.6.6-gcc.4.9.4$ ls /usr/local/arm/4.9.4/
arm-linux-gnueabi  bin  gcc-linaro-4.9-2016.02-manifest.txt  include  lib  libexec  share

二、kernel sourse的修改

2.1 由于cross-compile, 更改顶层make file下的这两行如下:

 anzyelay@ubuntu:linux-3.6.6-gcc.4.9.4$ vi Makefile

 195 ARCH        ?=arm
 196 CROSS_COMPILE   ?=/usr/local/arm/4.9.4/bin/arm-linux-gnueabi-

2.2 增加自己Machine的macro name和number(Uboot中的机器码)

在arch/arm/tools/mach-types文件中添加,

anzyelay@ubuntu:linux-3.6.6-gcc.4.9.4$ vi arch/arm/tools/mach-types

 # machine_is_xxx    CONFIG_xxxx     MACH_TYPE_xxx       number
 363 mini2440        MACH_MINI2440       MINI2440        1999
 364 lxa2440         MACH_LXA2440        LXA2440         193
  • 这几项用处是什么?
    同目录下有个gen-mach-types的脚本,譔脚本自动用此文件来生成include/generated/mach-types.h头文件见参考2,只举一项内容如下:

        #define MACH_TYPE_MINI2440             1999
        #ifdef CONFIG_MACH_MINI2440                                                 
        # ifdef machine_arch_type
        #  undef machine_arch_type
        #  define machine_arch_type __machine_arch_type
        # else
        #  define machine_arch_type MACH_TYPE_MINI2440
        # endif
        # define machine_is_mini2440()  (machine_arch_type == MACH_TYPE_MINI2440)
        #else
        # define machine_is_mini2440()  (0)
        #endif

    因此其各项作用:

    • machine_is_xxx :定义machine_is_mini2440()
    • CONFIG_xxxx:用来配置内核编译选项(后面修改Kconfig需要)
    • MACH_TYPE_xxx :宏定义MACH_TYPE_xxx =number(后面修改mach-class.c文件需要)
    • number:机器码,用来bootloader控制内核在boot阶段匹配哪个machine_desc(如果内核编译了多个machine的话)

    如:当CONFIG_MACH_MINI2440=y时,就定义了相应的machine_is_mini2440()函数,并编译arch/arm/mach-s3c24xx/mach-mini2440.c,此文件将__mach_desc_MINI2440添加到了( __arch_info_begin,__arch_info_end )里。
    在内核boot时将从bootloader得到的机器码与MACH_TYPE_xxx匹配就得到__mach_desc_MINI2440描述体了,从而以此描述体里的相应信息启动相应的kernel设备,不然就卡死在“Uncompressing Linux… done, booting the kernel.”之后了。

  • boot时是如何匹配?

    • 先看看arch/arm/include/asm/mach/arch.h 中的相关结构体

      
      #define MACHINE_START(_type,_name)          \
      
      static const struct machine_desc __mach_desc_##_type    \
       __used                         \
       __attribute__((__section__(".arch.info.init"))) = {    \
          .nr     = MACH_TYPE_##_type,        \
          .name       = _name,
      
      #define MACHINE_END     
      
      
      struct machine_desc {
          unsigned int        nr;     /* architecture number  */
          const char      *name;      /* architecture name    */
          ...
    • 在看编译的设备文件arch/arm/mach-s3c24xx/mach-mini2440.c中最后的MACHINE_START定义

      MACHINE_START(MINI2440, "MINI2440")
          /* Maintainer: Michel Pollet <buserror@gmail.com> */
          .atag_offset    = 0x100,
          .map_io     = mini2440_map_io,
          .init_machine   = mini2440_init,
          .init_irq   = s3c24xx_init_irq,
          .timer      = &s3c24xx_timer,
          .restart    = s3c244x_restart,
      MACHINE_END
      
    • 可看到这里定义了一个machine_desc( __mach_desc_MINI2440 )
      .nr=MACHINE_TYPE_MINI2440//本质就是机器码number
      .name=”MINI2440”

    • 内核启动时如下:
      bootloader将机器码等参数传入–飞凌里的boot如下call_linux(0, machine id, runaddr)– kernel接收到后运行如下:start_kernel–> setup_arch(&command_line) –>setup_machine_tags(machine_arch_type)–>for_each_machine_desc(p)

          //在所有编译进来的MACHIE中根据p->nr=machine_arch_type找出mdesc
          for_each_machine_desc(p)
              if (nr == p->nr) {
                  printk("Machine: %s\n", p->name);//显示"MINI2440"
                  mdesc = p;
                  break;
              }

2.3 修改Kconfig和添加.c文件

依上面的添加项修改

lxa2440         MACH_LXA2440        LXA2440 

2.3.1 增加menuconfig配置项,主要修改 arch/arm/mach-s3c24xx/Kconfig

 config MACH_LXA2440                                                                                      
     bool "LXA2440 development board"
     select S3C_DEV_NAND
     select S3C_DEV_USB_HOST
     help
         Say Y here if you are using the LXA2440

2.3.2 在 arch/arm/mach-s3c24xx/Makefile中添加machine.c文件的编译控制配置

78 obj-$(CONFIG_MACH_LXA2440)      += mach-lxa2440.o

2.3.3 关闭NAND_ECC校验

在drivers/mtd/nand/s3c2410.c文件内修改

 chip->ecc.mode   = NAND_ECC_NONE;  //旧的为NAND_ECC_SOFT

这是网上流传的方法 ,分析代码发现

    if (set->disable_ecc)
        chip->ecc.mode  = NAND_ECC_NONE;

只要set->disable_ecc为真就行,追踪下发现在mach-mini2440.c(就是我说的machine.c文件)的NAND分区设置里可以增加此参数,因此我用如下方法修改

static struct s3c2410_nand_set mini2440_nand_sets[] __initdata = {
    [0] = {
        .name       = "nand",
        .nr_chips   = 1,
        .nr_partitions  = ARRAY_SIZE(mini2440_default_nand_part),
        .partitions = mini2440_default_nand_part,
        .flash_bbt  = 1, /* we use u-boot to create a BBT */
        .disable_ecc =1,//增加此参数就行
    },
};

成功后启动会出现s3c24xx-nand s3c2440-nand: NAND ECC disabled字样

2.3.4 添加machine.c源码

用mach-mini2440或mach-smdk2440为模版修改
- 修改machine名字,不改也行,只要将MACHINE_START(LXA2440, "LXA2440")这句改好就行了。

```
cd  arch/arm/mach-s3c24xx/
cp  mach-mini2440.c  mach-lxa2440.c
vi mach-lxa2440.c
```
```
:%s/MINI/LXA/g
:%s/mini/lxa/g
```

- 检查时钟频率:s3c24xx_init_clocks(12000000);
- 依bootloader修改NAND分区

```
static struct mtd_partition lxa2440_default_nand_part[] __initdata = {
    [0] = {
        .name   = "Boot",
        .size   = 0x01000000,
        .offset = 0,
    },
    [1] = {
        .name   = "MyApp",
        .size   = 0x003c0000,
        .offset = 0x00140000,
    },
    [2] = {
        .name   = "Kernel",
        .size   = 0x00300000,
        .offset = 0x00500000,
    },
    [3] = {
        .name   = "fs_yaffs",
        .offset = 0x00800000,
        .size   = 0x03c00000,
    },
    [4] = {
        .name   = "WINCE",
        .offset = 0x04400000,
        .size   = 0x03c00000,   
    }
};

```
  • 添加LCD配置,我用的是4.3寸屏
    在static struct s3c2410fb_display lxa2440_lcd_cfg[] 末加入新增配置如下

        [4] = {
     .type       = (S3C2410_LCDCON1_TFT | S3C2410_LCDCON1_TFT24BPP),
     .width      = 480,
     .height     = 272,
     .pixclock   = 40000, /*这个不会算,所以就直接一个个填了没用宏定义 */
     .xres       = 480,
     .yres       = 272,
     .bpp        = 32,
     .left_margin    = 2,
     .right_margin   = 2,
     .hsync_len  = 41,
     .upper_margin   = 2,
     .lower_margin   = 2,
     .vsync_len  = 10, 
     .lcdcon5   = (S3C2410_LCDCON5_FRM565 |
                   S3C2410_LCDCON5_INVVLINE |
                   S3C2410_LCDCON5_INVVFRAME |
                   S3C2410_LCDCON5_HWSWP |
                   S3C2410_LCDCON5_PWREN),
    },
    

    然后修改lxa2440_features_str变量

    /*
     * lxa2440_features string
     *
     * t = Touchscreen present
     * b = backlight control
     * c = camera [TODO]
     * 0-9 LCD configuration
     *
     */
    static char lxa2440_features_str[12] __initdata = "4t";
    

    由下面的代码也可知,也可以通过bootloader的启动参数设置(lxa2440=4),

    static int __init lxa2440_features_setup(char *str)
    {
        if (str)
            strlcpy(lxa2440_features_str, str, sizeof(lxa2440_features_str));
        return 1;
    }
    
    __setup("lxa2440=", lxa2440_features_setup);//由__setup定义都可以通过command line传递参数
    
  • 添加触摸设备

    • 添加头文件:#include < plat/ts.h > //新片内核以更改了位置
    • 添加s3c2410_ts_mach_info结构

      static struct s3c2410_ts_mach_info lxa2440_ts_info = {                                                       
          .delay = 10000, //延时
          .presc = 49,    //预分频
          .oversampling_shift = 2,//采样次数 2的2次方
      };
      
    • 在初始化lxa2440_init(void)中初始化触摸设备

       s3c24xx_ts_set_platdata(&lxa2440_ts_info);
    • 修改lxa2440_parse_features中的case ‘t’,添加触摸设备s3c_device_ts,

              case 't':
                  if(features->done & FEATURE_TOUCH)
                      printk(KERN_INFO "LXA2440: '%c' ignored, "
                      "touchscreen not compiled in\n", f);
                  else {
                      features->optional[features->count++] = 
                              &s3c_device_ts;
                  }
                  features->done |= FEATURE_TOUCH;
                  break;
      
    • static struct platform_device *lxa2440_devices[]中添加adc设备

       &s3c_device_adc

三、make menuconfig 配置内核

  • 3.1首先更改System Type,选中我们添加的LXA2440设备
    System Type –>SAMSUNG S3C24XX SoCs Support —> S3C2440 Boards –>[*] LXA2440 development board,勾除MINI2440
  • 3.2 更改下Kernel Features ,勾上
    [*] Provide old way to pass kernel parameters //不同版本位置稍有区别,4.0.0之后的版本好像是在boot option里
    因为飞凌的bootloader版本旧,不兼容会导致卡死在Uncompressing 那里。具体分析可看我另一篇 基于FL2440的3.6.6内核移植出现Uncompressing Linux… done, booting the kernel.
  • 添加 触摸驱动
    Device Drivers->Input device support —> [] Touchscreens —> <> Samsung S3C2410/generic touchscreen input driver
  • 退出保存

四、编译下载

make clean 
make zImage

本方法同样适用于4.4.16 ,在4.5.4版本中移植网络有问题,无法NFS启动.照理说只有添加网卡平台设备就行了,可怎么也link up 不了,

五、参考文章

3.1 本移植记录是参考基于S3C2440的linux-3.6.6移植——内核移植,建立自己的平台系统,在此感谢
3.2 kernel内核中处理器类型的定义mach-types.h文件的生成

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值