Flash 存储器以其体积小、耗电省、非易失的特性,越来越广泛地应用于嵌入式系统开发中,成为重要的程序和数据载体。TrueFFS 文件系统是M - systems 公司推出的Flash 管理软件,它为种类繁多的Flash 提供了标准的块设备接口,因此被包括VxWorks 在内的很多嵌入式操作系统所采用。建立TFFS 后,用户可以像操作标准磁盘一样实现对Flash 的管理。

1 TrueFFS 文件系统结构

TrueFFS 位于DOS 文件系统和Flash 存储器之间,可以实现对底层Flash 的读写操作,同时对上层提供应用接口,使Flash 像标准磁盘设备一样由操作系统和文件系统所管理。其在整个系统中的位置和结构如图1 所示。核心层为文件系统提供完整的块设备功能; 翻译层负责管理文件系统和Flash 各个块的关系,实现逻辑块到物理块的映射,另外它还实现设备模拟算法和Flash 管理算法,如坏块管理、碎片回收、损耗均衡等; MTD( MemoryTechnology Driver )层实现Flash 底层驱动,如读、写、擦除等;Socket 层提供TFFS 与硬件之间的接口服务,如向系统注册Socket 设备、检测插拔、硬件写保护等。

2 TrueFFS 文件系统算法

TrueFFS 能均匀使用Flash,用冗余数据结构保证可靠的数据操作,能排除损坏以避免错误,实现了FTL( FlashTranslation Layer) 标准。

( 1) 损耗均衡算法

Flash 存储器的擦除寿命有限,随着使用次数的增多,它最终会变成只读状态。为延长其寿命,行之有效的方法就是平衡使用所有的存储单元,而不让某一单元过度使用。TrueFFS 使用一种基于动态维护表的block-to-flash( 块对应于Flash) 传输系统来实现损耗均衡技术。当块数据被修改、移动或碎片回收后,这张维护表会自动调整。

( 2) 碎片回收

块数据的修改使得Flash 的一些块区域被填满无效数据,这些区域在擦除之前变得不可写。TrueFFS 使用一种碎片回收( garbage collection) 机制来回收这些块。该机制从一个预擦除单元内拷贝所有的有效数据块到一个新的单元,然后更新block-to-flash 映射表,最后擦除废旧的预擦除单元。

( 3) 块分配和关联数据集结

TrueFFS 会将关联的数据( 如出自同一个文件) 集结到同一个单独擦除单元( erase unit) 内的一段连续的区域中。为此,TrueFFS 尽量在同一个擦除单元( erase unit) 内维持一个由多个物理上连续自由的块组成的存储池。这就提高了数据的读取效率,减少碎片的产生。

( 4) 错误恢复

TrueFFS 使用了一种先写后擦的策略。当更新Flash 一个扇区的数据时,只有在更新操作完成并且新存储的数据校验成功后,先前的数据才会被允许擦掉。操作成功,新扇区的数据才有效,否则老扇区的数据有效。

3 开发背景介绍

在开发中使用的硬件电路板焊接了64 MB SDRAM,两片NOR Flash,每片8 MB。嵌入式VxWorks 开发时生成bootrom. bin 文件为256 KB,VxWorks 镜像文件为5. 13MB。计划借助TrueFFS 创建两个磁盘C 和D,C 中存放bootrom. bin 和VxWorks 镜像文件,D 中存放数据文件和工作日志。但创建TFFS 时,Flash 大小必须以2 的正整数次幂对齐,即C 盘空间只能为1 MB、2 MB、4 MB 或8 MB。由于bootrom. bin 是直接固化到第一片NOR Flash 中,所以无法实现将该Flash 全部创建TFFS,导致不仅无法存放VxWorks 镜像文件,而且还造成Flash 空间的浪费。

4 实现过程

将第一片NOR Flash( Intel 公司生产的JS28F640J3)起始处的2 MB 空间用于固化bootrom. bin 文件,上电后可自动运行bootrom; 另外6 MB 空间创建TFFS 文件系统。构建TFFS 的过程中涉及5 个文件的修改: config. h、Makefile、sysTffs. c、tffsConfig. c、i28f640. c。各文件改动如下:

( 1) config. h: 加入必要的定义

#define INCLUDE_TFFS

#define INCLUDE_TFFS_DOSFS

#define INCLUDE_TFFS_SHOW

#define INCLUDE_DOSFS

#define INCLUDE_TL_FTL

