嵌入式系统对执行速度和系统可靠性的要求,决定了嵌入式系统需要一种安全、快速的存储设备,这种设备备同时还需要体积小、容量大、掉电数据不丢失等特点。而Flash存储器恰恰能够满足上述要求。这也使得Flash存储器成为嵌入式系统中的主要存储设备。
现在,Flash技术已经成熟,并已成为工业标准 但问题是如何能够更加有效的管理Flash设备.提高Flash的使用效率.加快操作速度和管理Flash各单元的使用频率从而提高Flash的使用寿命。因此,人们逐渐把注意力转移到Flash的管理软件上。M-system公司的True Flash File System (TrueFFS)就是在此背景下推出的Flash管理软件,它的基本功能是完成Flash的磁盘模拟功能,使人们能像操作磁盘一样来操作Flash 而TrueFFS则提供了一个标准的块设接口,能够对扇区进行读写操作。这样的功能已经足够让文件系统和操作系统管理Flash了 因此.True Flash也为不少嵌入式操作系统所采用.包括风河公司的VxWorks在内。正因如此,对Flash进行TrueFFS的驱动开发,已经成为嵌入式系统开发人员必做的工作之一。但是因为TrueFFS驱动的开发与硬件联系紧密,开发过程也有着不小的难度,而现在对TrueFFS文件系统的层次结构及原理介绍等相关资料很多.而对驱动的具体开发过程却介绍很少,所以,本文旨在对TrueFFS原理进行分析的基础上,以三星公司的Nand Flash K9F2808UOB为例,着重介绍在VxWorks操作系统上开发TrueFFS驱动的具体过程。
TrueFFS简介
TrueFFS能给操作系统提供完整的块设备功能.这使Flash能像一个标准磁盘设备一样由操作系统和文件系统所管理。同时,它还提供有透明的Flash介质管理,井具有提高Flash使用寿命(损耗均衡算法),确保数据完整(安全算法.坏数据映射),优化Flash性能(碎片回收)等优点 其结构如图1所示。
图1 TrueFFS基本结构图
由图中可以看出,TrueFFS主要由三个模块组成,分别为块设备API(驱动层)、块设备模拟+Flash管理层以及MTD层。
处在最顶端的是驱动层,其功能是为操作系统的文件系统提供块设备服务,此层的代码决定于不同的操作系统。
位于中间的模块是整个TrueFFS的核心部分,它包括块设备模拟算法和Flash管理算法(通常被称为翻译层,Translation Layer或TL)。该模块的职责是将文件系统的扇区翻译为Flash的物理块。在进行地址翻译的同时,它还可同时进行损耗均衡处理,坏数据块映射和其它相关操作(如碎片回收等)。
处于最底端的模块是MTD(Memory Technology Driver)层。它提供有对Flash进行基本的读/写/擦除的接口。本层的操作是由Flash管理层(Flash Management Layer)控制的。
TORNADO中的TrueFFS
Tornado中的TrueFFS是WindRiver Tornado开发环境下集成的Flash文件管理系统。它能通过VxWorks中的DOS文件系统对Flash进行文件管理操作。并能通过标准文件系统接口创建并控制一个文件系统。这使得用户在Flash上进行文件的读写就和直接在DOS文件系统设备上一样简单。
TrueFFS在VxWorks中的位置如图2所示。
图2 TrueFFS在VxWorks中的位置
由于Tornado为TureFFS提供了一个驱动层接口,因此,在VxWorks下可使用DOS文件系统或NFS(网络文件系统)。对于嵌入式应用程序来说,它们只需要简单的调用相关的文件系统接口函数即可。
Tornado中的TrueFFS层次结构和功能与前述的TrueFFS 基本层次结及功能一致。对于驱动层(或核心层)及翻译层代码,风河公司以二进制的形式提供。也就是说.驱动层及翻译层功能的完成已经不需要驱动开发人员所关心。因此,对Flash设备的TrueFFS驱动开发的重点就放在MTD层的开发,下面就以三星公司的Nand Flash K9F2808UOB为例, 来介绍VxWorks操作系统下Flash的TrueFFS驱动开发过程。
VxWorks下TrueFFS的驱动开发
VxWorks下的TrueFFS驱动开发主要面向MTD层。从图1可以看出,MTD层主要用于实现Flash器件的识别、读、写、擦除功能 而这一部分工作和具体的Flash存储器以及存储器和系统地连接有关。也就是说,选择不同的Flash器件,Flash芯片的连接方式将有所不同,实现MTD层的代码文件也都将不同。Tornado提供了几种Flash的TrueFFS MTD层驱动方案:它们处在installDir\target\src\drv\tffs中(installDir是Tornado的安装目录).其中包括Intel、AMD等公司的几种Flash的TrueFFS MTD层驱动。这样,如果开发者选用了这几种Flash芯片,就只须将相关代码文件复制到BSP所在的目录下,并在MakeFile文件MACH_EXTRA一项中添加相对应的目标代码就可以了。但是在很多情况下,开发者所选用的Flash芯片在Tornado中没有提供,因此.需要开发者自己完整编写MTD层驱动程序代码,这也是TrueFFS驱动开发的主要工作。
Nand Flash 存储器 K9F2808UOB简介
K9F2808UOB的容量为132 Mb,存储空间的组织由32768个 (行)、每页528个字节(列)的方式构成。备用的16页位于列地址的512~527,K9F2808UOB还将存储空间分为块(Block),每块由32个页构成。因此,K9F2808UOB中共有1024个块,其内部结构如图3所示。
K9F2808UOB的读和写都是以页为单位进行操作的 擦除是基于块的操作。其地址通过8位端口传送,CLE和ALE信号线可用于实现I/O口上指令和地址的复用。指令、地址和数据都通过拉低WE和CE来从I/O口写入器件中 其指令和功能表如表1所列。
MTD层驱动程序的编写
对MTD层进行驱动开发,实际上就是通过软件实现Flash器件的识别、读、写和擦除功能。因此,开发的第一步就是在BSP目录下建立一个MTD层驱动代码文件。设计时可将文件取名为K9F2808.c。下面的工作就是在其文件中实现对Flash的操作。此操作过程可分别通过nandMTDIdentify(),nandMTDRead(),nandMTDWrite()及nandMTDErase()这四个函数来完成。此外,还需要一个Flash内存映射函数nandMTDMap()。这些函数的编写与上述K9F2808UOB的组织结构、指令和功能及其芯片引脚的连接有关。
图4是FLASH芯片K9F2808与嵌入式ARM芯片S3C44B0X的硬件连接图。图中,S3C44B0X的nGCS1与nWE和nOE通过与门一起对K9F2808UOB进行读写控制,而地址锁存信号ALE和控制锁存信号CLE则分别由S3C44B0X的ADDR2与ADDR1控制,K9F2808UOB的状态通过GPC8读出,GPC9用于控制片选信号。8根数据输入输出引脚分别连接S3C44B0X的8根数据线。
通过对硬件连接图的分析可知,FLASH的基地址为0x02000000,控制锁存地址为0x02000002,地址锁存地址为0x02000004,设计时可将其分别定义为NFBaseAddr,NFCLEAddr,NFALEAddr。对于FLASH的写命令来说,地址操作可由下列函数完成:
/*WRITE_COMMAND -写命令 */
LOCAL void WRITE_COMMAND (UCHAR cmd)
{
*((volatile UCHAR *)NFCLEAdd) = cmd;
}
/* WRITE_ADDRESS -写地址 */
LOCAL void WRITE_ADDRESS(UCHAR addr)
{
*(( volatile UCHAR *) NFALEAdd)=addr;
}
FLASH的状态可以通过S3C44B0X的IO口控制寄存器读出,定义如下:
#define NFRBStatus() ((*((volatile UINT32 *)S3C44B0X_PDATC))& (1<<8))
因篇幅关系,这里无法将读、写及擦除函数一一列出,开发者可参考芯片资料,按照K9F2808UOB的各种操作时序,分别写出对Flash进行读、写、擦除等操作的函数。
在前面提到的五个函数中,需要特别注意的是nandMTDIdentify(), 因为此函数不仅会完成器件的辨识工作,而且还会在TrueFFS文件系统初始化时被调用,其调用过程如图5所示。因此,nandMTDIdentify需要对Flash的参数进行一些设置,并将读、写及擦除函数在上层注册,以供上层函数调用。但在设计时,需要在此函数中添加如下代码:
图5 TureFFS中Identify函数在VxWorks中的调用过程
pVol->write=nandMTDWrite;
pVol->erase=nandMTDErase;
pVol->map=nandMTDMap,
当K9F2808.c文件完成以后,在MakeFile文件MACH_EXTRA一项中添加K9F2808.o可将TureFFS文件驱动程序加入系统。
Socket驱动识别及系统配置
MTD层驱动完成后,接下来就是Socket驱动的识别和TrueFFS文件系统的配置。这部分工作相对比较简单。Socket层的相关代码是在sysTffs.c中完成的,开发者可以直接复制任何一个installDir\target\src\drv\tffs\sockets下的xxx-sysTffs.c到BSP目录下,并将其改名为sysTffs.c, 然后修改FLASH_BASE_ADRS以及FLASH_SIZE的宏定义,同时添加宏定义:
#define INCLUDE_MTD_NAND
同时将tffsConfig.c文件复制到BSP目录下,在tffsConfig.c中的mtdTable[]中注册自己所写的nandMTDIdentify:
#ifdefINCLUDE_MTD_NAND
nandMTDIdentify,
#endif
接下来就应修改在installDir\target\h\tffs中的stdcomp.h文件。在其中添加MTD识别函数
FLStatus nandMTDIdentify(FLFlash vo1);
至此,socket驱动识别工作就算完成。最后,就可在config.h中添加所需功能的宏定义:
#define INCLUDE_TFFS
#define INCLUDE_TFFS_DOSFS
#define INCLUDE_TFFS_SHOW
实现结果
当上述所有工作都完成以后,VxWorks就会在启动时调用tffsDrv()函数并初始化TrueFFS文件系统。用户可以通过tffsDevFormat函数格式化
Flash设备,并通过usrTffsConfig函数来创建TrueFFS设备。因为包括了DOS文件系统的宏定义,因而用户可以用DOS方式访问Flash设备。其结果如下:
->usrTffsConfig0,0,"/tffs0"
->devs
drv name
0/null
1/tyCo/0
1/tyCo/l
5 host:
6/vio
3/tffs0
-> copy "vxworks" ,"/tffs0/vxworks"
Copy OK:966996 bytes copied
->11 "/tffs0"
Listing Directory/tffs0:
-rwxrwxrwx 1 0 0 966668
Jan 1 1980 vxworks
结束语
通过TrueFFS对磁盘的仿真功能,可完成嵌入式VxWorks操作系统对FLASH设备的读写、分区、格式化等一系列操作。通过对操作系统的I/O控制调用,VxWorks还可以方便的访问FLASH设备。另一方面,用TureFFS技术对数据在Flash中的读写操作进行管理,可大大提高对FLASH的写操作次数,从而提高FLASH的使用寿命。本文以Nand Flash K9F2808UOB为例,结合嵌入式芯片S3C44B0X详细的介绍了其在VxWorks操作系统上实现TrueFFS驱动的过程。由此可见,TrueFFS驱动的实现可广泛应用于各种工业控制系统,具有较大的实用价值。