当前位置:首页 >> 信息与通信 >>

NAND+Flash文件系统—YAFFS2在Linux下的实现


http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现

超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现
龙亚春 黄 璞 吴 胜 (北京邮电大学无线网络实验室 100876)


*

要:通

过一个具体应用实例,阐述了如何在嵌入式平台(OMAP5910+嵌入式 Linux-2.4.21)中创建基于超大容量

NAND Flash 的 YAFFS2 文件系统软硬件实现方法。 关键字:嵌入式 Linux NAND Flash YAFFS2 MTD OMAP

1.NAND Flash 简介
NAND Flash 是当今市场上最主要的非易失大容量闪存。1989 年,东芝公司发布了 NAND Flash 结构,强调降低 每比特的成本及更高的性能,并且像磁盘一样可以通过接口轻松升级。NAND 结构能提供极高的存储密度和容量(目 前单片最大容量可达 32G 位) ,并且写入和擦除的速度也很快。NAND Flash 由于其具有非易失性、电可擦除性、可重 复编程以及高密度、低功耗等特点,而被广泛应用于 U 盘,MP3 和数码相机等嵌入式数字存储设备当中。 采用Flash介质时一个需要重点考虑的问题是可靠性,包括寿命、位交换和坏块处理三个方面。NAND Flash在每个 页面(page)中提供了足够的用于存储校验码的辅助存储区(Spare Area) ,对于主存储区(Main Area)长度为512字 节的小页面 (Small Page) 其辅助存储区大小为16字节; , 对于主存储区 (Main Area) 为2048字节的大页面 (Large Page) , 其辅助存储区大小为64字节。辅助存储区可用来存放ECC(Error Checking & Correction)、ECC有效标志、坏块标志等。 所有这些决定了基于NAND 的存储系统设计需要处理不同于其它类型闪存的特有问题。

2.MTD 简介
MTD是Memory Technology Device的缩写,它是底层硬件和上层软件之间的桥梁。对底层来说,它无论对NOR型 或是NAND型都有很好的驱动支持;对上层来说,它抽象出文件系统所需要的接口函数。图1显示了文件系统,MTD 和NAND Flash的层次关系和调用关系。

图 1 文件系统、MTD 和 NAND Flash 的层次关系 * 基金项目:北京市自然科学基金项目(4052021) 1 1

http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现 图中NAND特定硬件驱动层为具体NAND设备 一个MTD设备按照用户访问的顺序可以得到图2所示的层次结构[3]。 的驱动,实现特定硬件的具体操作;NAND通用驱动层是所有NAND设备的公用部分,实现了NAND设备发现、通用 NAND读写等操作;MTD原始设备层是MTD原始设备的通用代码,此外还包括各个特定的闪存设备所注册的数据,例 如NAND分区等。MTD向上提供块设备和字符设备两种接口。文件系统通过MTD块设备接口访问NAND闪存驱动。

图2

MTD模块的层次结构

具体的NAND闪存驱动是和NAND通用驱动相关联的,要实现一个NAND闪存硬件驱动,需要实现以下部分:初 始化函数,硬件相关的设备就绪函数和控制函数。为了灵活起见,还可以实现硬件相关的命令函数、硬件相关的等待 函数和硬件ECC函数。 在编程上, MTD 为上层提供了一系列的接口, 可以使上层程序不关心底层的硬件细节, 而通过这些函数直接访问。 这些接口包括:erase,read,write,read_ecc,write_ecc,read_oob,write_oob,sync,lock,unlock,suspend,resume, block_isbad,block_markbad 等函数。通过这些抽象出的接口,文件系统就可以方便的对 Flash 进行各种操作了。

