内核编译与移植(二)

前面编译好的新内核还不能正常使用,下面接着讨论如何进行修改。
由于开发板上使用的是NandFlash,所以要让内核正常操作它,还需要进行修改。S3C2416内置了NandFlash接口和相关配置寄存器,但要Linux很好地支持具体型号的NandFlash芯片,还需要对内核的相关文件进行修改。
在Linux中,是通过MTD来对NandFlash进行访问的。MTD(Memory Technology Device)即内存技术设备,是Linux对ROM、NorFlash、NandFlash等存储设备抽象出来的一个设备层,它向上提供统一的访问接口,屏蔽了底层硬件的操作和各类存储设备的差别。Linux内核针对S3C2416定义的NandFlash驱动,位于文件drivers/mtd/nand/s3c2410.c中,因此,只要对该文件进行针对性的修改即可。执行“cd /linux-3.0.99/drivers/mtd/nand”进入该目录,然后用vi打开文件s3c2410.c(打开前可先备份一下),先找到其中一个名为“nand_hw_eccoob”的结构体,修改其中的三项参数,如下:
.eccbytes = 4,
.eccpos = {40, 41, 42, 43},
.oobfree = {{2, 38}}
第一句表示告诉驱动ecc需要4个字节,第二句告诉驱动这些ecc字节放在哪里,第三句中的2表示偏移量(即从第2个字节开始),38表示ecc字节共有38个可以供用户使用。这些更改与具体使用的NandFlash芯片相关,更改完成后存一下盘。
接下来找到函数“s3c2410_nand_correct_data”,把该函数全部重写成如下内容:
static int s3c2410_nand_correct_data(struct mtd_info *mtd, u_char *dat,
u_char *read_ecc, u_char *calc_ecc)
{
int ret = -1;
unsigned long nfestat0, nfmeccdata0, nfmeccdata1;
unsigned char err_type;
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
pr_debug("%s(%p,%p,%p,%p)\n", __func__, mtd, dat, read_ecc, calc_ecc);
nfmeccdata0 = (read_ecc[1] << 16) | read_ecc[0];
nfmeccdata1 = (read_ecc[3] << 16) | read_ecc[2];
writel(nfmeccdata0, info->regs + S3C2440_NFECCD0);
writel(nfmeccdata0, info->regs + S3C2440_NFECCD1);
nfestat0 = readl(info->regs + S3C2440_NFESTAT0);
err_type = nfestat0 & 0x3;
switch (err_type) {
case 0:
ret = 0;
break;
case 1:
printk("s3c-nand: 1 bit error detected at byte %ld, correcting from "
"0x%02x ", (nfestat0 >> 7) & 0x7ff, dat[(nfestat0 >> 7) & 0x7ff]);
dat[(nfestat0 >> 7) & 0x7ff] ^= (1 << ((nfestat0 >> 4) & 0x7));
printk("to 0x%02x...OK\n", dat[(nfestat0 >> 7) & 0x7ff]);
ret = 1;
break;
case 2:
case 3:
printk("s3c-nand: ECC uncorrectable error detected\n");
ret = -1;
break;
}
return ret;
}
改完后存一下盘。接下来再继续找到函数“s3c2412_nand_enable_hwecc”,在其中的“ctrl = readl(info->regs + S3C2440_NFCONT);”一句下面,再加上下面两句:
ctrl |= S3C2412_NFCONT_INIT_MAIN_ECC;
ctrl &= ~S3C2412_NFCONT_MAIN_ECC_LOCK;
改完后再存一下盘。再继续往下找,找到函数“s3c2412_nand_calculate_ecc”,把该函数也全部重写成如下内容:
static int s3c2412_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code)
{
unsigned long ctrl;
unsigned long nfmecc0;
struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
ctrl = readl(info->regs + S3C2440_NFCONT);
ctrl |= S3C2412_NFCONT_MAIN_ECC_LOCK;
writel(ctrl, info->regs + S3C2440_NFCONT);
nfmecc0 = readl(info->regs + S3C2412_NFMECC0);
ecc_code[0] = nfmecc0 & 0xff;
ecc_code[1] = (nfmecc0 >> 8) & 0xff;
ecc_code[2] = (nfmecc0 >> 16) & 0xff;
ecc_code[3] = (nfmecc0 >> 24) & 0xff;
pr_debug("calculate_ecc: returning ecc %02x,%02x,%02x\n", ecc_code[0], ecc_code[1], ecc_code[2]);
return 0;
}
完成后存一下盘,再继续找,找到函数“s3c2410_nand_update_chip”,在其中再找到“if (chip->page_shift > 10)”一句,把这整个if……else……语句都删除,然后改成下面的内容:
if (chip->page_shift > 10) {
chip->ecc.size = 2048;
chip->ecc.bytes = 4;
chip->ecc.layout = &nand_hw_eccoob;
} else {
chip->ecc.size = 512;
chip->ecc.bytes = 4;
chip->ecc.layout = &nand_hw_eccoob;
}
更改完成后就可存盘退出了。到此,整个文件s3c2410.c就改好了。
以上更改就要是针对特定的NandFlash芯片进行的,在硕数的核心板上使用的是一片型号为K9F1G08UOC,容量为128MB的SLC型NandFlash芯片。由于NandFlash芯片的特点,其必须要有ECC(Error Correcting Code)功能的参与才能正确存储数据,所以上面的修改主要就是针对些进行的。关于具体的NandFlash芯片资料可上网查询,这里就不多说了。
完成上述修改后,还需要告诉内核你的NandFlash是怎么分区的,以让内核能正确地读写分区,否则内核会使用默认分区进行读写,这表现在启动时会出现如下图所示的信息。

 

