通過在嵌入式操作系統(tǒng)uClinux上實(shí)現(xiàn)可讀寫JFFS文件系統(tǒng)的實(shí)例,介紹了在嵌入式系統(tǒng)中使用Flash芯片的方法。
1 引言
近年來,隨著電子技術(shù)的不斷進(jìn)步,嵌入式系統(tǒng)開發(fā)已成為熱點(diǎn),而Linux作為一個(gè)自由軟件 ,也得到了極大的發(fā)展 ,嵌入式系統(tǒng)與Linux的結(jié)合,正日益被人們看好。Linux具有內(nèi)核小,效率高,源代碼開放等優(yōu)點(diǎn),還內(nèi)含了完整的TCP/IP網(wǎng)絡(luò)協(xié)議,很適合在嵌入式系統(tǒng)中使用。作為專門為嵌入式微處理器定制的小型化Linux,uClinux正是嵌入式Linux的代表。在嵌入式系統(tǒng)開發(fā)中,F(xiàn)lash 芯片以相對低廉的價(jià)格提供了高可靠性和高密度的存儲,已成為嵌入式系統(tǒng)的重要組成部分。在很多嵌入式系統(tǒng)中,操作系統(tǒng)及應(yīng)用程序直接固化在Flash上,系統(tǒng)啟動(dòng)時(shí),代碼直接在Flash上開始運(yùn)行。
2 在嵌入式系統(tǒng)中使用Flash
當(dāng)前的嵌入式系統(tǒng)開發(fā),需要方便靈活地使用Flash,以嵌入式的Web Server為例,在運(yùn)行過程中,要求能夠動(dòng)態(tài)地保存一些數(shù)據(jù),并且當(dāng)系統(tǒng)重新上電時(shí),保存的數(shù)據(jù)依然存在。又比如將嵌入式處理器應(yīng)用于工控領(lǐng)域,可能整個(gè)系統(tǒng)都集成在一小塊電路板上,一些重要的工藝參數(shù)在控制過程中需要?jiǎng)討B(tài)地改變并保存,而使用硬盤等存儲介質(zhì)又不太現(xiàn)實(shí),在這種場合下,僅僅將Flash作為保存系統(tǒng)代碼的ROM使用是“大材小用”了。需要充分發(fā)揮Flash可擦寫的優(yōu)勢,在系統(tǒng)運(yùn)行過程中,動(dòng)態(tài)地擦寫Flash來保存數(shù)據(jù)。針對嵌入式系統(tǒng)多樣、靈活、專用性強(qiáng)等特點(diǎn),可以發(fā)揮嵌入式操作系統(tǒng)軟件復(fù)用的優(yōu)點(diǎn),找到一種方便、快捷地使用Flash 的方法來縮短開發(fā)時(shí)間,提升系統(tǒng)性能,嵌入式Linux就提供了這樣一條捷徑。由遍布全世界的自由軟件開發(fā)者為Linux提供支持,使得在嵌入式Linux上使用Flash變的十分容易。
3 JFFS 文件系統(tǒng)簡介
我們使用的uClinux系統(tǒng)采用ROMFS作為根文件系統(tǒng),它相對于一般的EXT2文件系統(tǒng),具有節(jié)約空間的優(yōu)勢。但是ROMFS是一種只讀的文件系統(tǒng),不支持動(dòng)態(tài)擦寫保存,對于系統(tǒng)需要?jiǎng)討B(tài)保存的數(shù)據(jù)只能采用虛擬ram盤的方法(ram盤使用EXT2文件系統(tǒng))。
針對ROMFS文件系統(tǒng)存在的問題,我們可以使用JFFS文件系統(tǒng)(Journaling Flash File System)。JFFS文件系統(tǒng)是瑞典的Axis Communications公司(www.axis.com) 在GNU General Public License下發(fā)布的自由軟件,主要用于嵌入式Linux。只需要在自己的嵌入式Linux中加入JFFS文件系統(tǒng)并做少量的改動(dòng),就可以使用JFFS文件系統(tǒng)。通過JFFS文件系統(tǒng),可以用Flash來保存數(shù)據(jù),即將Flash作為系統(tǒng)的硬盤來使用。可以像操作硬盤上的文件一樣操作Flash芯片上的文件和數(shù)據(jù)。系統(tǒng)運(yùn)行的參數(shù)可以實(shí)時(shí)保存到Flash芯片中,在系統(tǒng)斷電后數(shù)據(jù)仍然存儲在Flash芯片中。
作為一種EEPROM,F(xiàn)lash可分為兩種主要類型:NOR Flash 和NAND Flash。一片沒有使用過的Flash,每一位的值都是邏輯1,對Flash的寫操作就是將特定位的邏輯1改變?yōu)檫壿?。而擦除就是將邏輯1改變?yōu)檫壿?。Flash的數(shù)據(jù)存儲是以塊(Block)為單位來組織的,F(xiàn)lash只能整塊擦除,而Flash的壽命是以擦除次數(shù)來計(jì)算的,一般是每塊100,000次。為了保證某塊不早于其他塊到達(dá)其壽命,就有必要在所有塊中盡可能地平均分配擦除次數(shù),這就是“損耗平衡”。JFFS 文件系統(tǒng)是一種“追加式”的文件系統(tǒng),新的數(shù)據(jù)總是被追加到上次寫入數(shù)據(jù)的后面。這種“追加式”的結(jié)構(gòu)就自然實(shí)現(xiàn)了“損耗平衡”。
要加入JFFS文件系統(tǒng),需實(shí)現(xiàn)Linux下對Flash芯片的驅(qū)動(dòng),Axis Communications公司提供了實(shí)現(xiàn)代碼。在這個(gè)系統(tǒng)中,代碼包括uClinux/linux/drivers/block/flash.c 和uClinux/linux/include/linux/flash.h。
在flash.c中的設(shè)備初始化函數(shù) flash—init()里,將Flash作為塊設(shè)備向系統(tǒng)注冊:
4 開發(fā)環(huán)境簡介
這里采用的是宿主機(jī)+目標(biāo)板的開發(fā)模式,宿主機(jī)為PC+redhat7.2 ,目標(biāo)板為Motorola Coldfire5272+uClinux, uClinux版本為2.0.38,在宿主機(jī)上將uClinux和應(yīng)用程序編譯后,下載到目標(biāo)板的Flash中運(yùn)行。我們使用的Flash是2片AMD AM29LV160BT,大小為2M字節(jié),工作在16bit雙字節(jié)模式。對于Motorola Coldfire5272,其RAM、Flash、外設(shè)I/O 參與統(tǒng)一平坦編碼,也沒有地址變換。2片F(xiàn)lash的地址范圍設(shè)置為:0xffb00000-0xffcfffff 和0xffd00000-0xffefffff。每片F(xiàn)lash共有35個(gè)扇區(qū),除前四個(gè)扇區(qū)不規(guī)則,大小分別為:16K,8K,8K,32K 外,剩余31個(gè)扇區(qū)均為64K字節(jié)大小。
5 實(shí)現(xiàn)JFFS 文件系統(tǒng)的實(shí)例
為實(shí)現(xiàn)Flash上的JFFS文件系統(tǒng),需要在內(nèi)核中加入對JFFS文件系統(tǒng)和Flash設(shè)備的支持;針對具體的Flash 芯片修改設(shè)備驅(qū)動(dòng)程序;生成設(shè)備節(jié)點(diǎn)并將JFFS文件系統(tǒng)掛接到Flash 設(shè)備上。
5.1在內(nèi)核中加入對JFFS文件系統(tǒng)和Flash 設(shè)備的支持
標(biāo)準(zhǔn) Linux可以模塊的形式加載各種類型的設(shè)備驅(qū)動(dòng),要求在設(shè)備驅(qū)動(dòng)中編制兩個(gè)入口點(diǎn):init—module() 和 cleanup—module() ; uClinux 2.0 內(nèi)核不支持內(nèi)核模塊 LKM(loadable kernel modules),設(shè)備驅(qū)動(dòng)及文件系統(tǒng)要靜態(tài)地編譯進(jìn)內(nèi)核。我們需要:
完成上述修改并編譯后,JFFS文件系統(tǒng)和Flash設(shè)備就被編譯入內(nèi)核,同時(shí)在系統(tǒng)引導(dǎo)時(shí)加入了對JFFS 文件系統(tǒng)和 Flash設(shè)備的初始化函數(shù)的調(diào)用。
5.2針對具體設(shè)備修改Flash設(shè)備驅(qū)動(dòng)程序
Axis Communications在發(fā)布JFFS的同時(shí),也給出了Flash 設(shè)備的驅(qū)動(dòng)程序。此驅(qū)動(dòng)程序支持AMD,Toshiba等公司的主流系列Flash芯片,需要根據(jù)自己系統(tǒng)中具體Flash芯片的型號及配置,修改驅(qū)動(dòng)程序,使Flash設(shè)備能夠在嵌入式系統(tǒng)中正常工作。如果讀者使用的是此驅(qū)動(dòng)尚未支持的Flash芯片,只需仿照其他型號,將Flash型號加入此驅(qū)動(dòng)程序即可。
下面,以系統(tǒng)中的Flash為例,給出uClinux/linux/drivers/block/flash.c中需要的修改:
(1) 在文件的開頭處,加入#define CONFIG—BLK—DEV—FLASH。
(2) 在flash—probe(),chips〔0〕.start = (unsigned char *)(0xf0200000),這個(gè)值取決于系統(tǒng)中實(shí)現(xiàn)JFFS的Flash芯片的起始地址,在第2片F(xiàn)lash上實(shí)現(xiàn)JFFS ,其起始地址為0xffd00000,所以將其改為 chips〔0〕.start = (unsigned char *)(0xffd00000),隨后,需要根據(jù)芯片型號設(shè)置4個(gè)起始扇區(qū)的大小,系統(tǒng)中Flash的型號是AM29LV160BT。以下代碼定義了起始4個(gè)扇區(qū)的大小:chip→bootsectorsize〔0〕= 0x8000; chip→bootsectorsize〔3〕 = 0x2000; chip→bootsectorsize〔0〕= 0x2000; chip→bootsectorsize〔3〕 = 0x4000。
我們使用的Flash起始4個(gè)扇區(qū)的大小前文已經(jīng)給出,所以需要將這4個(gè)值依次改為0x4000,0x2000,0x2000,0x8000即可。
(3) 在uClinux/linux/drivers/block/ll-rw-blk.c中的blk—dev—init()函數(shù)中,在flash—init()前加入flash—probe()調(diào)用執(zhí)行對flash的檢測。
5.3 將JFFS文件系統(tǒng)掛接到Flash設(shè)備上
首先在宿主機(jī)的uClinux/romfs/dev目錄下新增設(shè)備節(jié)點(diǎn):mknod flash0 b 60 16;mknod flash1 b 60 17;mknod flash2 b 60 18。
在Flash芯片上建立起分區(qū)。這樣,當(dāng)重新編譯內(nèi)核并將內(nèi)核下載到Flash中后,就可以在目標(biāo)板的/dev目錄下新增Flash設(shè)備文件供我們使用,目標(biāo)板的uClinux系統(tǒng)啟動(dòng)之后,在目標(biāo)板上執(zhí)行mount-t jffs /dev/flash1/mnt,就在flash1分區(qū)上建立起了JFFS 文件系統(tǒng),JFFS文件系統(tǒng)掛接在目標(biāo)板 /mnt目錄下,可在此掛接目錄上執(zhí)行建立、刪除目錄,文件等操作。
6結(jié)束語
開發(fā)的實(shí)例表明,開放源代碼的Linux在嵌入式系統(tǒng)開發(fā)中有極大的優(yōu)勢,借助于Linux的開放性,我們能夠靈活快捷地開發(fā)嵌入式系統(tǒng)應(yīng)用。
參考文獻(xiàn)
[1]Alessandro Rubini. Linux設(shè)備驅(qū)動(dòng)程序 [M].北京 :中國電力出版社,2000.
[2]Daniel P.Bovet & Marco Cesati. 深入理解Linux內(nèi)核[M].北京:中國電力出版社,2001.
[3]David Woodhouse. JFFS : The Journalling Flash File System[EB/OL]. http://sources.redhat.com, 2002.
[4]Advanced Micro Devices, Inc. Am29LV160B Datasheet[EB/OL]. http://www.amd.com, 1999.