3.YAFFS2 文件系统简介
YAFFS(Yet Another Flash File System)文件系统是一个开源的,专门为NAND Flash设计的文件系统,也是一种 日志型文件系统,具有很好的可移植性,能够在Linux,μCLinux,和Windows CE下面运行。 YAFFS 目前有 YAFFS 和 YAFFS2 两个版本,一般说来,YAFFS 对小页面(528 字节/页)有很好的支持,而更大 的页面(2K+64 字节/页)就需要 YAFFS2 了。超大容量(总容量超过 512M 字节)的 NAND Flash 一般都采用大页面。 YAFFS 对文件系统上的所有内容(比如正常文件,目录,链接,设备文件等等)都统一当作文件来处理,每个文 件都有一个页面专门存放文件头,文件头保存了文件的模式、所有者 ID、组 ID、长度、文件名、Parent Object ID 等 信息。因为需要在一页内放下这些内容,所以对文件名的长度,符号链接对象的路径名等长度都有限制。 前面说到对于 NAND FLASH 上的每一页数据,都有 Spare Area 用来存储附加信息,通常 NAND 驱动只使用了这 些空间的一部分,YAFFS 正是利用了这部分空间中剩余的部分来存储文件系统相关的内容。以 512+16B 为一页的 NAND Flash 为例,YAFFS 文件系统数据的存储结构如表 1 所示: 表1 字节序号 0..511 512..515 516 517 518..519 520..522 Small Page 的存储结构 内 容

数据区域(文件数据或文件头) YAFFS TAG 数据状态字节(坏块标志位) 数据状态字节 YAFFS TAG 后 256 字节数据的 ECC 校验结果 2 2

http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现 523..524 525..527 顺序如表 2 所示。 表2 位数 20 YAFFS 的 TAGs 分配表 内 容 YAFFS TAG 前 256 字节数据的 ECC 校验结果

这里 YAFFS 一共使用了 8 个字节用来存放文件系统相关的信息(YAFFS Tags)。这 8 个字节的具体使用情况按

ChunkID,该 page 在一个文件内的索引号,所以文件大 小被限制在 2^20 PAGE 即 512Mb 2 位的序列号 ByteCount 该 page 内的有效字节数 ObjectID,文件 ID 号,用来唯一标示一个文件 Ecc, Yaffs_Tags 本身的 ECC 校验和 Unused,保持为 1

2 10 18 12 2

YAFFS2 的辅助存储区的数据结构与 YAFFS 的略有不同,比如 YAFFS2 的辅助存储区中增加了块序号;一个 YAFFS2 的辅助存储区(64 字节)包括 4 个类似 YAFFS 的辅助存储区(16 字节) 。 下面介绍一下文件系统是如何运作起来的。 操作文件系统的第一步是取得 SuperBlock, YAFFS 文件系统本身在 NAND Flash 上并不存在所谓的 SuperBlock 块, 完全是在文件系统 mount 的过程中由 read_super 函数填充的,不过有意思的一点是,由于物理上没有存储 SuperBlock 块,所以 NAND Flash 上的 YAFFS 文件系统本身没有存储 filesystem 的魔数(MagicNum) ,在内存中 SuperBlock 里的 s_magic 参数也是直接赋值的, 所以存储在 NAND FLASH 上的任何文件系统都能被当作 YAFFS 文件系统 mount 上来, 只是数据都会被当作错误数据放在 lost+found 目录中。 通常一个具体的文件系统在 VFS 的 Super_block 结构中除了通用的数据外,还有自己专用的数据,YAFFS 文件系 统的专用数据是一个 yaffs_DeviceStruct 结构,主要用来存储一些相关软硬件配置信息,相关函数指针和统计信息等。 在 mount 过程执行 read_super 的过程中,Yaffs 文件系统还需要将文件系统的目录结构在内存中建立起来。由于没 有 super 块,所以需要扫描 YAFFS 分区,根据从 OOB(Out of Band)中读取出的 yaffs_tags 信息判断出是文件头 page 还是数据 page。再根据文件头 page 中的内容以及数据 page 中的 ObjectID、ChunkID、serial Number 等信息在内存中 为每个文件(Object)建立一个对应的 yaffs_object 对象。 在 yaffs_object 结构中,主要包含了: 修改时间,用户 ID,组 ID 等文件属性; 用作 yaffs 文件系统维护用的各种标记位如脏(dirty)标记,删除标记等; 用作组织结构的,如指向父目录的 Parent 指针,指向同级目录中其他对象链表的 siblings 双向链表头结构。 此外根据 Object 类型的不同(目录,文件,链接) ,对应于某一具体类型的 Object,在 Yaffs_object 中还有其各自 专有的数据内容。 普通文件:文件尺寸,用于快速查找文件数据块的 yaffs_Tnode 树的指针等; 目录:目录项内容双向链表头(children); 链接:softlink 的 alias,hardlink 对应的 ObjectID。 除了对应于存储在 NAND FLASH 上的 object 而建立起来的 yaffs_object 以外,在 read_super 执行过程中还会建立 一些虚拟对象(Fake Object) ,这些 Fake Object 在 NAND FLASH 上没有对应的物理实体,比如在建立文件目录结构 的最初,YAFFS 会建立四个虚拟目录(Fake Directory) :rootDir, unlinkedDir, deleteDir, lostNfoundDir 分别用作根目录, unlinked 对象挂接的目录,delete 对象挂接的目录,无效或零时数据块挂接的目录。 通过创建这些 yaffs_object,YAFFS 文件系统就能够将存储在 NAND FLASH 上数据系统的组织起来,在内存中维 护一个完整的文件系统结构。 YAFFS 和 YAFFS2 文件系统的源代码可以从 http://www.aleph1.co.uk/armlinux/projects/下载。 YAFFS 代码包括以下 文件:yaffs_ecc.c(ECC 校验算法) ,yaffs_fileem.c(测试 flash) ,yaffs_fs.c(文件系统接口函数) ,yaffs_guts.c(Yaffs 文件系统算法) ,yaffs_mtdif.c(NAND 函数) ,yaffs_ramem.c(Ramdisk 实现) 。 3 3

