1. 移植准备
1.1 获取Linux内核源代码(linux-2.6.32.tar.gz)
$ wget
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 的编译是否能正常通过。
执行:
使用缺省内核配置文件,s3c2410_defconfig 是 SMDK2440 的
缺省配置文件
编译时间较长
编译通过,在此我们先不必烧写到开发板验证它的正确性。
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")
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
使用linux dnw下载zImage至开发板,命令:
板子 ——> 选【k】 download linux kernel
PC ——> $ dnw arch/arm/boot/zImage
然后板子端选 [b] Boot the system
可以看到,kernel已经可以引导,单还不能完全跑起来。
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 = "supervivi",
-
.size = 0x00040000, //256K
-
.offset = 0,
-
},
-
[1] = {
-
.name = "param",
-
.size = 0x00020000, //128K
-
.offset = 0x00040000,
-
},
-
[2] = {
-
.name = "Kernel",
-
.size = 0x00500000, //5M
-
.offset = 0x00060000, //0x00040000 + 0x00020000
-
},
-
[3] = {
-
.name = "root",
-
.size = 0x40000000,
-
.offset = 0x00560000,
-
},
-
[4] = {
-
.name = "nand",
-
.size = 1024 * 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,
-
};
除此之外,还需要把 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;
即可。
重新编译、下载运行,可以看到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
4.1 下载yaffs2源代码
网上有人说使用下述方法下载yaffs2源码
- $ git clone git://www.aleph1.co.uk/yaffs2
但是,我用该命令未能下载下来,连接被重置。
我是直接进入下载()
选择最新版本,点击snapshot下载。
进入解压后源代码目录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
保存并退出。
然后重新编译内核:
并把zImage烧写至板子,同时也把FriendlyARM随机带的root_qtopia-128M.img烧写至root分区,然后测试,串口log如下:
- 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移植成功!
阅读(1193) | 评论(0) | 转发(0) |