可见内核默认把NandFlash分成了7个分区,这显然不符合开发板上的原有分区,所以内核不能正确启动,必须重新进行分区。分区在文件arch/arm/plat-s3c24xx/common-smdk.c中定义,用vi打开该文件,找到结构体定义“mtd_partition smdk_default_nand_part[] ”,把它全部重写成下面的内容:
static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "UBOOT",
.size = SZ_1M,
.offset = 0,
},
[1] = {
.name = "kernel",
.offset = SZ_1M,
.size = 0x300000,
},
[2] = {
.name = "ROOTFS",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_SIZ_FULL,
}
};
其它内容不要更改,完成后存盘退出。这样进行分区就符合原来硕数核心板上的分区结构了。接下来还需要对内核进行适当的配置,进入到linux-3.0.99源码目录,执行“make menuconfig”(如果还没有默认配置需要先执行“make s3c2410_defconfig”),然后在文本对话框中进行如下配置:
1.勾选Kernel Features -> Use the ARM EABI to compile the kernel项及其下的Allow old ABI binaries to run with this kernel项。
2.勾选Drivers Divers -> Memory Technology Device (MTD) Support -> Enable UBI - Unsorted block images项,并勾选NAND Device Support -> NAND Flash support for SamSung S3C SOCs项及其下的SamSung S3C NAND Hardwaree ECC项。
3.勾选File System -> Miscellaneous filesystem -> UBIFS file system support项。
完成后保存退出,接下来就可以编译修改过的内核了,先执行“make clean”命令清一下内核,然后执行“make zImage”对内核进行编译。完成后把生成的zImage内核映像文件下载到开发板上,启动内核,这次就可以进入到命令行提示符了,如下图所示。

由于原来的核心板上已经写入了UBIFS形式的根文件系统,所以只要内核能正确读写NandFlash并且正确识别分区,就可以正常启动了。看一下在启动过程中显示的分区信息,如下图所示。

可以看到,和我们修改的分区完全一致。虽然此时系统已经正常启动了,但实际上还不能用,或者说内核移植只完成了一半,因为还有很多驱动没有移植,比如从前一张图中就可以看到一句“ifconfig: SIOCSIFADDR: No such device”,这表明网卡还未正常工作,所以接下来还要进行网卡驱动的移植。

posted @ 2020-02-10 00:05  fxzq  阅读(421)  评论(0编辑  收藏  举报