http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现

4.应用实例
下面通过具体实例,介绍如何在嵌入式平台(OMAP5910+嵌入式 Linux-2.4.21)中创建基于 NAND Flash(三星公 司的 K9F4G08U0M)的 YAFFS2 文件系统的软硬件实现方法。关于 OMAP5910 的详细资料可以查看其数据手册[2], 关于 NAND FLASH 的详细资料[1]可以查看其数据手册或参考文献[5]。

4.1 硬件接口电路
NAND Flash 属于慢速设备,它可以通过 OMAP 的 GPIO 口或 EMIFS 接口与控制器相连。这里采用 EMIFS 接口 的方式, 且以其 CS3#作为 NAND Flash 的片选信号, 则其首地址为 0x0C00 0000, 空间大小则完全取决于所选用的 Flash 型号,而不受 EMIFS 的 CS3#的地址空间大小限制。为实现接口间的时序匹配,必须合理设置 EMIFS 的 CS3#的读写 时钟周期长度。具体的电路连接如图 2 所示。

图 2 硬件连接图 按图 2 所示,可以算出 NAND Flash 的数据读写地址为 0x0C00 0000,命令输入地址为 0x0C00 0002,地址输入地 址为 0x0C00 0004,并给出如下宏定义。其中 Flash 端的 WP#信号也可直接上拉,为保持电平稳定,R/B#信号最好上 拉。

4.2 文件系统创建流程
第一步:给内核打补丁,更新 MTD
对于系统内核是 Linux-2.4.21 或以前版本,虽然这个版本的源代码里已有了 MTD 的支持,不过老版本的 MTD 驱 动对 NAND FLASH 的支持并不是很好,而且支持的最大页面不超过 512 字节。因此创建的第一步是更新 MTD 驱动。 首先从 MTD 官方网站下载最新的 cvs,这里用得是 mtd-snapshot20050519。解压这个 snapshot,然后打补丁。更新完 MTD 后,新的 Linux 系统内核就可以支持 2K/页的 NAND FLASH 了。 对于内核版本为 2.6 以后的,可以略过此步骤。

第二步:定义与硬件相关的驱动程序
为了在 Linux 中加入对特定开发板上 NAND FLASH (如 K9F4G08U0M) 的支持, 需要根据特定的硬件书写 NAND Flash 的驱动程序,并修改 MTD 的 Makefile,把这个驱动编译进 MTD 子系统。

