Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16699
  • 博文数量: 4
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 50
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-10 13:57
文章分类
文章存档

2011年(1)

2009年(3)

我的朋友
最近访客

分类: 嵌入式

2009-08-07 00:03:43

一、简介

YaffsYet 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文件系统代码,下载网址:

点击页面左下角的Download tarball即可下载全部相关代码。

 

2)将下载的文件cvs-root.tar.gz拷贝到你的一个临时目录中,假设是/tmp,并解压:

# cd /tmp

# tar xzvf cvs-root.tar.gz

 

解压后得到cvs目录,该目录里有两个子目录:yaffsyaffs2。考虑到现在的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目录下的KconfigMakefile文件。

#./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),里面是工具mkyaffsimagemkyaffs2image的源代码。前者用来制作yaffs1映像文件,后者用来制作yaffs2映像文件。

       目前mkyaffsimage工具只能生成老格式的yaffs1映像文件,因为我们在配置内核时没有选上支持旧格式(没有设置CONFIG_YAFFS_9BYTE_TAGS)的yaffs1映像文件,所以需要修改源码来支持新格式。

       在修改源码之前,我们先来看看yaffs1新、老格式的不同点。他们的不同在于oob区的使用发生了变化:一是ECC校验码的位置发生了变化,二是可用空间即标记(tag)的数据结构定义发生了变化。

       另外,由于配置内核是没有设置Lets Yaffs do its own ECCyaffs文件系统将使用MTD设备层的ECC校验方法,制作映像文件时也应该使用与MTD设备层相同的函数计算ECC码。

 

oob区中校验码的位置变化:

       oob区中使用6个字节来存放ECC校验码,前3个字节对应上半页,后3个字节对应下半页。由nand_oob_16结构可知,以前的校验码在oob区中存放的位置为8910131415,而现在改为012367

 

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.cyaffs_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中。

阅读(2115) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~