flash檔案系統實現原理
http://www.dpj.com.cn/ 網址
摘要:在深入分析TI為開發DSP提供的RTS.LIB(RTS.SRC為源泉代碼)的基礎上,介紹對自訂的檔案和裝置的操作方法;設計一個簡易的Flash檔案系統,極
大地方便了應用編程。
關鍵詞:DSP CC/CCS Flash 檔案系統
1 概述
在開發DSP的應用程式過程中,經常需要處理一些資料檔案。這些資料檔案可以是實際採集到的資料集合,也可以是用類比模擬軟體產生的資料集合,一般是
以檔案的形式存放在主機磁碟上的。一般的開發環境(如TI的CCS和CC)都提供了ANSI C標準操作檔案格式,如開啟一個檔案fopen("盤符:/路徑/檔案名稱",
“開啟模式”)。嵌入式系統一般都外掛Flash。我們希望能夠和讀寫主機磁碟檔案一樣操作Flash讀寫時序等問題,使應用編程人員可以把精力用在解決實際
應用問題上,從而提供一個良好的編程介面。同時,在需要鍵盤、串口等裝置的系統中,也希望提供一個簡易的API介面,如從鍵盤得到一個鍵,只需作如下
操作,在執行fopen("keyboard","讀")後,就可以用fread函數讀入一個字元。
結合TI公司提供的DSP開發環境CC/CCS(CC針對3X系列,CCS針對5X和6X系列)和實際開發經驗,提供上述問題的解決方案,並成功應用到我們的產品中。
2 CC/CCS檔案操作機制
TI公司為其TMS320C3X系列DSP提供了一個開發環境Code Composer,配套的C語言編譯器提供了檔案的標準操作。在調試(debug)環境下,對主機(host)硬碟文
件的操作是通過標準的ANSI檔案操作格式與主機的通訊來完成的。ANSI C I/O操作分為三個等級—high level、low level和Device level。在High level中
,標準介面是Fopen和Fwrite等函數;而Low level中是Open和Write等函數。這三個等級功能用三個表來實現—檔案表、流表(實質就是記憶體緩衝區索引)和
裝置表。檔案的開啟和關閉等基本屬性在檔案表中反應。當開啟一個檔案時,檔案表中便相應增加一個描述該檔案的資訊單元;同樣,關閉一個檔案時,該
檔案的資訊單元從檔案表中被刪除。流表提供了對檔案的緩衝操作處理,緩衝區位置和大小等均在流表中記錄。一個檔案對應一個流,即緩衝區。對檔案的
讀寫就是對緩衝區的讀寫。當緩衝區填滿時,再一次性寫入Flash等裝置中,避免了對Flash的頻繁操作,延長了Flash的使用壽命。裝置包括Flash、硬碟、
鍵盤等在裝置表中體現。多個流可以對應一個裝置,例如在Flash中可以開啟多個檔案,但是一個裝置不能對應多個流。流操作和裝置操作是緊密聯絡在一起
的。當開啟一個檔案時,同時給出了該檔案在什麼裝置上操作,再分配一個流。以後對該檔案的操作通過流對應的具體裝置的驅動函數來完成。主機的
target任何外設都可被加入進去成為裝置表的成員之一。
Code Composer對HOST磁碟檔案的操作最終是通過與HOST整合式開發環境通訊的方式來進行。TI提供的RTS.LIB提供兩個函數與主機通訊,writemsg()函數發送
資料和參數到主機。Readmsg()函數從主機讀取資料到目標機。Code Composer再與主機進行互動,利用主機檔案系統的支援,屏蔽了具體的物理地址讀寫問
題。在調試階段,當要在主機上建立檔案、讀取檔案和儲存資料時,只需用標準的ANSI C函數操作就可以,從而極大方便了編程調試。
3 Flash檔案系統的實現
嵌入式檔案系統一般有集中管理檔案系統,儲存空間的使用資訊集中存在儲存空間的某個地方,如DOS的FAT,Unix的inode表。線性檔案系統,又稱為連續檔案
系統,每個檔案相關的所有資訊都連續存放在儲存空間中。與集中式檔案系統相比,實現更簡單,讀寫更快,特別是將檔案的關鍵系統分布存放。記錄檔系
統順序寫入檔案系統的修改,如同日誌記錄一樣,可加速檔案寫入和崩潰修複。採用Log唯一結構,Log包含索引資訊、名稱和資料。嵌入式系統不可能帶硬
盤,一般都是基於Flash儲存空間的。
3.1 Flash特點及其相應處理
Flash的讀操作與普通RAM時序一樣,但是寫和擦除操作則具有自身的特點。同一地址不能同時寫入兩次,必須進行費時的擦除操作。執行擦除的方式有三種
:一是片擦除,即一次性全部擦除所有內容(這個相當于格式化功能,在第一次使用時可以執行這種操作);二是塊擦除;三是扇區擦除。以SST39VF400A為
例,塊Block的大小是32KB,扇區的大小是2KB,塊擦除一次擦除一個塊內容;扇區類似。如果一個檔案內容被改動,且改動的內容不足一個扇區的話,則更
新檔案時必須重寫這個扇區的所有內容;在重寫前必須擦除該扇區的所有內容。因此基於Flash的檔案系統不能完全套用已有的檔案系統,但可以在其基礎上
進行改動。Flash能夠擦除的範圍越小,對檔案的改動就越小,所執行的I/O操作就越小,從而減少I/O時間,提供檔案系統的即時效能。我們使用的
SST39VF400A的扇區大小是2KB,也就是2048B(1K=1024)。用常數定義,#define FileUnit 2048。
3.2 Flash檔案系統的層次性
與ANSI C標準相對應,我們將Flash檔案系統分為3個層次。第一層次,API層。API層是檔案系統與使用者應用程式之間的介面,包含一個與檔案函數相關的函
數庫,如FS_FOpen、FS_Fwrite等,也相當於High Level層。第二層次,檔案系統層,即Low Level層。該層處理檔案是否存在,開啟,關閉和為檔案分配相
應的緩衝等。該層調用底層驅動。第三層是Device Level層,就是裝置驅動層。Flash的實際讀寫操作就是在該層進行的,特定的Flash儲存空間對應特定的讀
寫程式。
3.3 Flash檔案資訊表的設計
該表儲存Flash中已有檔案的屬性,Flash大小和檔案的屬性等都在該表中反映出來。該表與Flash中的內容保持同步更新,即一個檔案最小塊更新完畢時,寫
入Flash中。
Flash的空間分配:
①Flash空間,以簇為單位,讀和寫都是一簇,即一個扇區單位;
②0簇給檔案配置表,不被應用檔案佔用;
③每次檔案系統初始化時,把Flash內0簇的內容讀取到記憶體中,儲存在數組FAT16[]中。
常量定義
#define CLUSTER_BLOCK_SIZE 2048 //每一簇的位元組數
#define NUMBER_OF_CLUSTER_IN_FAT16 25
//在檔案配置表中,一共有多少個簇
#define NUMBER_OF_FILE_BUF 10
//一共有幾個檔案緩衝區
#define MODE_OPEN_FILE_READ 0x01 //讀取(檔案開啟模式)
#define MODE_OPEN_FILE_WRITE 0x02 //寫入(檔案開啟模式)
#define MAX_SIZE_OF_FIEL 2048 //檔案的最大尺寸
檔案結構體:
typedef struct{
unsigned int IsLock:1;//檔案是否被上鎖,=0沒開啟;=1已被開啟。此標誌只在檔案的第一簇使用
unsigned int status:7;//簇的狀態,=0,此簇為色,沒使用;=1,此簇是第一簇;=2,此簇不是第一簇
char FileName[8];//檔案名稱,在第一簇有效
char FileExName[3]; //副檔名,在第一簇有效
unsigned int SizeOfFile;//檔案的位元組數,在第一簇有效
unsigned int NextCluster;//下一簇的簇號。當為0xffffffff時,說明這是當前檔案的最後一簇
}FlashFAT;
檔案控制代碼結構體:
typedef struct{
unsigned int Buffer[CLUSTER_BLOCK_SIZE];//檔案緩衝區
unsigned int fileblock;//檔案當前簇的位置
unsigned int filemode;//開啟支援的模式
unsigned int filebufnum;//檔案緩衝區中已被/寫的位元組數
unsigned int fileCurpos;//檔案讀寫的當前位置
unsigned int filesize;//檔案的大小
}FlashFILE;
3.4 Device Level驅動函數
SST39VF400A標準裝置級驅動函數如下:
void Program_One_Word(WORD SrcWord,WORD far Dst){/*寫入一個字*/
WORD far *Temp;WORD far*SourceBuf;WORD far*DestBuf;
Int Index;DestBuf=Dst;
Temp=(WORD far *)0xC0005555;/*設定地址為C000:555h*/
*Temp=0xAAAA; /*寫資料0xAAAA到此地址*/
Temp=(WORD far *)0xC0002AAA;/*設定地址為C000:2AAAh*/
*Temp=0x5555;/*寫資料0x5555到此地址*/
Temp=(WORD far*)0xC0005555;/*設定地址為C000:5555h*/
*Temp=0xA0A0;/*寫資料0xA0A0到此地址*/
*DestBuf=SrcWord;/*傳送位元組到目的地址*/
Check_Toggle_Ready(DestBuf);/*等待TOGGLF位準備好*/
}
原始碼見網站www.dpj.com.cn。
3.5 Flash檔案系統的工作流程
在使用Flash檔案系統前,先將FlashROM裝置加入裝置表中(最開始假設Flash中沒有任何檔案),讀入Flash檔案表。下面簡述系統工作流程。
(1)加入FlashROM裝置
add_device("FlashROM",_MSA,flash_open,flash_close,flash_read,flash_write,flash_lseek,
flash_unlink,flash_rename);
其中flash_open、flash_close、flash_read、flsh_write、flash_lseek、flash_unlink、flash_rename是最底層的
flash驅動函數名稱。針對不同的Flash,需要不同的驅動函數。
int flash_open(char *path,unsigned flags,int fno);
int flash_close(int fno);
int flash_read(int fno,char *buffer,unsigned count);
int flash_write(int fno,char *buffer,unsigned count);
(2)初始設定檔案系統
在使用Flash前,必須初始化。初始化臨時檔案緩衝區,將Flash的各種資訊讀入到系統中,如Flash的大小,存在的檔案的名稱、大小、建立日期等,這樣系
統才能正確使用Flash.
Init_eFS();/*初始設定檔案系統函數*/
(3)執行各種檔案操作
如果要在Flash上開啟一個檔案,執行fopen("FlashROM:/路徑/檔案名稱",“開啟模式”)就可以了。當開啟檔案時,先檢查檔案表中是否存在該檔案。如果沒
有,則在Flash檔案表中尋找是否存在該檔案。如果存在,則開啟;如果沒有,則建立這樣一個檔案,同時開啟該檔案。隨後就可以進行檔案的讀寫、追加、
屬性修改等操作。
該Flash檔案系統的幾個技術關鍵點:
①利用RTS.LIB(TI附帶有原始碼RTS.SRC)的進階層檔案操作功能。該庫已經按照ANSI C標準處理了高層檔案應用問題。我們可以如同在上位機上編程一樣使
用各種檔案操作函數,不同的是將盤符改為FlashROM盤符。例如,將fopen("C:/read.txt","r")改為fopen("FlashROM:/read.txt","r")。用這種模式操作
Flash,的繁瑣時序處理和扇區擦除等重複性問題,可以將精力集中到應用編程上來。
②用自設計的Low Level級代碼接管了RTS.LIB的低層處理。前述的Flash檔案資訊表是核心,只有通過該表才能知道Flash中究竟有什麼,在哪裡操作。當在
API層操作檔案時,高層函數將調用相應的底層處理屬數,在Low Level判斷檔案是否開啟,是否可讀寫等屬性。同時為該檔案分配一個內緩衝區,所有對該
檔案的操作先操作緩衝區,即流操作。當緩衝區滿時,調用的操作先操作緩衝區,即流操作。當緩衝區滿時,調用Device Level級函數,將資料寫入Flash中
。同樣,讀取的時候,是先讀取一個扇區內容,處理完畢後再讀取下一扇區內容。
操作鍵盤等其它外設相對Flash要簡單得多,不用設計檔案資訊表。執行兩個步驟就可以使用。一是加入裝置,調用add_device(……)函數,填入裝置名稱;二
是編寫裝置驅動函數,將對應的函數名作為參數傳入add_device()中。在這裡要說明的是,不同裝置、同樣的操作名其實際含義是不同的。如對鍵盤開啟一
個字元,則意味著讀入一個字元,因此在實際中應用靈活處理。
結語
該Flash檔案系統實現了基本的檔案讀寫功能,但是還有些不足地方:檔案分享權限設定問題沒有解決,在掉電的情況下可能導致檔案丟失。由於我們研製這個Flash
系統的目的在於方便編程、調試;同時在我們的應用領域(電力系統繼電保護)中,掉電的幾率非常低,儲存的檔案主要是整定值、控制字(修改不多)和
故障濾波記錄。這些資料即使丟失也不會造成災難性的後果,故該系統在整體上滿足我們的應用需求。
本文來自CSDN部落格,轉載請標明出處:http://blog.csdn.net/nogodoss/archive/2009/06/05/4243490.aspx