第一篇博客就总结一下linux的移植吧,最近在参照相广超老师的视频教程移植linux以及学习yaffs2根文件系统的制作,跟着视频操作了之后,开发板并不能成功加载文件系统,所以觉得需要总结一下移植经验,与人分享,也为以后移植做个参考。
内核源码:linux-2.6.31.tar.bz2(官网地址)
编译工具:arm-linux-gcc-4.3.3.tar.bz2(网上搜,还不知道有没有官网可以下载各种版本的,哪位朋友知道留言告诉我哈)
《》解压linux源码
#tar xjvf linux-2.6.31.tar.bz2
《》修改Makefile的183行,指定处理器架构以及编译工具
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-
《》修改时钟:
修改arch/arm/mach-s3c2440/mach-smdk2440.c的163行
static void __init smdk2440_map_io(void)
{
s3c24xx_init_clocks(12000000); //输入时钟为12MHz
}
《》修改机器码(要与bootloader的匹配)
在u-boot和kernel中都会有一个机器码(即:MACH_TYPE),
只有这两个机器码一致时才能引导内核,否则就会出现如下mach的错误信息:
Error: unrecognized/unsupported machine ID (r1 = 0x0000270f).
Available machine support:
ID (hex) NAME
0000016a SMDK2440
Please check your kernel config and/or bootloader.
我使用的是UBOOT,在uboot源码目录的include/asm-arm/mach-types.h中
定义了uboot的机器码,找到S3C2440对应的机器码是168
#define MACH_TYPE_TOTO 361
#define MACH_TYPE_S3C2440 168
#define MACH_TYPE_KS8695P 363
那么我们也把linux中的机器码修改成168就可以了
在arch/arm/tools/mach-types文件中找到s3c2440对应的机器码(379行)
改为168
s3c2440 ARCH_S3C2440 S3C2440 168
《》配置内核
make menuconfig
在配置菜单中选择"Load an AlternateConfiguration File" ,输入2440的默认
配置文件:arch/arm/configs/s3c2410_defconfig,这个文件就是S3C24XX
系列开发板板级支持包(BSP)然后选择 OK,按回车。
进入"System Type"选项单,里面的选项保持默认在"S3C24XXMachine"选项中只配置这几项(其他的选项取消):
S3C2410 Machine --->
[*] SMDK2410/A9M2410
S3C2440 Machine --->
[*] SMDK2440
[*] SMDK2440 with S3C2440 cpu moudle
配置完后,回到主菜单,选择这一项"Save an Alternate Configuration File" ,输入要保存的配置文件名称:.config (默认)或自己取名:TX2440A_config,退出。
编译内核: #make zImage
编译完后,会在arch/arm/boot下生成zImage内核镜像文件,可以修改该目录下的Makefile, 在第57行下面添加:
@cp -f arch/arm/boot/zImage zImage
@echo ' Kernel: $@ is ready '
这样执行make zImage后,就把生成的zImage拷到内核根目录下。
如果希望在在执行make distclean时,也同时把zImage删除,可以修改内核根目录下Makefile 的第1247行,在后面加上:
-type f -print | xargs rm -f rm zImage
把 zImage 镜像烧进 NandFlash 跑一下,看是否正常打印出信息,如果第一步能正常引导内核,那就开始进行第二步,添加驱动。
注意,系统启动最后可能会出现这个错误:
Kernel panic - not syncing: Attempted to kill init!
然后出打印出一些很乱的东西。因为用4.x.x版本的交叉编译器使用EABI,但内核默认是不支持EABI编译的,所以编译出的系统会报错,
但用3. x.x版本的编译器就不会出现这个问题。解决办法是,配置内核支持EABI编译:
Kernel Features --->
[*] Use the ARM EABI to compile the kernel
[*] Allow old ABI binaries to run with this kernel (EXPERIMENTA)
《》支持NandFlash
这里我们要使NandFlash驱动同时支持 64M,256M 或更高容量。
修改arch/arm/plat-s3c24xx/common-smdk.c文件,在第 110 行:
static struct mtd_partition smdk_default_nand_part[] = {
#if defined(CONFIG_64M_NAND)
[0] = {
.name = "boot",
.offset = 0,
.size = SZ_1M,
},
[1] = {
.name = "kernel",
.offset = SZ_1M + SZ_128K,
.size = SZ_4M,
},
[2] = {
.name = "yaffs2",
.offset = SZ_1M + SZ_128K + SZ_4M,
.size = SZ_64M - SZ_4M - SZ_1M - SZ_128K,
}
#elif defined(CONFIG_256M_NAND)
[0] = {
.name = "boot",
.offset = 0,
.size = SZ_1M,
},
[1] = {
.name = "kernel",
.offset = SZ_1M + SZ_128K,
.size = SZ_4M,
},
[2] = {
.name = "yaffs2",
.offset = SZ_1M + SZ_128K + SZ_4M,
.size = SZ_256M - SZ_4M - SZ_1M - SZ_128K,
}
#endif
};
这个分区名字可以随便起。
接下来修改Nand读写匹配时间,这个改不改应该问题都不大,我认为是根据Nand的读写特性
相关的,也就是查芯片资料得到的值,每种Nand的值都不一样,还是在这个文件中第140行:
static struct s3c2410_platform_nand smdk_nand_info = {
.tacls = 10,
.twrph0 = 25,
.twrph1 = 10,
.nr_sets = ARRAY_SIZE(smdk_nand_sets),
.sets = smdk_nand_sets,
};
修改 Kconfig 文件,在配置时选择NAND类型,修改driver/mtd/nand/Kconfig,在172行,添加:
choice
prompt "Nand Flash Capacity Select"
depends on MTD
config 64M_NAND
boolean "64M NAND For TX-2440A"
depends on MTD
config 256M_NAND
boolean "256M NAND For TX-2440A"
depends on MTD
endchoice
配置内核,支持 NandFlash
Device Drivers --->
<*> Memory Technology Device (MTD) support --->
[*] MTD partitioning support
<*> NAND Device Support --->
<*> NAND Flash support for S3C2410/S3C2440 SoC
[*] S3C2410 NAND Hardware ECC <—这个一定要选上
Nand Flash Capacity Select(256M Nand For TX-2440A)--->
启动时输出:
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c24xx-nand s3c2440-nand: Tacls=1, 10ns Twrph0=3 30ns, Twrph1=1 10ns
s3c24xx-nand s3c2440-nand: NAND hardware ECC
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB3,3V 8-bit)
Scanning device for bad blocks
Creating 3 MTD partitions on "NAND 256MiB 3,3V 8-bit":
0x000000000000-0x000000100000 : "boot"
0x000000120000-0x000000520000 : "kernel"
0x000000520000-0x000010000000 : "yaffs2"
《》支持yaffs2文件系统
下载yaffs2源码(去官网下载,yaffs2文件系统官网下载),最好下载10年附近的版本,因为linux2.6.31就是09年中旬的嘛,
解压,进入yaffs2目录:
#tar xzvf yaffs2.tar.gz
#cd /yaffs2/
给内核打上yaffs2文件系统的补丁,执行:
#./patch-ker.sh c /………/linux-2.6.31/ <—这个是你的内核源码的目录
这时内核源码fs目录下多了一个yaffs2目录,同时Makefile文件和Kconfig文件也增加了yaffs2的配置和编译条件。
配置对 yaffs2 支持
这部分配置的比较多,可根据自己的需要进行配置,把不用的文件系统都去掉,下面是几个主要的配置:
File systems --->
DOS/FAT/NT Filesystems --->
<*> MSDOS fs support
<*> VFAT (Windows95) fs support
Miscellaneous filesystems --->
<*> YAFFS2 file system support
[*] Autoselect yaffs2 format 这个一定要选上,因为下一步就是加载我们制作好的yaffs2文件系统
说明:现在内核已经支持NandFlash和yaffs2文件系统,将内核烧入NandFlash后,再烧入yaffs2
文件系统,可以使用制作好的文件系统,也可以自己制作,详细的制作文件系统方法,请看后续。
启动时(成功挂载文件系统)输出:
yaffs: dev is 32505858 name is "mtdblock2"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.2, "mtdblock2"
yaffs: auto selecting yaffs2
yaffs_read_super: isCheckpointed 0
VFS: Mounted root (yaffs filesystem) on device 31:2.
Freeing initmemory: 196K
《》一个错误的解决办法
经过以上的修改及配置,把制作好的镜像(uboot,llinux内核,yaffs2文件系统)全部烧进开发板的NandFlash中,重启开发板,内核启动后出现一个错误
end_request: I/O error, dev mtdblock2,sector 0 Buffer I/O error on device mtdblock2, logical block 0
原因分析:由于内核是通过uboot烧写到nandflash中,因此uboot产生的ecc校验码与内核的ecc校验码不同,所以需要关闭内核的ecc校验。
解决方法:
打开内核源码目录的drivers/mtd/nand/s3c2410.c文件
在s3c2410_nand_init_chip()函数中修改如下:
把NAND_ECC_HW和NAND_ECC_SOFT替换成NAND_ECC_NONE,
即关闭ecc校验
if(hardware_ecc) {
chip->ecc.calculate= s3c2410_nand_calculate_ecc;
chip->ecc.correct = s3c2410_nand_correct_data;
chip->ecc.mode = NAND_ECC_NONE;//NAND_ECC_HW;
switch(info->cpu_type) {
caseTYPE_S3C2410:
chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
chip->ecc.calculate= s3c2410_nand_calculate_ecc;
break;
caseTYPE_S3C2412:
chip->ecc.hwctl = s3c2412_nand_enable_hwecc;
chip->ecc.calculate =s3c2412_nand_calculate_ecc;
break;
caseTYPE_S3C2440:
chip->ecc.hwctl = s3c2440_nand_enable_hwecc;
chip->ecc.calculate = s3c2440_nand_calculate_ecc;
break;
}
}else {
// chip->ecc.mode = NAND_ECC_SOFT;
chip->ecc.mode = NAND_ECC_NONE;
}
至此,错误解决,开发可以正常挂载文件系统了
下一步就是用busybox制作yaffs2文件系统啦,请参照下一篇博客