编写 NAND 驱动
在 drivers/mtd/nand/新建一个文件,为 ti5910.c。 首先,定义 FLASH 的设备的分区结构,这里把这块 512M 的 FLASH 分为五个区。 const static struct mtd_partition ti5910_partitions[] = { { name: size: offset: { name: size: "bootloader", 0x00060000, 0x00000000, }, "Params", 0x00040000, //128k for kernel parameters 4 4 //384k for bootloader

http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现 offset: { name: size: offset: { name: size: offset: { name: size: offset: }; 然后,定义相关控制引脚: static void ti5910_hwcontrol(struct mtd_info *mtd, int cmd) { struct nand_chip *chip = mtd->priv; switch (cmd) { case NAND_CTL_SETNCE: break; case NAND_CTL_CLRNCE: break; case NAND_CTL_SETCLE: /*latch cmd cycle*/ break; /*release this chip*/ /*select this chip*/ 0x00060000, }, "Kernel", 0x00500000, 0x000a0000, }, "root", 0x00a00000, 0x00aa0000, }, "user space", 0x1eb40000, 0x014a0000, } // 491.25M for user space //10M for root filesystem //5M for Kernel

chip->IO_ADDR_W += 0x00000002; case NAND_CTL_CLRCLE:

/*release cmd cycle*/ break;

chip->IO_ADDR_W -= 0x00000002; case NAND_CTL_SETALE:

/*latch addr cycle*/ break;

chip->IO_ADDR_W += 0x00000004; case NAND_CTL_CLRALE:

/*release addr cycle*/ break;

chip->IO_ADDR_W -= 0x00000004; } } 再后,定义初始化函数,如下所示: int __init ti5910_nand_init (void) { struct nand_chip *this; u_int16_t nfconf; unsigned int result=0;

/* Allocate memory for MTD device structure and private data */ ti5910_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct nand_chip), GFP_KERNEL); …… this = (struct nand_chip *) (&ti5910_mtd[1]); /* Get pointer to private data */ memset((char *) ti5910_mtd, 0, sizeof(struct mtd_info)); /* Initialize structures */ memset((char *) this, 0, sizeof(struct nand_chip)); ti5910_mtd->priv = this; /* Link the private data with the MTD structure */ /* Set address of NAND IO lines */ this->IO_ADDR_R = ioremap(0x0c000000, SZ_1K);;

this->IO_ADDR_W = ioremap(0x0c000000, SZ_1K); this->hwcontrol this->eccmode = ti5910_hwcontrol; = NAND_ECC_NONE; 5 5

http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现 …… /* Allocate memory for internal data buffer */ this->data_buf = kmalloc(sizeof(u_char) * (ti5910_mtd->oobblock + ti5910_mtd->oobsize), GFP_KERNEL); if (!this->data_buf) { printk ("Unable to allocate NAND data buffer for ti5910.\n"); this->data_buf = NULL; return -ENOMEM; } } 最后,添加分区: result= add_mtd_partitions(ti5910_mtd,ti5910_partitions, sizeof(ti5910_partitions)/sizeof(ti5910_partitions[0]));

把驱动加入 MTD 子系统
修改 drivers/mtd/nand/Makefile.common,在里面增加 obj-$(CONFIG_MTD_NAND_TI5910) +=ti5910.o 修改同一目录下的 Config.in 文件,找到 if [ "$CONFIG_ARM" = "y" ]; then dep_tristate ' NAND Flash device on SPIA board' CONFIG_MTD_NAND_SPIA $CONFIG_MTD_NAND $CONFIG_ARCH_P720T 在其后里面加入 dep_tristate ' NAND Flash device on OMAP board' CONFIG_MTD_NAND_TI5910 $CONFIG_MTD_NAND 最后重新配置内核,运行 make menuconfig,选择 MTD 支持,块设备,字符设备支持,NAND Flash 支持,NAND Flash device on OMAP board 支持。 这样编译好的内核就能通过 MTD 驱动 NAND Flash 了。

