引言
在以DSP为核心的嵌入式系统中,尤其在需要处理和存储大量数据的应用领域,提供必要的文件管理功能显得尤为重要,但大多基于DSP的嵌入式系统一般不提供文件管理功能。目前,以DSP为核心的嵌入式系统中文件的存储一般采用FLASH存储器,而FLASH存储器都有自己的容量限制,不可能无限制地将所有采集到的数据全部记录到存储器中。针对上述问题,本文设计并实现了一种基于DSP的可循环读写的文件系统。其中DSP采用TI公司的TMS320C6678,存储载体采用16片三星公司的FLASH芯片K9WAG08U1M,单片容量2 GB,共32 GB。该文件系统具有以下几个特点:
① 统一管理FLASH存储器存储空间,实施存储空间的分配与回收;
② 实现文件的按名存取,使用方便、直观;
③ 向用户提供方便使用的接口,提供对文件系统以及文件的操作命令。
1 文件系统的基本架构与存储空间管理
1.1 文件系统的基本架构
文件系统中的FLASH以块为单位组织,读写的最小单位是页,每块512页,每页8 192字节,按块擦除。该文件系统参考FAT文件系统设计,FLASH开始部分4个数据块为系统数据区,用来存储文件系统信息。
存储器操作的时间瓶颈不在于数据传递,而是FLASH存储器内部的擦除和写操作等待。FLASH存储器读出的速度和DSP处理数据的速度都很快,因此虽然将页面作为读写操作的基本容量单位,但额外增加的操作时间很短。
为了使文件系统的结构更加清晰,同时便于文件系统的维护、升级和移植,将文件系统划分为三层[1]:文件管理层、文件逻辑层和驱动层。各层的主要功能如下:
① 文件管理层对整个文件系统进行封装,为应用层提供统一的、标准的API接口,将用户对文件操作的请求提交给文件逻辑层进行处理。为了增强文件系统在不同存储器上的移植能力,选取几个最基本的操作作为文件系统与FLASH存储器设备的应用接口。本文件系统提供的基本API函数见表1。
② 文件逻辑层为文件管理层提供服务,把文件管理层对文件的操作转换为物理逻辑上的操作,并提交给驱动层处理。
③ 驱动层实现对存储设备的物理操作,包括坏块管理、区块擦除、页面写入、页面读出等功能。
表1 文件系统API函数
1.2 文件系统的存储空间管理
本文件系统的存储结构类似于MSDOS的FAT文件系统结构,分别由系统记录、文件登记表、文件分配表和文件数据区域等组成[2],其基本结构如图 1所示。
图1 文件系统存储结构图
(1) 系统记录(SR)
系统记录(SR)存放存储器物理信息和文件系统分区信息。存储器物理信息包括存储器的类型、容量、划分成多少个区块、每区块包含多少个页面等。文件系统分区信息包括分区的起始块和结束块、分区的起始页和结束页、分区大小、可用空间等信息。系统记录占用256字节,其中前48字节为存储器物理信息,有效数据40字节;后208字节为文件系统分区信息,有效数据168字节。具体的存储定义见表2、表3。
(2) 文件登记表(FRT)
文件登记表(FRT)存放文件系统中每一个文件的文件代号、文件长度、文件属性以及该文件的存储链在文件分配表中的入口。考虑到嵌入式系统的应用范围,本文件系统不支持子目录结构。文件登记表占用15.75 KB,每个文件节点占用32字节,因此,该文件系统可管理15.75 KB/32 B=504个文件。文件登记表数据结构见表4。
表2存储器物理信息数据结构
表4文件登记表数据结构
(3) 文件分配表(FAT)
文件分配表(FAT)是整个文件系统的核心,存放着存储器上所有区块的占用与空闲情况以及每个文件的存储链接结构。考虑到在嵌入式处理器上实现的方便性并权衡文件系统应用的规模,选择将文件分配表固定为16字节的FAT标识,16 KB可标识8K个块,每块占用2字节,共可管理32 GB的FLASH。
(4) 数据区域(Data Aera)
数据区域(Data Aera)用于存放文件的数据内容。本文件系统中,数据分配的最小单位是存储器的一个基本擦除单位,即一个物理区块,大小为4 MB。也就是说,文件所占用的存储空间必须为一个物理区块的整数倍,即使文件只有1字节,也要占用一个物理区块的存储空间。
2 文件系统的实现
2.1 文件系统的初始化
当文件系统被加载时,系统首先扫描整个存储介质。将存储在介质中的系统信息表、文件登记表、文件分配表从存储介质中读取到内存,建立临时系统信息表和临时文件列表,创建一个临时文件分配表。这样,文件系统对文件登记表和文件分配表的操作转换成对内存中两个临时表的操作。因为内存的读写效率远远高于FLASH,因此可以大幅提高文件系统的操作效率。文件系统初始化流程图如图2所示。
图2 文件系统初始化流程图
2.2 降低文件系统的资源消耗
基于DSP的FLASH文件系统的资源消耗[3],主要包括程序代码开销、处理器占用时间、运行时内存开销以及额外的FLASH存储器消耗。其中,运行时内存开销很大程度上限制了FLASH文件系统的应用;而设计结构的改善与运行时内存开销直接相关,因此针对资源消耗的结构优化主要着重于减小运行时的内存开销。
FLASH存储器的擦除单位是区块,这是本文件系统中数据存储分配的最小单元。如果不采用任何措施,运行时内存开销中将至少包括备份一个完整区块数据的缓冲区;而一个FLASH存储器的区块可能很大,这在很多嵌入式系统中都是过大的资源[4]。
为此,采用交换缓冲区(Swap Buffer)技术来解决这个困难。当需要向某一个区块写入数据时,并不直接向该区块写入,而是首先擦除用于做交换缓冲区的区块,然后逐步向交换缓冲区填入目的数据内容。此时任何有用数据内容都未被破坏,所以运行内存中的缓冲就较小。当交换缓冲区填写完成后,再擦除目的区块,拷贝交换缓冲区内容到目的区块。
采用交换缓冲区后,对内存中的缓冲区大小没有特别要求,考虑到FLASH存储器的操作特性,选取FLASH存储器的页面容量作为内存缓冲区大小。在结构上做了上述改进后,可大幅降低文件系统在运行时的内存消耗。在一般的FLASH存储器中都有一个特别制作的区块,该区块保证不会损坏,适用于做交换缓冲区。这样可以省去中间交换缓冲过程的数据完整性检验,加快写操作的速度。
2.3 文件系统的可循环读写
由于FLASH具有读写速度较快而擦除较慢的特点[5],写入过程中,当系统存储空间不足需要擦除数据时,将出现擦除过程尚未结束而再次申请写入的情况,导致数据写入错误。为了避免这一错误,在该文件系统中设计了一个擦除队列,并保留一定的存储空间。当检测到系统的剩余存储空间小于保留空间的大小时,把旧的数据块放入待擦除队列,在写入数据的间隙擦除数据,同时缓存待写入数据,擦除完成后继续写入过程。文件系统的循环读写流程图如图3所示。
图3 循环读写流程图
2.4 文件系统的高可靠性设计
在多数嵌入式文件系统中,仅仅对数据区域提供坏损管理,而对于系统记录、文件分配表和文件登记表这3个极重要的文件系统数据结构却未做任何保护。一旦这些区域的内容失效,必然将导致文件数据的大量损失。
针对FLASH存储器的写操作异常终止问题(如非正常关电),本文件系统中将系统记录、文件分配表和文件登记表这3个文件系统重要数据结构采用冗余存储的方法进行处理。这样可以避免因它们的操作异常,而导致的整个文件系统失效。
具体做法是:将本次对文件操作所对应的系统信息记录标记为最新,以此类推,则上次所做操作对应的系统记录为次新记录。对系统记录定义4个系统记录保留区块,将系统记录、文件分配表和文件登记表顺序存放在这个区域内,确切的位置在文件系统初始化时通过扫描找到最新的系统记录。
如此可确保FLASH存储器上总是存有一整套完好的较新的系统记录表、文件分配表和文件登记表。在系统启动运行时,文件系统首先确定每一张表备份的合法性和时效性,判断出上次系统关闭时是否存在操作异常终止并及时更正。通过这样的设计,即使文件系统在使用中出现了写操作异常终止的情况,错误也只涉及当时被操作的文件数据,不会扩散给FLASH文件系统中的其他文件,更不会因此损坏3个文件系统表结构而造成整个文件系统的瘫痪。
结语
本文介绍了一种在DSP环境下开发文件系统的方法,并最终在项目中实现了该文件系统。经实际应用,很好地满足了项目在数据存储和文件管理方面的需求。
本系统软件主体代码以C语言写成,使用一个非常小的存储器设备驱动接口,具有较好的可扩展及可移植能力。另外,本文件系统针对FLASH本身的特性,采用冗余存储和三层结构设计,提高了文件系统的可靠性和操作效率,并具有良好的可维护性。