您的位置:首页 > 编程语言 > PHP开发

YAFFS文件系统在2.6内核上的移植

2010-03-21 14:30 381 查看
来源:http://blog.chinaunix.net/u3/93625/showart_2020160.html
一、简介
Yaffs(Yet Another Flash File System)文件系统是专门针对NAND 闪存设计的嵌入式文件系统,目前有YAFFS 和YAFFS2 两个版本,两个版本的主要区别之一在于YAFFS2 能够更好的支持大容量的NAND FLASH芯片。
Yaffs 文件系统有些类似于JFFS/JFFS2 文件系统,与之不同的是JFFS1/2 文件系统最初是针对NOR FLASH的应用场合设计的,而NOR FLASH 和NAND FLASH本质上有较大的区别,所以尽管JFFS1/2 文件系统也能应用于NAND FLASH,但由于它在内存占用和启动时间方面针对NOR 的特性做了一些取舍,所以对NAND来说通常并不是最优的方案。
 
二、yaffs/yaffs22.6.30.3中的移植
(1)下载YAFFS文件系统代码,下载网址:
http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/
点击页面左下角的Download tarball即可下载全部相关代码。
 
(2)将下载的文件cvs-root.tar.gz拷贝到你的一个临时目录中,假设是/tmp,并解压:

# cd /tmp
# tar xzvf cvs-root.tar.gz
 
解压后得到cvs目录,该目录里有两个子目录:yaffs和yaffs2。考虑到现在的NAND FLASH容量越做越大,而且yaffs2可以自动选择挂载是yaffs1还是yaffs2文件系统,这里我们移植yaffs2。当然如果你的NAND FLASH只是512+16B的,可以只移植yaffs,因为即使你移植了yaffs2,它也会自动选择挂载yaffs1的。
 
(3)为Linux打上支持yaffs2的补丁。
进入cvs/yaffs2目录,执行patch-ker.sh脚本即可。这个脚本完成把yaffs源码拷贝到linux源码目录的fs/yaffs2下和修改fs目录下的Kconfig、Makefile文件。

#./patch-ker.sh c /root/linux-2.6.30.3/
 
(4)配置内核支持YAFFS文件系统:

File systems ---> Miscellaneous filesystems --->
<*> YAFFS2 file system support
-*- 512 byte / page devices
[ ] Use older-style on-NAND data format with pageStatus byte
[ ] Lets Yaffs do its own ECC
-*- 2048 byte (or larger) / page devices
[*] Autoselect yaffs2 format
[*] Disable lazy loading
[ ] Turn off wide tnodes
[ ] Force chunk erase check
[*] Cache short names in RAM
注意:
       在这里没有选上Lets Yaffs do its own ECC选项和修改MTD驱动,也就是说不是用yaffs自身的ECC校验方法,而是使用MTD设备层中的ECC校验方法。
 
好了,到这里内核已经支持yaffs文件系统了,重新编译内核。

#./make uImage
 
三、制作yaffs文件系统映像文件
(1)修改制作yaffs映像文件的工具
    在yaffs源码中有个utils目录(假如/cvs/yaffs2/utils),里面是工具mkyaffsimage和mkyaffs2image的源代码。前者用来制作yaffs1映像文件,后者用来制作yaffs2映像文件。
       目前mkyaffsimage工具只能生成老格式的yaffs1映像文件,因为我们在配置内核时没有选上支持旧格式(没有设置CONFIG_YAFFS_9BYTE_TAGS)的yaffs1映像文件,所以需要修改源码来支持新格式。
       在修改源码之前,我们先来看看yaffs1新、老格式的不同点。他们的不同在于oob区的使用发生了变化:一是ECC校验码的位置发生了变化,二是可用空间即标记(tag)的数据结构定义发生了变化。
       另外,由于配置内核是没有设置Lets Yaffs do its own ECC,yaffs文件系统将使用MTD设备层的ECC校验方法,制作映像文件时也应该使用与MTD设备层相同的函数计算ECC码。
 
oob区中校验码的位置变化:
       oob区中使用6个字节来存放ECC校验码,前3个字节对应上半页,后3个字节对应下半页。由nand_oob_16结构可知,以前的校验码在oob区中存放的位置为8、9、10、13、14、15,而现在改为0、1、2、3、6、7。
 
‚oob区中可用空间的数据结构定义变化:
       oob区中可用的空间有8个字节,他用来存放文件系统的数据,代码中这些数据被称为标记(tag)。
 
       老格式的yaffs1中,这8个字节的数据结构定义如下(在yaffs_guts.h文件中)所示:

