本文开发环境:uClinux-2.6, bf561, VDSP-4.5
1 MTD技术
MTD的全称是Memory Technology Device,用以实现对内存设备支持的统一接口,尤其是Flash,它可以提供Flash设备到字符设备驱动和块设备驱动的转换。在uClinux下包含对许多不同类型NOR Flash、NAND Flash的支持,其所有的代码均放在drivers/mtd目录下。
2 字符设备与块设备
在Linux操作系统下有两类主要的设备文件类型,一种是字符设备,另一种是块设备。字符设备和块设备的主要区别是:在对字符设备发出读/写请求时,实际的硬件I/O一般就紧接着发生了,块设备则不然,它利用一块系统内存作缓冲区,当用户进程对设备请求能满足用户的要求,就返回请求的数据,如果不能,就调用请求函数来进行实际的I/O操作。
块设备是主要针对磁盘等慢速设备设计的,以免耗费过多的CPU时间来等待。但是这种缓冲使得块设备几乎没有用,或者说非常不可靠。缓冲会重新安排写操作的次序,使得应用程序丧失了在任何时刻及时知道准确的磁盘内容的能力。这导致对磁盘数据结构(文件系统,数据库等)的可预测的和可靠的崩溃恢复成为不可能。由于写操作被延迟,内核无法向应用程序报告哪个特定的写操作遇到了写错误,这又进一步增加了一致性问题。由于这个原因,真正的应用程序从不依赖于块设备,事实上,几乎所有访问磁盘的应用程序都尽力指定总是使用字符(或“raw”)设备。
对于嵌入式系统的块设备,可选择存储文件系统的块驱动器(Block Driver)主要有三种选择。
①Blkmem driver。Blkmem driver仍是uClinux上使用最普通的Flash驱动器。它是为uClinux而设计的,但是它的结构相对比较简单,并且仅支持NOR Flash的操作,需要在RAM中建立根文件系统。同时它也很难配置,需要代码修改表来建立Flash分区。尽管如此,它还是提供了最基本的分区擦/写操作。
②MTD driver。MTD driver是Linux下标准的Flash驱动器。它支持大多数Flash存储设备,兼有功能强大的分区定义和映像工具。借用交叉存取技术(interleaving),MTD driver甚至可支持同一系统中不同类型的Flash,Linux内核中关于MTD driver配置有较为详细的选择项。
③RAM disk driver。在无盘启动的标准Linux中,用得最多的就是RAM disk driver;但它不支持底层的Flash存储器,仅对根文件系统的建立有意义,即根文件系统压缩以后存放在Flash的什么地方。
通过上面的比较可以看到,MTD driver提供对Flash最有力的支持,同时它也支持在Flash上直接运行文件系统,譬如JFFS和JFFS2,而B1kmem driver则不支持。
3 NorFlash和NandFlash
Flash是目前嵌入式系统中广泛采用的主流存储器,它的主要特点是按整体/扇区擦除和按字节编程,具有低功耗、高密度、小体积等优点。目前,Flash分为NOR, NAND两种类型。
NOR型闪存可以直接读取芯片内储存的数据,因而速度比较快,但是价格较高。NOR型芯片,地址线与数据线分开,所以NOR型芯片可以像SRAM一样连在数据线上,对NOR芯片可以“字”为基本单位操作,因此传输效率很高,应用程序可以直接在Flash内运行,不必再把代码读到系统RAM中运行。它与SRAM的最大不同在于写操作需要经过擦除和写入两个过程。
NAND型闪存芯片共用地址线与数据线,内部数据以块为单位进行存储,直接将NAND芯片做启动芯片比较难。NAND闪存是连续存储介质,适合放大文件。擦除NOR器件时是以64-128KB的块进行的,执行一个写入/擦除操作的时间为5s;擦除NAND器件是以8-32KB的块进行的,执行相同的操作最多只需要4ms。
NAND Flash的单元尺寸几乎是NOR器件的一半,由于生产过程更为简单,NAND结构可以在给定的模具尺寸内提供更高的容量,也就相应地降低了价格。NOR flash占据了容量为1―16MB闪存市场的大部分,而NAND flash则大存储容量的产品当中,这也说明NOR主要应用在代码存储介质中,NAND适合于数据存储。
寿命(耐用性),在NAND闪存中每个块的最大擦写次数是一百万次,而NOR的擦写次数是十万次。NAND存储器除了具有10比1的块擦除周期优势,典型的NAND块尺寸要比NOR器件小8倍,每个NAND存储器块在给定的时间内的删除次数要少一些。
4 MTD的层次关系
CFI接口的MTD设备基本上可分为以下几层:
一、Flash硬件驱动层:硬件驱动层负责在init时驱动Flash硬件,Linux MTD设备的NOR Flash芯片驱动遵循CFI接口标准或者JEDEC标准,其驱动程序位于drivers/mtd/chips子目录下。NAND型Flash的驱动程序则位于/drivers/mtd/nand子目录下,MTD包含特定Flash芯片的驱动程序,开发者要选择适合自己系统的Flash芯片驱动。Flash芯片驱动向上层提供读、写、擦除等基本的操作,MTD对这些操作进行封装后向用户层提供MTD char和MTD block类型的设备。
二、MTD原始设备:原始设备层有两部分组成,一部分是MTD原始设备的通用代码,另一部分是各个特定的Flash的数据,例如分区。
三、MTD设备层:基于MTD原始设备,linux系统可以定义出MTD的块设备(主设备号31)和字符设备(设备号90)。MTD char类型的设备包括/dev/mtd0, /dev/mtdl等,它们提供对Flash原始字符的访问。MTD block类型的设备包括/dev/mtdblock0,/dev/mtdblock1等,MTD block设备是将Flash模拟成块设备,这样可以在这些模拟的块设备上创建像Cramfs, JFFS2等格式的文件系统。
四、设备节点:通过mknod在/dev子目录下建立MTD字符设备节点(主设备号为90)和MTD块设备节点(主设备号为31),通过访问此设备节点即可访问MTD字符设备和块设备。
五、根文件系统:在Bootloader中将JFFS(或JFFS2)的文件系统映像jffs.image(或jffs2.img)烧到flash的某一个分区中,在/arch/arm/mach-your/arch.c文件的your_fixup函数中将该分区作为根文件系统挂载。
六、文件系统:内核启动后,通过mount 命令可以将flash中的其余分区作为文件系统挂载到mountpoint上。
5
这两个概念都是针对NorFlash的。现在的NorFlash大都支持CFI或者JEDEC这样的规范,根据这些规范可以自动检测出芯片的一些参数,所以uClinux将这些规范的驱动实现单独放在mtd/chips目录下。也就是说这个目录下放的是芯片的通用驱动代码,这些代码本身是不会主动去检测芯片的存在的,它仅仅是注册了一个驱动供其它模块调用。
在通用规范的基础上,每个不同的厂商有不同的实现,且芯片在不同的系统中可能有不同的参数,如基地址,位宽等。uClinux将这部分独立出来放在mtd/maps下。这个目录下的代码将根据芯片实现的不同规范调用相应的chips驱动。因此chips下的模块必须先于maps下的模块初始化。 chips和maps