移植 linux kernel 2.6.32 至 mini2440 板

1. 移植准备
1.1 获取Linux内核源代码(linux-2.6.32.tar.gz)
 $ wget http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.32.tar.gz
1.2 解压内核源代码
 $ tar xvzf linux-2.6.32.tar.gz
 得linux-2.6.32源代码目录
1.3 指定交叉编译变量
修改总目录下的 Makefile

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH   ?= $(SUBARCH)
CROSS_COMPILE ?=

改为:

export KBUILD_BUILDHOST := $(SUBARCH)
ARCH   ?= arm
CROSS_COMPILE ?= /usr/local/arm/4.3.2/bin/arm-linux-

其中,ARCH 是指定目标平台为 arm,CROSS_COMPILE 是指定交叉编译器
接下来,要测试一下 linux 的编译是否能正常通过。
执行:

$ make s3c2410_defconfig

使用缺省内核配置文件,s3c2410_defconfig 是 SMDK2440 的
缺省配置文件

$ make

编译时间较长
编译通过,在此我们先不必烧写到开发板验证它的正确性。

2. 开始移植
2.1 克隆建立自己的目标平台
   删除 arch/arm/mach-s3c2440/mach-mini2440.c
   重新复制 arch/arm/mach-s3c2440/mach-smdk2440.c 为arch/arm/mach-s3c2440/mach-mini2440.c
  修改:

MACHINE_START(S3C2440, "SMDK2440")

为:

MACHINE_START(MINI2440, "FriendlyARM Mini2440 development board")

注:此处第二个参数,写什么都不重要,重要的是第一个参数,它决定的了内核使用的机器码

请参考本人的另一篇文章,且对应机器码一定要和bootloader中传递给内核的机器码是一致的

http://my.oschina.net/hanshubo/blog/538823


2.2 修改时钟源频率

static void __init smdk2440_map_io(void)
        16934400  ---> 12000000


2.3 从 SMDK2440 到 MINI2440
 在mach-mini2440.c中替换所有的smdk2440为mini2440 (%s/smdk2440/mini2440/g)
并注释掉mini2440_machine_init(void)函数中的 smdk_machine_init()

2.4 编译测试

$ make mini2440_defconfig
$ make zImage

3. 移植 Nand 驱动并更改分区信息
Linux2.6.32 已 经 自 带 了 大 部 分 Nand Flash 驱 动 , 在linux-2.6.32/drivers/mtd/nand/nand_ids.c 文件中,定义了所支持的各种 Nand Flash 类型。
在 mach-mini2440.c 中加入以下代码:

static struct mtd_partition mini2440_default_nand_part[] = {
    [0] = {
        .name = "vboot",
        .size = 0x00060000,
        .offset = 0,
    },
    [1] = {
        .name = "Kernel",
        .size = 0x00500000, //5M
        .offset = 0x00060000, //0x00040000 + 0x00020000 
    },
    [2] = {
        .name = "root",
        .size = 0xfaa0000,
        .offset = 0x00560000,
    },
    [3] = {
        .name = "nand",
        .size = 256 * 1024 * 1024,
        .offset = 0x00000000,
    }
};

static struct s3c2410_nand_set mini2440_nand_sets[] = {
    [0] = {
        .name = "NAND",
        .nr_chips = 1,
        .nr_partitions = ARRAY_SIZE(mini2440_default_nand_part),
        .partitions = mini2440_default_nand_part,
    },
};

static struct s3c2410_platform_nand mini2440_nand_info = {
    .tacls = 20,
    .twrph0 = 60,
    .twrph1 = 20,
    .nr_sets = ARRAY_SIZE(mini2440_nand_sets),
    .sets = mini2440_nand_sets,
    .ignore_unset_ecc = 1,
};

注:

1、此处代码放在

static void __init mini2440_map_io(void)

函数定义的下面 

2、分区部分代码每个人的情况都不一样,要根据自己的实际情况进行编写,原则:NAND FLASH里写了什么内容,

3、且此处分区的定义还和后面提到的linux command line中的 root=/dev/mtdblockX 相对应的,本人此处root的坐标是2,所以root=/dev/mtdblock2