/* 包含需要使用的翻译层* /

( 2) Makefile: 将生成的i28f640. o 编译进系统映像,加入定义

MACH_EXTRA = i28f640. o

( 3) sysTffs. c: 配置TFFS 各项参数

#define INCLUDE_MTD_I28F640

/* 可以调用i28f640Identify 函数* /

#define INCLUDE_TL_FTL

/* 包含需要使用的翻译层* /

#undef INCLUDE_TL_SSFDC

/* 去掉不使用的翻译层* /

#define FLASH_BASE_ADRS 0

/* TFFS 空间从0 地址开始* /

#define FLASH_SIZE 0x00800000

/* 共8MB * /

改写sysTffsFormat 函数,完成格式化过程。此处必须弄清tffsDevFormatParams 中各个参数的定义。

typedef struct {

long int bootImageLen;

/* bootImage 需要从flash 开始处预留的长度* /

unsigned percentUse;

/* Flash 被格式化的百分率,为了提高TrueFFS 的性能,不要设为100%,以便任何时候都有空余空间。默认值为99%* /

unsigned noOfSpareUnits;

/* 空余擦除单元数目,目的在于flash 出现坏块时可以用它来替代,默认为1* /

unsigned long vmAddressingLimit;

/* FTL 在RAM 中映射的大小,默认为61Kbytes* /

FLStatus ( * progressCallback) ( int totalUnitsToFormat,int totalUnitsFormattedSoFar)

;

/* 回调函数,用来监测flash 擦除过程,如果返回值为OK,则继续,否则停止擦除* /

char volumeId;

/* Dos 卷标号* /

char FAR1 * volumeLabel;

/* Dos 卷标字符串,如果为NULL,则没有卷标* /

unsigned noOfFATcopies;

/* 文件分配表( FAT) 的拷贝数,正常情况下只使用一个FAT,而另一个只有在使用的FAT 被破坏的情况下用来恢复分配表,默认为2* /

unsigned embeddedCISlength;

/* CIS 嵌在单元头部( unit header) 之后的字节长度* /

char FAR1 * embeddedCIS;

/ * 单元头部被结构化用来作为一个PCMCIA tuple链( aCIS) 的起始,它包含了一个数据组织tuple,通常用16 进制的0xFF 来标示上一个单元头部结束的位置( end-of-tuple-chain) 。

* /

} FormatParams;

实际使用的格式化参数为{ 0x00200000l,99,1,

0x10000l ,NULL,{ 0,0

,0

,0

} ,NULL,2,0,NULL} 。此文件的改写是实现非2 的n 次幂TFFS 文件系统创建的关键。在设置Flash 地址和空间大小时依据NOR Flash 的实际参数配置,而在对Flash 格式化时修改bootImageLen 参数,将2 MB 空间给bootrom,而TFFS 只使用后面6 MB 空间。

( 4) tffsConfig. c: 在MTDidentifyRoutine mtdTable[]中加入定义

#ifdef INCLUDE_MTD_I28F640

i28f640Identify,

#endif

( 5) i28f640. c: 实现MTD 层的功能根据js28f640j3 数据手册编写FLFlash 结构体的各项成员,包括i28f640Write、i28f640Erase、i28f640Identify、lv28f640MTDMap。

程序中需要注意以下几点:

①对于NOR Flash,不需要编写i28f640Read 函数;

②如果要创建多于1 个TFFS 文件系统,需要对每个文件系统编写lv28f640MTDMap 函数;

③首次创建时,最好#define DEBUG_PRINT printf,可以观察整个创建过程,便于查找问题;

④需要在擦除和写操作中屏蔽中断,因为Flash 在擦除、读写ID 状态时,不能正常读取Flash 中的数据。而VxWorks 的异常入口位于Flash 存储器的开始处,异常发生时不能得到正常的入口指令,会导致系统跑飞。

5 文件系统创建

第一次启动时设置通过网络加载映像,当系统启动成功后在Shell 中执行以下命令:

- tffsShowAll

TFFS Version 2. 2

0: socket = RFA: type = 0x17,unitSize = 0x20000,mediaSize

= 0x800000

1: socket = RFA: type = 0x17,unitSize = 0x20000,mediaSize

= 0x800000

value = 48 = 0x30 =

- sysTffsFormat

value = 0 = 0x0

- sysTffsFormat

- usrTffsConfig 0,0

/tffs

value = 0 = 0x0

- devs

drv name

0 /null

1 /tyCo /0

5 host:

6 /vio

3 /tffs

value = 25 = 0x19

此时可以看到3 /tffs,说明设备挂接已经成功。执行dosFsShow/tffs /命令,/tffs 空间5. 68 MB 可用。

6 结束语

通过对TrueFFS 相关函数的配置,可实现嵌入式Vx-Works 中非2 的n 次幂TFFS 文件系统的构建。本文详细描述了创建过程及注意事项。这种方式已经应用到某发射系统的显控技术上,设备运行稳定、可靠,具有较大的实用价值。