第三步:修改内核的文件系统,增加对 YAFFS2 的支持
首先下载最新的 YAFFS2 代码,解压。在 Linux 目录的 fs 目录下创建 YAFFS2 目录。把下载下来的 YAFFS2 源 文件都拷贝到这个目录下。 修改 fs/Config.in 脚本,加入这么几行: if [ "$CONFIG_MTD_NAND" = "y" ]; then

tristate "Yaffs2 filesystem on NAND" CONFIG_YAFFS2_FS fi dep_bool "yaffs2" CONFIG_YAFFS_YAFFS2 修改 fs/Makefile,加入对 yaffs2 的支持。加入如下一行: subdir-$(CONFIG_YAFFS2_FS) += yaffs2 再重新配置内核,进入在文件系统模块的选择界面,选中“Yaffs2 file system on NAND”、“Yaffs2”、“2048 byte (or larger)/page devices”选项。 重新编译内核,编译成功后,新内核就支持 YAFFS2 文件系统了。

第四步:测试新的文件系统
1)系统内核启动之后,启动信息中应该含有如下内容: NAND device: Manufacturer ID: 0xec, Chip ID: 0xdc (Samsung NAND 512MiB 3,3V 8-bit) Scanning device for bad blocks Creating 5 MTD partitions on "NAND 512MB 3,3V 8-bit": 0x00000000-0x00060000 : "bootloader" 0x00060000-0x000a0000 : "Params" 0x000a0000-0x005a0000 : "Kernel" 0x00aa0000-0x014a0000 : "root" 0x014a0000-0x1ffe0000 : "user space" this is the result of add_mtd_partitions 0 2)如果在内核里面添加了proc文件系统的支持,那么proc中应该包含有关YAFFS的信息。 6 6

http://www.paper.edu.cn 超大容量 NAND Flash 文件系统—YAFFS2 在 Linux 下的实现 /proc # ls -l y* -r--r--r-- 1 0 0 0 Jan 1 00:54 yaffs 3)dev目录下的相关目录中包括有关NAND设备的信息,如下所示: /dev # ls -l mtd* crw-rw-rw- 1 0 0 90, 8 Jan 1 00:00 mtd4 crw-rw-rw- 1 0 0 31, 1 Jan 1 00:00 mtdblock1 brw-rw-rw- 1 0 0 31, 4 Jan 1 00:00 mtdblock4 4)建立mount目录:#mkdir /mnt/flash mount MTD block设备:#mount -t yaffs /dev/mtdblock4 /mnt/flash #cp test.txt /mnt/flash 将文件拷贝到mount上的目录下后,umount设备,再次mount后可以发现拷贝的文件仍然存在。这时删除该文件, 然后umount,再次mount后可以发现拷贝的文件已经被删除,由此可见该分区可以正常读写。文件系统移植成功。

5.结束语
本文主要阐述了基于超大容量NAND FLASH的软硬件设计并介绍了YAFFS2文件系统在LINUX系统的创建和移植工作。 现在,每页大小为2K字节的新型超大容量NAND FLASH已经出现,针对这种Flash的文件系统YAFFS2也正处于深入研究 和广泛应用当中。希望笔者的经验之谈能对准备进行超大容量NAND FLASH开发的同仁有所帮助。

参考文献:
1. Samsung. K9F4G08U0M flash memory datasheet (rev. 1.0) http://www.sumsung.com, 2005 《计算机工程》 2006 年第 2 期 《电子技术应用》2006 年第 1 期 2. OMAP5910 Dual-Core Processor Data Manual (SPRS197C) http://www.ti.com, 2003 3. 嵌入式 Linux 下 NAND 存储系统的设计与实现(胡勇其,侯紫峰) 4. YAFFS 文件系统在嵌入式 Linux 上的实现(毛勇强,黄光明)

5. NAND型Flash在大容量存储回放系统中的应用(谢明,高梅国,王超) 《电子技术应用》2006年第4期

作者简介:
龙亚春(1976- ) ,男,北京邮电大学无线网络实验室在读硕士,研究方向:无线通信设备的嵌入式开发。 黄 吴 璞(1982- ) ,男,北京邮电大学无线网络实验室在读硕士,研究方向:无线通信设备的嵌入式开发。 胜(1982- ) ,男,北京邮电大学无线网络实验室在读硕士,研究方向:无线通信设备的嵌入式开发。

