Arm嵌入式开发之Flash文件系统建立

Flash转换层

Flash无法重复在同一块存储位置做写入操作(要擦除),硬盘上的文件系统沿用时要通过一层转换层:FTL用于NOR Flash,NFTL用于NAND Flash。但其效率不高,尽量避免使用依赖于转换层的文件系统。

Cramfs

Cramfs是一种压缩的只读文件系统,当浏览Flash中的目录或读取文件时,Cramfs文件系统会动态地计算出压缩后的数据所存储的位置,实时的解压缩到内存中,对用户来说与使用ramdisk感觉不出差异。、

通过一下命令创建Cramfs文件系统映像:(源码位于linux/fs/cramfs

Mkcramfs my_cramfs/ cramfs.img (my_cramfs为要创建映像的目录)

将映像复制到Flash的第一个分区并mount/mnt/nor

cp cramfs.img /dev/mtd1

mount –cramfs /dev/mtdblock1 /mnt/nor

 

JFFS/JFFS2

JFFS/JFFS2是管理在MTD设备上实现的日志型文件系统。

制作JFFS2文件系统的工具mkfs.jffs2(包含在mtd-utils中),执行如下命令可生成所要的映像:

./mkfs.jffs2 –d my_jffs2/ -o jffs2.img

jffs2.img复制到Flash第一个分区,挂载到linux目录

Cp jffs2.img /dev/mtd1

mount –t jffs2 /dev/mtdblock1 /mnt/nor

 

Yaffs/Yaffs2

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.9中的移植
(1)
,下载YAFFS文件系统代码,下载网址:
http://www.aleph1.co.uk/cgi-bin/viewcvs.cgi/
点击页面左下角的Download tarball即可下载全部相关代码。
(2)
,将下载的文件yaffs.tar.gz拷贝到你的一个临时文件夹中,假设是/tmp,并解压:
# cd /tmp
# tar xzvf yaffs.tar.gz
解压后得到Development文件夹,该文件夹里有两个子文件:yaffsyaffs2。考虑到现在的NAND FLASH容量越做越大,而且yaffs2可以自动选择挂载是yaffs1还是yaffs2文件系统,这里我们移植yaffs2。当然如果你的NAND FLASH只是512+16B的,可以只移植yaffs,因为即使你移植了yaffs2,它也会自动选择挂载yaffs1的。
(3)
在要移植的内核目录下建立yaffs2文件夹,并将需要的文件拷贝过来:
# cd $(linuxdir)/fs
# mkdir yaffs2

# cd yafs2
# cp /tmp/Development/yaffs2/*.c .
# cp /tmp/Development/yaffs/*.h .
# cp /tmp/Development/yaffs2/Makefile-kernel Makefile
# cp /tmp/Development/yaffs2/Kconfig .
(4)
修改$(linuxdir)/fs/yaffs2中的文件:
在开始未修改该目录.c文件前,会出现很多的built-in.o的错误,要么是提示某些函数未定义,要么是某些函数重复定义,花了我很长的时间,终于找到问题所在。部分错误提示如下:(这是我开始编译yaffs时的错误,yaffs2的错误更多,但类型差不多)
fs/built-in.o(.text+0x8478c): In function `yaffs_internal_read_super_mtd':
: undefined reference to `nandmtd_WriteChunkToNAND'
fs/built-in.o(.text+0x84790): In function `yaffs_internal_read_super_mtd':
: undefined reference to `nandmtd_ReadChunkFromNAND'
fs/built-in.o(.text+0x84794): In function `yaffs_internal_read_super_mtd':
: undefined reference to `nandmtd_EraseBlockInNAND'
fs/built-in.o(.text+0x84798): In function `yaffs_internal_read_super_mtd':
: undefined reference to `nandmtd_InitialiseNAND'
查看.c文件,我发觉有很多是通过Kconfig文件里定义的CONFIG常量来判断执行的,而这些常量在你make menuconfig/xconfig后退出后会将你的选择保存到文件中,但yaffs2目录下的有些.c 文件中引用了这些常量来判断,却并未加入引用config.h文件,从而会出错。yaffs2目录下所有引用了这些常量的.c文件中加入对 config.h的引用即可: #include
(5)
,修改$(linuxdir)/fs/Makefile Kconfig文件。
# cd $(linuxdir)/fs
# vi Makefile   (
将下面一行添加到Makefile)
    obj-$(CONFIG_YAFFS_FS) += yaffs2/