除此之外,还需要把 nand flash 设备注册到系统中,同时加入RTC

static struct platform_device *mini2440_devices[] __initdata = {
    &s3c_device_usb,
    &s3c_device_lcd,
    &s3c_device_wdt,
    &s3c_device_i2c0,
    &s3c_device_iis,
    &s3c_device_nand, // new added
    &s3c_device_rtc, //new added
};

此时执行 make zImage 会报错如下:

CHK include/linux/version.h
make[1]: `include/asm-arm/mach-types.h' is up to date.
  CHK include/linux/utsrelease.h
  SYMLINK include/asm -> include/asm-arm
  CALL scripts/checksyscalls.sh
  CHK include/linux/compile.h
  CC arch/arm/mach-s3c2440/mach-mini2440.o
arch/arm/mach-s3c2440/mach-mini2440.c:49: error: array type has incomplete element type
arch/arm/mach-s3c2440/mach-mini2440.c:50: error: array index in non-array initializer
arch/arm/mach-s3c2440/mach-mini2440.c:50: error: (near initialization for 'mini2440_default_nand_part')
arch/arm/mach-s3c2440/mach-mini2440.c:51: error: field name not in record or union initializer
arch/arm/mach-s3c2440/mach-mini2440.c:51: error: (near initialization for 'mini2440_default_nand_part')
arch/arm/mach-s3c2440/mach-mini2440.c:52: error: field name not in record or union initializer

这是因为缺少以下头文件:

#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
#include <linux/mtd/nand_ecc.h>
#include <linux/mtd/partitions.h>
#include <plat/nand.h>


加入重新编译,生成arch/arm/boot/zImage,下载至板子,重新启动,结果产生kernel panic如下:

S3C24XX NAND Driver, (c) 2004 Simtec Electronics 
s3c24xx-nand s3c2440-nand: Tacls=4, 39ns Twrph0=8 79ns, Twrph1=8 79ns 
Unable to handle kernel NULL pointer dereference at virtual address 00000018 
pgd = c0004000 
[00000018] *pgd=00000000 
Internal error: Oops: 5 [#1] 
last sysfs file: 
Modules linked in: 
CPU: 0 Not tainted (2.6.32 #2) 
PC is at s3c24xx_nand_probe+0x2d8/0x514 
LR is at s3c24xx_nand_probe+0x1a4/0x514 
pc : [<c01d9d44>] lr : [<c01d9c10>] psr: 60000013 
sp : c3823f08 ip : 00000000 fp : 00000001 
r10: 00000000 r9 : 00000000 r8 : 00000000 
r7 : c03cf388 r6 : 00000000 r5 : c39b68c0 r4 : c3895800 
r3 : 00000001 r2 : c3895988 r1 : c4c00000 r0 : 00000002 
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel 
Control: c000717f Table: 30004000 DAC: 00000017 
Process swapper (pid: 1, stack limit = 0xc3822270) 
Stack: (0xc3823f08 to 0xc3824000)

上面第二行的内容说明我们更改的nand驱动参数根本就没有生效,分析Linux内核中的nand flash驱动drivers/mtd/nand/s3c2410.c文件中的相应函数,
其中的static int s3c2410_nand_setrate(struct s3c2410_nand_info *info)函数发现:

struct s3c2410_platform_nand *plat = info->platform;
        int tacls_max = (info->cpu_type == TYPE_S3C2412) ? 8 : 4; 
         …………
    info->clk_rate = clkrate;
        clkrate /= 1000; /* turn clock into kHz for ease of use */

        if (plat != NULL) {
                tacls = s3c_nand_calc_rate(plat->tacls, clkrate, tacls_max);
                twrph0 = s3c_nand_calc_rate(plat->twrph0, clkrate, 8);
                twrph1 = s3c_nand_calc_rate(plat->twrph1, clkrate, 8);
        } else { 
          /* default timings */
                tacls = tacls_max;
                twrph0 = 8;
                twrph1 = 8; 
            }

        if (tacls < 0 || twrph0 < 0 || twrph1 < 0) {
                dev_err(info->device, "cannot get suitable timings\n");
                return -EINVAL;
        }

        dev_info(info->device, "Tacls=%d, %dns Twrph0=%d %dns, Twrph1=%d %dns\n",
               tacls, to_ns(tacls, clkrate), twrph0, to_ns(twrph0, clkrate), twrph1, to_ns(twrph1, clkrate));

由以上内容可以看出,你的内核并没有使用你的mini2440_nand_info结构体中的配置,而是使用了它的默认配给,即

} else {      
          /* default timings */
                tacls = tacls_max;
                twrph0 = 8;
                twrph1 = 8;      
            }

中的配置信息。这点和你的内核输出s3c24xx-nand s3c2440-nand: Tacls=4, 39ns Twrph0=8 79ns, Twrph1=8 79ns完全符合。

解决方法:
只需在mach-mini2440.c的初始化函数mini2440_machine_init(void)里加入

s3c_device_nand.dev.platform_data=&mini2440_nand_info;

static void __init mini2440_machine_init(void)
{
	s3c24xx_fb_set_platdata(&mini2440_fb_info);
	s3c_i2c0_set_platdata(NULL);

	platform_add_devices(mini2440_devices, ARRAY_SIZE(mini2440_devices));

	s3c_device_nand.dev.platform_data = &mini2440_nand_info;
	//smdk_machine_init();
}

即可。
重新编译、下载运行,可以看到nand分区信息:

S3C24XX NAND Driver, (c) 2004 Simtec Electronics 
s3c24xx-nand s3c2440-nand: Tacls=3, 29ns Twrph0=7 69ns, Twrph1=3 29ns 
s3c24xx-nand s3c2440-nand: NAND soft ECC 
NAND device: Manufacturer ID: 0xec, Chip ID: 0xf1 (Samsung NAND 128MiB 3,3V 8-bit) 
Scanning device for bad blocks 
Creating 5 MTD partitions on "NAND 128MiB 3,3V 8-bit": 
0x000000000000-0x000000040000 : "supervivi" 
uncorrectable error : 
0x000000040000-0x000000060000 : "param" 
uncorrectable error : 
0x000000060000-0x000000560000 : "Kernel" 
uncorrectable error : 
0x000000560000-0x000008000000 : "root" 
ftl_cs: FTL header not found. 
0x000000000000-0x000008000000 : "nand"

至此,就完成了 nand flash 驱动的移植

4.  移植 yaffs2

A、下载yaffs2源代码

我是直接进入http://www.yaffs.net下载

下载地址:

http://www.aleph1.co.uk/gitweb?p=yaffs2.git;a=summary

选择最新版本,点击snapshot下载。

进入解压后源代码目录yaffs2-d43e901:

cd yaffs2-d43e901

4.2为内核打上 yaffs2 补丁

./patch-ker.sh c m ../../kernel/linux-2.6.32

报以下信息

Updating ../../kernel/linux-2.6.32/fs/Kconfig
Updating ../../kernel/linux-2.6.32/fs/Makefile

此时,inux-2.6.32/fs 目录,可以看到已经多了一个 yaffs2 目录

4.3配置和编译带 YAFFS2 支持的内核
在 Linux 内核源代码根目录运行:make menuconfig
选中

Kernel Features --->
    [*] Use the ARM EABI to compile the kernel
    [*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL) (NEW)
File systems ---> 
     [*] Miscellaneous filesystems --->
                <*> yaffs2 file system support
                -*- 512 byte / page devices

保存并退出。
然后重新编译内核

make zImage

并把zImage烧写至板子

同时也把FriendlyARM随机带的root_qtopia-128M.img烧写至root分区,然后测试,串口log如下:

注:此处本人是自己制作的yaffs2文件系统image

以下为原文作者,遇到的问题:

FAT: unable to read boot sector 
VFS: Cannot open root device "mtdblock2" or unknown-block(31,2) 
Please append a correct "root=" boot option; here are the available partitions: 
1f00 256 mtdblock0 (driver?) 
1f01 128 mtdblock1 (driver?) 
1f02 5120 mtdblock2 (driver?) 
1f03 125568 mtdblock3 (driver?) 
1f04 131072 mtdblock4 (driver?) 
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(31,2) 
[<c00319f8>] (unwind_backtrace+0x0/0xdc) from [<c02d9044>] (panic+0x40/0x118) 
[<c02d9044>] (panic+0x40/0x118) from [<c0009000>] (mount_block_root+0x1d0/0x210) 
[<c0009000>] (mount_block_root+0x1d0/0x210) from [<c0009298>] (prepare_namespace+0x164/0x1bc) 
[<c0009298>] (prepare_namespace+0x164/0x1bc) from [<c00085bc>] (kernel_init+0xd8/0x10c) 
[<c00085bc>] (kernel_init+0xd8/0x10c) from [<c002ce14>] (kernel_thread_exit+0x0/0x8)

重点看第二行内容,这个说明根据bootloader传过来的linux_cmd_line,不能找到真正的root分区。由于上文对nand flash分区如下:

0x000000000000-0x000000040000 : "supervivi" 
0x000000040000-0x000000060000 : "param" 
0x000000060000-0x000000560000 : "Kernel" 
0x000000560000-0x000040560000 : "root" 
0x000000000000-0x000040000000 : "nand"

说明root内容存放在/dev/mtdblock3上,因此,先检查bootloader设置。
按q进入vivi command line

Supervivi> param show 
Number of parameters: 9 
name                                 :                                  hex                                           integer 
------------------------------------------------------------------------------------------------------------- 
mach_type                        :                             000007cf                                       1999 
media_type                       :                             00000003                                          3 
boot_mem_base               :                             30000000                                805306368 
baudrate                            :                             0001c200                                    115200 
xmodem                            :                             00000001                                           1 
xmodem_one_nak            :                             00000000                                           0 
xmodem_initial_timeout :                             000493e0                                       300000 
xmodem_timeout            :                              000f4240                                      1000000 
boot_delay                        :                              01000000                                     16777216 
Linux command line: noinitrd root=/dev/mtdblock2 init=/linuxrc console=ttySAC0

linux_cmd_line设置不对,修改之

Supervivi> param set linux_cmd_line "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0" 
Change linux command line to "noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0" 
Supervivi> param save 
Found block size = 0x00020000 
Erasing... ... done 
Writing... ... done 
Written 49152 bytes 
Saved vivi private data
Supervivi> menu

重新启动,输出log如下:

S3C24XX RTC, (c) 2004,2006 Simtec Electronics 
s3c2410-rtc s3c2410-rtc: rtc disabled, re-enabling 
s3c2410-rtc s3c2410-rtc: rtc core: registered s3c as rtc0 
S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics 
s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled 
Advanced Linux Sound Architecture Driver Version 1.0.21. 
No device for DAI UDA134X 
No device for DAI s3c24xx-i2s 
ALSA device list: 
  No soundcards found. 
TCP cubic registered 
NET: Registered protocol family 17 
s3c2410-rtc s3c2410-rtc: hctosys: invalid date/time 
yaffs: dev is 32505859 name is "mtdblock3" rw 
yaffs: passed flags "" 
VFS: Mounted root (yaffs filesystem) on device 31:3. 
Freeing init memory: 140K 
hwclock: settimeofday() failed: Invalid argument 
[01/Jan/1970:00:00:12 +0000] boa: server version Boa/0.94.13 
[01/Jan/1970:00:00:12 +0000] boa: server built Mar 26 2009 at 15:28:42. 
[01/Jan/1970:00:00:12 +0000] boa: starting server pid=933, port 80 
                                                                                                                           
open device leds: No such file or directory 
Try to bring eth0 interface up......ifconfig: SIOCGIFFLAGS: No such device 
ifconfig: SIOCSIFHWADDR: No such device 
ifconfig: SIOCSIFADDR: No such device 
route: SIOCADDRT: Network is unreachable 
Done 
                                                                                                                           
Please press Enter to activate this console.

至此说明kernel已经可以成功mount rootfs,linux kernel移植成功

注:本人用的交叉编译器是:arm-linux-gcc 4.3.2



你可能感兴趣的:(移植 linux kernel 2.6.32 至 mini2440 板)