Create a YAFFS2 bases on Super-Large NAND Flash in Linux
Long Yachun, Huang Pu, Wu Sheng (Wireless Network Lab., Beijing University of Posts and Telecom., 100876) Abstract: This paper introduces a practical method about how to create a YAFFS2 bases on Super-Large NAND Flash in an embedded platform which includes OMAP dual-core processor and embedded Linux operation system. Key Words: Embedded Linux; NAND Flash; YAFFS2; MTD; OMAP

作者简介:
龙亚春(1976- ),男,北京邮电大学无线网络实验室在读硕士,研究方向:无线通信设备的嵌入式开发。 黄璞(1982- ),男,北京邮电大学无线网络实验室在读硕士,研究方向:无线通信设备的嵌入式开发。 吴胜(1982- ),男,北京邮电大学无线网络实验室在读硕士,研究方向:无线通信设备的嵌入式开发。

7 7


相关文章:
几种Nand flash文件系统的对比
几种Nand flash文件系统的对比_信息与通信_工程科技_专业资料。NAND FLASH ...Although YAFFS2 is designed to support NAND flash memory, it has ...
深入理解yaffs2文件系统(一)
1.2Yaffs 文件系统特性 YAFFS 是一个专为 NandFlash 特性设计的文件系统。...(2)Easily ported – 易于移植, 已经移植到 GNU/Linux, WinCE,eCOS,pSOS, ...
U-boot2009.08支持YAFFS2
头文件部分可以去掉 5.1,添加 Yaffs2 镜像烧写功能 由于现在很多使用 Nand Flash 的系统,在 Linux 下都用 Yaffs2 作为存储数据 的文件系统,甚至是根文件系统...
详细分析Linux文件系统格式优劣
yaffs2文件系统的制作 9页 免费 LINUX_MTD 44页 1下载linux-mtd-nand驱动...例如/tmp 和/var 目录,这样既 避免了对 Flash 存储器的读写损耗,也提高了...
Linux文件系统制作详细_图文
Linux 文件系统制作流程关键词:ARM 关键词:ARM Linux yaffs 文件系统 移植 ...闪存主要有 NOR 和 NAND 两种技术(简单比较见附录)。Flash 存储器的擦写 次数...
嵌入式YAFFS文件系统在nand-flash设备上的分析与移植《...
嵌入式YAFFS文件系统在nand-flash设备上的分析与移植《开题报告》_专业资料。北京...平台是 ARM-S3C2440 内核的 QQ2440V3 开发板;Linux 操作 系统采用 2.6 以后...
2-7-基于Linux2.6的YAFFS文件系统移植
基于Linux2.6 的 YAFFS 文件系统移植一、YAFFS 文件系统简介 YAFFS,Yet Another...NAND Flash 大多采用 MTD+YAFFS 的模式。MTD( Memory Technology Devices,内存...
YAFFS文件系统在嵌入式Linux上的实现(ok)
YAFFS 文件系统在嵌入式 Linux的实现引言 随着嵌入式技术在各种电子产品中的...Flash 主要有 NOR 和 NAND 两种类型。目前,针对 NOR Flash 设计的文件系统 ...
nandFlash编程内幕
linux -2.6.32.2 ②配置内核以支持 Yaffs2 文件系统 在 Linux 内核源代码...表 1 128 MB Nand Flash 的分区结构图 其部分实现代码如下: static struct ...
linux nandflash 驱动说明
linux nandflash 驱动说明_计算机软件及应用_IT/计算机...yaffs2" 第一行, driver/mtd/nand/s3c2410.c 中...层来作为具体的硬件设备驱动和上层文件系统的桥 梁...
更多相关标签:
nand flash 文件系统 | nandflash的文件系统 | nand write.yaffs | yaffs2文件系统制作 | yaffs文件系统 | yaffs2文件系统 | yaffs文件系统制作 | yaffs2文件系统原理 |