#####为了方便阅读,文章末尾添加了YAFFS2的基础知识
/*YAFFS2的作用*/
简单理解,Yaffs2文件系统是Yaffs的第二版本;是专门为nand flash设计的一款文件系统。
由于RAMDISK为只读的文件系统,如果要保存用户数据就需要增加一个可写的文件系统,由于用的是NAND FLASH,所以准备选用YAFFS2。还句话说,RAMDISK是在内存建立的文件系统,掉电数据就会丢失,那么就需要建立一个能够将数据(文件、目录等)永久保存的文件系统,最好的选择就是YAFFS2,到这里,应该明白了为什么要移植YAFFS2了吧。
######前期准备
首先查看NAND FLASH分区情况 #cat /proc/mtd 看到只有两个分区,在查看当前支持的文件系统 #cat /proc/filesystems 看到里面没有支持YAFFS2。
考虑好要将Yaffs2存放在nand flash的哪个位置了吗?那就先对nand flash分区吧(我把这一步理解为划分windows下的C盘、D盘)。方法如下:
在文件board-am335xevm.c内(linux/arch/arm/mach-omap2)[根据自己的平台查找吧]
根据自己的NAND flash 实际大小分区。
/*
* NAND flash
*/
static struct mtd_partition __initdata ek_nand_partition[] = {
{
.name = "Partition 1",
.offset = 0,
.size = 4 * 1024 * 1024,
},
{
.name = "Partition 2",
.offset = 4 * 1024 * 1024,
.size = 200 * 1024 * 1024,
},
{
.name = "Partition 3",
.offset = 200 * 1024 * 1024,
.size = MTDPART_SIZ_FULL,
},
};
#####下载Yaffs2源代码
操作(下载到PC机上):#git clone git://www.aleph1.co.uk/yaffs2
#####为内核打上yaffs2补丁
如果内核fs目录内已经存在yaffs2文件夹,将其删掉,并进入Kconfig文件内,删掉source "fs/yaffs2/Kconfig",不然会报错。
然后进入 yaffs2 源代码目录执行:
#cd yaffs2
#./patch-ker.sh c m /opt/FriendlyARM/mini2440/linux-2.6.32.2
如图,yaffs2 补丁已经成功打上。
此时进入 内核/fs 目录,可以看到已经多了一个 yaffs2 目录。
#####配置和编译带 YAFFS2 支持的内核
在 Linux 内核源代码根目录运行:make menuconfig,移动上下按键找到 File Systems,再找到“Miscellaneous filesystems”菜单项,按回车进入该子菜单
找到“YAFFS2 file system support”,并按空格选中它,这样我们就在内核中添加了 yaffs2 文件系统的支持,按“Exit”退出内核配置。
#####编译内核
操作:make zImage
拷贝下载到开发板(这步都不懂的,步骤见http://blog.csdn.net/taiyi2012/article/details/18304585)
#####挂载文件系统
进入内核后,执行以下命令:
root@linux#mount -t yaffs2 /dev/mtdblock2 /tmp
挂载成功显示如下信息:
yaffs: dev is 32505858 name is "mtdblock2"
yaffs: passed flags ""
yaffs: Attempting MTD mount on 31.2, "mtdblock2"
yaffs: restored from checkpoint
# cd tmp
可以创建文件和目录
重新启动,不放心可以掉电再来,重新挂载后即可看到刚才新建的文件。
#####卸载文件系统
# umount tmp
卸载成功显示
save exit: isCheckpointed 1
/******YAFFS2基础知识**********/
Yaffs文件系统有些类似于JFFS/JFFS2文件系统,与之不同的是JFFS1/2文件系统最初是针对NOR FLASH的应用场合设计的,而NOR FLASH和NAND FLASH本质上有较大的区别,所以尽管JFFS1/2 文件系统也能应用于NAND FLASH,但由于它在内存占用和启动时间方面针对NOR的特性做了一些取舍,所以对NAND来说通常并不是最优的方案。
与NOR相比,NAND不是完全可靠的,每块芯片出厂时都有一定比例的坏块存在,对数据的存取不是使用地址映射而是通过寄存器的操作,串行存取数据。
前面说到对于NAND FLASH上的每一页数据,都有额外的空间用来存储附加信息,通常NAND驱动只使用了这些空间的一部分,Yaffs正是利用了这部分空间中剩余的部分来存储文件系统相关的内容。以512+16B为一个PAGE的NAND FLASH芯片为例,Yaffs文件系统数据的存储布局如下所示:
0..511
|
数据区域
|
512..515
|
YAFFS TAG
|
516
|
Data status byte
|
517
|
Block status byte 坏块标志位
|
518..519
|
YAFFS TAG
|
520..522
|
后256字节数据的ECC校验结果
|
523..524
|
YAFFS TAG
|
525..527
|
前256字节数据的ECC校验结果
|
Bits
|
Content
|
20
|
ChunkID,该page在一个文件内的索引号,所以文件大小被限制在2^20 PAGE 即512Mb
|
2
|
2 bits serial number
|
10
|
ByteCount 该page内的有效字节数
|
18
|
ObjectID 对象ID号,用来唯一标示一个文件
|
12
|
Ecc, Yaffs_Tags本身的ECC校验和
|
2
|
Unused
|
ObjectID号为18bit,所以文件的总数限制在256K即26万个左右。
最后以上这些是针对Yaffs1而言,对于Yaffs2因为针对chunk size大于1k的NAND FLASH,在Tags各分量及总体尺寸上都做了修改,以便更快更好的处理大容量的NAND FLASH芯片。由于Tag尺寸的增大,在512+16B类型的NAND FLASH上就一个Trunk对应一个page的情况,目前就无法使用Yaffs2文件系统了。
由于文件系统的基本组织信息保存在页面的备份空间中,因此,在文件系统加载时只需要扫描各个页面的备份空间,即可建立起整个文件系统的结构,而不需要像JFFS1/2 那样扫描整个介质,从而大大加快了文件系统的加载速度。
1.3 yaffs文件系统在内存中的组织方式
通常一个具体的文件系统在VFS的Super_block结构中除了通用的数据外,还有自己专用的数据,Yaffs文件系统的专用数据是一个yaffs_DeviceStruct结构,主要用来存储一些相关软硬件配置信息,相关函数指针和统计信息等。
在yaffs_object结构中,主要包含了:
Ø 如修改时间,用户ID,组ID等文件属性;
Ø 用作yaffs文件系统维护用的各种标记位如脏(dirty)标记,删除标记等等;
Ø 用作组织结构的,如指向父目录的Parent指针,指向同级目录中其他对象链表的siblings双向链表头结构
此外根据Object类型的不同(目录,文件,链接),对应于某一具体类型的Object,在Yaffs_object中还有其各自专有的数据内容
Ø 普通文件:文件尺寸,用于快速查找文件数据块的yaffs_Tnode 树的指针等
Ø 目录:目录项内容双向链表头(children)
Ø 链接:softlink的alias,hardlink对应的ObjectID
通过创建这些yaffs_object,yaffs文件系统就能够将存储在NAND FLASH上数据系统的组织起来,在内存中维护一个完整的文件系统结构。
Ø 参考yaffs代码中的Kconfig文件,按照2.4内核的风格修改你自己的Config.in文件,使得可以配置YAFFS。
Ø 修改fs/makefile,加入yaffs目录
Ø 按照2.4内核的风格修改YAFFS目录中的Makefile文件。
此外就是最好把Lets Yaffs do its own ECC选上,理由后面会说,其他选项就无所谓了,主要是对性能的调整,看着选吧,按推荐配置好了,比如Turn off debug chunk erase check,这一项,我试验的结果选上后平均可以提高20-30%左右的擦写速度。
运行mkyaffsimage dir imagename可以制作出yaffs1文件系统的镜像。
但是,需要注意的是,制作出来的yaffs image文件与通常的文件系统的image文件不同,因为在image文件里除了以512字节为单位的一个page的data数据外,同时紧跟在后还包括了16字节为单位的NAND备份数据区(OOB)的数据。所以实际上是以528个字节为单位的。就是因为包含了这额外的16字节/page的数据,所以基本上常规办法如dd,或者通常的下载其它类型image的工具就无法正常下载yaffs image了,需要修改你所使用的下载工具的代码,使得它能将yaffs image中的这些额外数据也写入NAND FLASH OOB中。
这里还有一点需要注意的是,通过mkyaffsimage制做出来的image其OOB中也包含它自己计算的ECC校验数据,其校验算法有可能和MTD NAND驱动的校验算法不同,如果在内核中由MTD来处理ECC,会造成MTD认为所有的page都校验错误。所以,这也是我前面说最好把Lets Yaffs do its own ECC选上的原因,同时,要把MTD NAND驱动中的ECC校验关闭。
Ø 没有合适的page size的NAND FLASH芯片,比如板上NAND FLASH芯片为512+16的格式,但是想要试验Yaffs2文件系统。
Yaffs提供了两种用来在这种情况下测试yaffs文件系统的途径。
稍微修改一下Makeflie将编译出来的模块插入内核,将在/dev/mtd /dev/mtdblock目录下创建一个新的MTD设备。然后就可以将该设备当作一个物理的MTD NAND设备分区进行相关的操作,可以在上面创建yaffs文件系统,mount umount等等。这种方法不仅适用于yaffs文件系统,同样也适用于其它可用于NAND设备的文件系统。
2.2.3.2 Yaffsram
根据yaffs 官方文档的描述,通过mount –t yaffsram none /mountpoint 可以在内存中建立一个yaffs分区,这有些类似于ramfs。不过,在试验最新版本的Yaffs2文件系统时,该功能并不可用,只有Yaffs1文件系统的代码包里包含了相关的代码。