|
好了,在了解Nand Flash组成和Yaffs/yaffs2文件系统结构后,我们再回到u-boot中。目前,在u-boot中已经有对Cramfs、Jffs2等文件系统的读写支持,但与带有数据校验等功能的OOB区的Yaffs/Yaffs2文件系统相比,他们是将所有文件数据简单的以线性表形式组织的。所以,我们只要在此基础上通过修改u-boot的Nand Flash读写命令,增加处理00B区域数据的功能,即可以实现对Yaffs/Yaffs2文件系统的读写 系统启动一半 发现很多flash 坏块,接下来出现N多ECC错误,以前没有的,正在找解决办法。。。
|
|
②、在原来对Nand操作的命令集列表中添加Yaffs2对Nand的写命令,如下:
|
U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand, //注意:这里只添加了yaffs2的写命令,因为我们只用u-boot下载(即写)功能,所以我们没有添加yaffs2读的命令
|
接着,在该文件中对nand操作的do_nand函数中添加yaffs2对nand的操作,如下:
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) if (argc < 4) addr = (ulong)simple_strtoul(argv[2], NULL, 16); read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */ s = strchr(cmd, '.'); //添加yaffs2相关操作,注意该处又关联到nand_write_skip_bad函数 #if defined(CONFIG_MTD_NAND_YAFFS2) else if (!strcmp(s, ".oob")) if (read) printf(" %zu bytes %s: %s\n", size, read ? "read" : "written", ret ? "ERROR" : "OK"); return ret == 0 ? 0 : 1; |
③、在include/linux/mtd/mtd.h头文件的mtd_info结构体中添加上面用到rw_oob和skipfirstblk数据成员,如下:
|
|
④、在第二步关联的nand_write_skip_bad函数中添加对Nand OOB的相关操作,如下:
|
int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length, u_char *buffer) #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if (((*length)%(nand->oobsize+nand->writesize)) != 0) datapages = *length/(datasize+oobsize); /* Reject writes, which are not page aligned */ len_incl_bad = get_len_incl_bad (nand, offset, *length); if ((offset + len_incl_bad) >= nand->size) { #if !defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support return rval; while (left_to_write > 0) { WATCHDOG_RESET (); if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) { #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support if (left_to_write < (nand->erasesize - block_offset)) printf("\rWriting at 0x%llx -- ",offset); //add yaffs2 file system support
left_to_write -= write_size; #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support } return 0; |
⑤、在第四步nand_write_skip_bad函数中我们看到又对nand_write函数进行了访问,所以这一步是到nand_write函数中添加对yaffs2的支持,如下:
|
|
OK,对yaffs2支持的代码已修改完毕,重新编译u-boot并下载到nand中,启动开发板,在u-boot的命令行输入:nand help查看nand的命令,可以看到多了一个 nand write[.yaffs2]的命令,这个就是用来下载yaffs2文件系统到nand中的命令了。
⑥、使用nand write[.yaffs2]命令把事前制作好的yaffs2文件系统下载到Nand Flash中(yaffs2文件系统的制作请参考:Linux-2.6.30.4在2440上的移植之文件系统),下载操作步骤和效果图如下:
|
⑦、结合u-boot和内核来测试启动下载的yaffs2文件系统
设置u-boot启动参数bootargs,注意:这一长串参数要与内核配置里面的Boot options-->Default kernel command string的设置要一致。特别是mtdblock3要根据内核具体的分区来设,在上一篇中讲到了内核中Nand的分区情况,u-boot属于mtdblock0,param属于mtdblock1,kernel属于mtdblock2,root就属于mtdblock3,所以这里要设置成root=/dev/mtdblock3,否则文件系统无法启动成功,会出现一些什么I/O之类的错误
好了,最后重启开发板,内核引导成功,yaffs2文件系统也挂载成功,效果图如下:
系统启动一半 发现很多flash 坏块,接下来出现N多ECC错误
Scanning device for bad blocks
Bad eraseblock 3744 at 0x03a80000Bad eraseblock 3745 at 0x03a84000
Bad eraseblock 3746 at 0x03a88000
Bad eraseblock 3747 at 0x03a8c000
Bad eraseblock 3748 at 0x03a90000
。。。。。。
。。。。。。
block 3822 is bad
block 3823 is bad
block 3824 is bad
block 3825 is bad
**>>yaffs ecc error unfixed on chunk 32:0
**>>yaffs ecc error unfixed on chunk 32:1
**>>Block 1 marked for retirement
**>>yaffs ecc error unfixed on chunk 33:0
**>>yaffs ecc error unfixed on chunk 33:1
**>>Block 1 marked for retirement
。。。。。。
首先解决flash坏块的问题,我犯了一个低级错误,yaffs系统文件的大小是0x39d9020,但是我烧写命令写的是0x3d9c000,如果是写bootloader或linux内核文件写大一点问题不大,但是在写yaffs时会写oob区,导致系统检测时会出现很多"假"flash坏块,换正确的命令后linux启动时不再报flash坏块错误,但是依然有很多ecc校验错误。
分析一下出现ecc错误的原因,首先在以前使用同样的yaffs文件与linux内核文件没有问题,说明我的yaffs文件与linux内核的ecc校验是匹配的,不存在yaffs制作工具与内核版本不匹配导致ecc校验错误的问题。那会不会是新的uboot在写的oob时写错了呢,使用uboot的nand dump.oob 命令查看第一个page的oob,与yaffs文件的oob做一下对比,发现两者完全一致。那就奇怪了,在网上查了一下针对utu2440的uboot移植资料,没有找到有成功移植写yaffs的案例。只能自己来分析、查找了。
考虑到使用开发板自带的uboot(无源代码)烧写yaffs是可以正常启动的,那就首先用开发板自带的uboot烧写一遍,dump出来看一下,然后再用新移植的uboot写yaffs,将两者做一下对比。说干就干,写uboot、写yaffs、dump oob、记录、比较,最终发现了其中的奥妙(^_^,开心啊):
yaffs 文件 page1 的oob信息: |
结论:
针对utu2440的开发板在写oob时需要做以下变换:
每次在写完512字节的数据后再写16个字节的oob,此时需要首先将oob的第8位、第9位互换,第13位、第14位互换。
|
另外一点需要注意的是针对utu2440,在写yaffs是不能跳过第一个好块,这一个我就不是很清楚了,为什么要跳过呢!!!???到现在也没弄明白。
但是,在做了变换修改以后,重新下载yaffs,错误依旧,通过nand dump 260000查看该页的oob,发现与用扬创自带的u-boot.bin下载后的一致,可是依旧出现上述错误,至今没有想明白问题所在。一开始以为是扬创在生成mkimage时也做了这样的变换,后来猜想可能是内核在yaffs操作oob上也被修改了,于是打开内核配置,去掉了去掉Steven Hill‘s nand_ecc.c支持这一项,并且,将uboot的变换改了回来,即不再做上述变换,成功挂载。
看来,只是内核上的oob计算被修改过了,选择让yaffs自己做ECC校验就可以了。