typedef struct {
        unsigned chunkId:20;
        unsigned serialNumber:2;
        unsigned byteCountLSB:10;
        unsigned objectId:18;
        unsigned ecc:12;
        unsigned byteCountMSB:2;
} yaffs_Tags;

      
       新格式的yaffs1中,定义如下(在yaffs_packedtags.h文件中)所示:

typedef struct {
        unsigned chunkId:20;
        unsigned serialNumber:2;
        unsigned byteCount:10;
        unsigned objectId:18;
        unsigned ecc:12;
        unsigned deleted:1;
        unsigned unusedStuff:1;
        unsigned shouldBeFF;
/* 新格式中,shouldBeFF没有使用,yaffs_PackedTags1还是8个字节 */
} yaffs_PackedTags1;

 
       新、老结构有细微差别:老结构中有两位没有使用(unusedStuff);新结构中只有一位没有使用,另一位(deleted)被用来标识当前页是否已经删除。
 
ƒoob区中ECC码的计算:
       如果配置内核时设置了Lets Yaffs do its own ECC,则yaffs文件系统将使用yaffs2/yaffs_ecc.c文件中的yaffs_ECCCalculate函数来计算ECC码;否则使用drivers/mtd/nand/nand_ecc.c文件中的nand_calculate函数。
       mkyaffsimage工具原来的代码中使用yaffs_ECCCalculate函数。由于上面配置内核时,我们没有选择Lets Yaffs do its own ECC,为了使映像文件与内核保持一致,下面我们来修改mkyaffsimage源码,使用nand_calculate_ecc函数计算ECC码。
 
1)添加头文件:
修改文件mkyaffsimage.c,加上下面这行,里面定义了yaffs_PackedTags1结构体。

#include "yaffs_packedtags1.h"

 
2)修改mkyaffsimage.c文件的write_chunk函数:
 

static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
{
/* Modify by cjy*/
#ifdef CONFIG_YAFFS_9BYTE_TAGS
/* 如果要生成老格式的yaffs1映像文件,定义这个宏 */
……/* 原来的代码 */
……
        return write(outFile,&s,sizeof(yaffs_Spare));
#else
        yaffs_PackedTags1 pt1;
        yaffs_ExtendedTags etags;
        __u8 ecc_code[6];
        __u8 oobbuf[16];

        /* 写页数据,512字节 */
        error = write(outFile,data,512);
        if(error < 0) return error; 

        /* 构造tag */
        etags.chunkId = chunkId;
        etags.serialNumber = 0;
        etags.byteCount = nBytes;
        etags.objectId = objId;
        etags.chunkDeleted = 0; 

        /*
         * 重定位oob区中的可用数据(称为tag)
         */
        yaffs_PackTags1(&pt1, &etags);

         /* 计算tag本身的ECC码 */
        yaffs_CalcTagsECC((yaffs_Tags *)&pt1);

        memset(oobbuf, 0xff, 16);
        memcpy(oobbuf+8, &pt1, 8);
 
        /*
         * 使用与内核MTD层相同的方法计算一页数据(512字节)的ECC码
         * 并把它们填入oob
         */
        nand_calculate_ecc(data, &ecc_code[0]);
        nand_calculate_ecc(data+256, &ecc_code[3]);
 
        /* 对应新格式yaffs1 ECC校验码的存放位置 */
        oobbuf[0] = ecc_code[0];
        oobbuf[1] = ecc_code[1];
        oobbuf[2] = ecc_code[2];
        oobbuf[3] = ecc_code[3];
        oobbuf[6] = ecc_code[4];
        oobbuf[7] = ecc_code[5]; 

        nPages++;

        /* 写oob数据,16字节 */
        return write(outFile, oobbuf, 16);
#endif
}

 
 

3)添加文件,修改Makefile:

#cp ../yaffs_packedtags1.c
 
把nand_ecc.c和yaffs_packedtags1.c编译进mkyaffsimage工具:

#vi Makefile
 

MKYAFFSSOURCES = mkyaffsimage.c yaffs_packedtags1.c nand_ecc.c
 
现在,在utils目录下执行make命令生成mkyaffsimage工具了。把生成的mkyaffsimage可执行文件拷贝到/usr/bin目录下。

#cp mkyaffsimage /usr/bin
 
(2)制作yaffs映像文件
把之前做好的文件系统制作为yaffs映像:

#mkyaffsimage filesystem filesystem.yaffs
 

到此,我们就可以把yaffs映像文件烧写到Nand Flash中。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息