# vi Kconfig (
将下面一行添加到Kconfig)
    source "fs/yaffs2/Kconfig
(6)
在编译内核时选择:
<*> YAFFS2 file system support
   <*> 512 byte / page devices
    <*> Lets Yaffs do its own ECC
         <*> 2048 byte (or larger) / page devices
    <*> Autoselect yaffs2 format
    <*> Disable lazy loading
    <*> Turn off wide tnodes
   <*> Turn off debug chunk erase check
通过mkyaffsimage 制做出来的image OOB 中也包含它自己计算的ECC校验数据,其校验算法有可能和MTD NAND 驱动的校验算法不同,如果在内核中由MTD来处理ECC,会造成MTD 认为所有的page 都校验错误。所以,这也是我前面说最好把Lets Yaffs do its own ECC 选上的原因,同时,要把MTD NAND 驱动中的ECC 校验关闭。在$(linuxdir)/drivers/mtd/nand/your_nand.c的初始化函数中设置this-eccmode = NAND_ECC_NONE.这样做实际是使用了yaffsECC,但在读写yaffs分区时分出现提示说:
Reading data from NAND FLASH without ECC is not recommended
Writing data without ECC to NAND-FLASH is not recommended
个人认为,其实已经使用了yaffsECC,只是在传给MTD时,MTD没认可,参考mtd/nand/nand_base.c文件里的 nand_read_ecc函数以及yaffs2/yaffs_fs.c文件中在于ECC的定义。这里应该是提示没用NANDECC,而使用的是 yaffsECC。这可以通过mkyaffsimage制作一个image来验证。解决方法:要么使用nandECC,将yaffsECC屏蔽掉; 要么将nand_base.c里的相关错误信息屏蔽掉。
(7)
,修改你要移植的芯片中的Makefile,在devices后面添加mtdXmtdblockX设备,设备个数视你的nand的分区个数而定,这里我的flashyour_nand.c中分成了三个区。
\
mtd0,c,90,0   mtd1,c,90,1   mtd2,c,90,2 \
\
mtdblock0,b,31,0 mtdblock1,b,31,1 mtdblock2,b,31,2
(8)
,编译后将kernel和文件系统下载到板子上,查看结果并挂载。
# cat /proc/mtd      (
查看分区情况)
mtd0: 00400000 00004000 "EV40 flash partition 1"
mtd1: 00400000 00004000 "EV40 flash partition 2"
mtd2: 00800000 00004000 "EV40 flash partition 3"
# cat /proc/filesystems    (
查看内核支持的文件系统)
nodev    sysfs
nodev    rootfs
nodev    bdev
nodev    proc
nodev    sockfs
nodev    futexfs
nodev    pipefs
nodev    eventpollfs
          ext2
nodev    ramfs
nodev    devfs
nodev    nfs
nodev    jffs2
          romfs
          yaffs
          yaffs2
nodev    rpc_pipefs
我们发现系统已经支持yaffsyaffs2文件系统了。
# eraseall /dev/mtd0      (
在挂载之前可以先将该分区里的内容擦除掉)
# mount –t yaffs2 /dev/mtdblock0 /mnt     (
将第1个分区挂载到/mnt目录下)
yaffs: dev is 32505856 name is "mtdblock0"
yaffs: Attempting MTD mount on 31.0, "mtdblock0"
yaffs: auto selecting yaffs1
我们发现如果你的flash512+16B / page的,即使你选择的是yaffs2文件系统,内核也会自动选择挂载yaffs1文件系统。

你可能感兴趣的:(Arm嵌入式开发之Flash文件系统建立)