隨著嵌入式技術的不斷發展,嵌入式系統的應用越來越廣泛,人們對于嵌入式系統功能的要求也越來越高,相應地其大容量數據存儲和管理變得越來越重要。相對硬盤而言,FLASH等非易失性存儲器具有體積小、功耗低、成本低、抗震強等優點,已在嵌入式系統中被大量作為存儲設備使用,而大容量非易失數據存儲方案的應用還存在成本和軟件支持方面的問題需要克服。大頁NAND FLASH具有寫入速度快、容量大、成本低等優點,適合于需要進行數據存儲的場合。YAFFS2作為專門支持大頁NAND FLASH的文件系統在U-Boot和嵌入式Linux上一直沒有得到正式支持。本文結合部隊應用實際,在嵌入式Linux系統中實現了大頁NAND FLASH和YAFFS2文件系統的結合,為裝備的數據存儲處理搭建起了小型的智能化平臺。本文內容安排如下,首先介紹系統存儲方案特點和YAFFS2數據在大頁NAND FLASH上的儲存方式,然后詳細敘述系統移植和文件系統制作過程,最后對移植結果進行測試。
1 系統存儲方案設計
某國產化設備用于取代隨裝多臺套設備,除完成原設備的數據記錄功能外,還需進行數據翻譯、判讀,數據分析處理,二維顯示和三維動態復現等功能;同時,需存儲裝備長時間工作輸出的所有原始數據信息,類似黑匣子功能,以供事后分析使用。具有程序量大,數據需實時存儲,且數據存儲量大的特點。板上存儲設備包括SDRAM和FLASH,SDRAM為易失性存儲器,作為程序的運行空間和記錄數據的緩存空間;FLASH為非易失性存儲器,用于存儲系統軟件程序和記錄數據。
嵌入式系統中應用的FLASH主要有NORFLASH和NAND FLASH兩種。NOR FLASH的塊大小范圍為64~128 KB,其容量一般為l~32 MB,可作為嵌入式設備的啟動設備,適合于代碼存儲。NAND FLASH的塊大小范圍為8~64 KB,容量一般為8~512 MB,適合于數據存儲。它們之間的主要差別有以下幾點。
(1)速度。在寫數據和擦除數據時,NANDFLASH支持整塊擦寫操作,其速度比NOR FLASH要快得多,兩者相差近千倍;讀取時,NAND FLASH要先向芯片發送地址信息進行尋址才能開始讀寫數據,而NOR FLASH的操作則是以字或字節為單位進行的,直接讀取,所以讀取數據時,NOR FLASH效率更高。
(2)容量和成本。NOR FLASH的每個存儲單元與位線相連,增加了芯片內位線的數量,不利于存儲密度的提高。在面積和工藝相同的情況下,NANDFLASH的容量比NOR FLASH要大得多,生產成本更低。
(3)易用性。NAND FLASH的I/O端口采用復用的數據線和地址線,必須先通過寄存器串行地進行數據存取,各個產品或廠商對信號的定義不同,增加了應用的難度;NOR FLASH有專用的地址引腳來尋址,較容易與其他芯片進行連接,另外還支持片上執行XIP(eXecute In Place),應用程序可以直接在FLASH內部運行,簡化了產品設計。
(4)可靠性。由于FLASH的電器特性,在讀/寫數據過程中,會產生比特位反轉,造成一位或幾位數據錯誤。NAND FLASH位反轉的幾率比NOR FLASH高,在使用時需要使用EDC/ECC算法。NANDFLASH還可能會隨機分布壞塊。
(5)耐久性。FLASH由于寫入和擦除數據時會導致介質的氧化降解,導致芯片老化,所以并不適合頻繁地擦寫,NAND FLASH的擦寫次數是100萬次,而NOR FLASH只有10萬次。
基于以上分析,為了滿足經常性的進行實時快速大容量數據存儲和較長使用壽命的要求,采用NANDFLASH來存儲操作系統和數據,其復雜操作、比特位反轉和壞塊等問題可以通過文件系統解決。NORFLASH因為出現位反轉和壞塊的幾率小,并且讀取速度快,用來存儲啟動程序,能保證正常啟動系統的前提下提高設備反應時間。整個系統的存儲空間分配如圖1所示。
整個系統存儲空間由SDRAM,NOR FLASH,NAND FLASH組成。其中,sDRAM分成程序空間(Prog Space)和數據空間(Data Space)。NORFLASH存儲系統啟動程序U-Boot;NAND FLAsH分成程序空間(Prog Space)和數據空間(Data Space),程序空間中固化存儲Linux操作系統和YAFFS2文件系統及相應的應用程序,在U-Boot的控制下,通過頁傳輸方式讀入SDRAM程序空間中;數據空間中存儲來自前端的原始數據,該數據在SDR-AM中打包,以頁方式將數據寫入NAND FLASH中,提高數據寫入速度。
對小頁NAND FLASH的文件系統支持已有比較多的編程實例可借鑒,而對本文使用的大頁NANDFLASH的編程支持還沒有完整的說明。因此,移植嵌入式操作系統,以建立對大頁NAND FLASH支持的文件系統是該存儲方案需解決的關鍵問題。
2 YAFFS/YAFFS2文件系統分析
目前廣泛應用的嵌入式文件系統有JFFS/JFFS2(JournaIling FLASH File Systern) 和 YAFFS/YAFFS2(Yet Another FLASH File Syst-em)。JFFS/JFFS2文件系統主要針對NOR FLASH設計,在NAND FLASH上性能不佳。YAFFS/YAFFS2文件系統是專門針對NAND FLASH設計,其具有可寫入、修改并能永久保存文件的特性,并提供了損耗平衡和掉電保護。與JFFS相比,它減少了一些功能,因此速度更快、占用內存更少。此外YAFFS自帶NANDFLASH芯片驅動,并為嵌入式系統提供了直接訪問文件系統的API,用戶可以不使用Linux中的MTD和VFS,直接對文件進行操作。
YAFFS文件系統已發展為兩個版本,YAFFS和YAFFS2。YAFFS版本只支持512 B的小頁NANDFLASH。而YAFFS2作為YAFFS的升級版,在向下兼容小頁NAND FLASH的同時也能夠更好地支持2 KB的大頁NAND FLASH。YAFFS2的性能與YAFFS相比有很大提高,表1為YAFFS,YAFFS2(512 B×8),YAFFS2(2 KB×8)三者性能比較,從測試結果可以看出,YAFFS2和2 KB大頁NANDFLASH的結合更好地提高了存儲器操作效率。
YAFFS2文件系統在設計時就充分考慮了大頁NAND FLASH的結構,根據大頁NAND FLASH以頁面為單位存取的特點,將文件組織成固定大小的頁,利用大頁NAND FLASH提供的每個頁面(2 112 B,其中前2 048 B存儲數據)64 B的備用空間(SpareData,OOB)來存放ECC和文件系統的組織信息,這樣不僅能夠實現錯誤檢測和壞塊處理,還能夠提高文件系統的加載速度。以三星公司的K9F1G08UOA的NANDFLASH為例,它的單片存儲容量為128 MB,由1 024 block組成,每個塊包含64 page,每個頁均包含一個2 048 B的數據區和64 B的備用空間,總共包含2 112 B。結構如圖2所示。
表2說明了YAFFS2文件系統數據在NANDFLASH的備用空間內的存儲布局。
blockState:描述該塊的狀態。如果不是OxFF,就說明是壞塊。相對應的是,所有正常的塊,里面所有數據都是OxFF的。
chunkld:描述該頁在一個文件內的索引,所以文件大小被限制在232×2 KB。chunkld為O,說明此頁面保存的是文件頭。不為O,說明是數據頁面。文件內偏移量為0,即放在第一個頁面的文件,其chunkId為1,后面的以此類推。
ObjectID:描述對象ID號,用來惟一標示一個文件。所以YAFFS2文件系統支持的文件總數限制在232個。
nBytes:記錄該頁面內的有效字節數。
blockSequence:記錄著各塊被分配出去的先后順序,每分配出去一塊,就加1。在YAFFS2文件系統建立的時候,塊的掃描順序就是由它決定的,而不是FLASH的物理介質順序。在垃圾收集的時候也會以此作為參考之一,判斷該塊是否適合回收。
tagsEcc:Ecc,YAFFS Tags區域的ECC校驗數據。
ECC:數據區的ECC校驗數據。讀/寫數據區的數據時,每256 B生成3 B ECC校驗和,一頁面2 KB數據就會生成24 B的校驗數據。
3 系統移植
此次開發采用宿主機+目標系統的開發模式。宿主機為PC+Fedora9,Fedora9安裝在PC的虛擬機內。目標系統軟硬件組成為目標板(CPU為S3C2440A)+U-Boot+嵌入式Linux,Linux版本為2.6.29.4。交叉編譯工具為arm-linux-gcc-4.3.2。
選用嵌入式Linux系統是因為它有著技術上先進,健壯、安全;是多任務系統,支持ARM體系結構;源碼開放,驅動程序及其他資源非常豐富,良好的可移植性等優點。嵌入式系統的移植從軟件角度可以分為以下四個步驟。如圖3所示。
(1)引導加載程序的移植,包括固化在固件(Fireware)中的boot代碼和Bootloader兩大部分。大多數嵌入式系統中并沒有固件,Bootlo-ader是上電后執行的第一個程序。它主要用來初始化處理器及外設,然后調用Linux內核。
(2)嵌入式Linux內核移植。特定于嵌入式處理系統的定制內核以及內核的啟動參數。內核的啟動參數可以是內核默認的,或是由Bootlo-ader傳遞給它的。
(3)文件系統制作。包括根文件系統和建立于FLASH內存設備之上的文件系統。里面包含了Linux系統配置文件和運行應用軟件所需要的庫等。
(4)用戶應用程序編寫。特定于用戶的應用程序,它所實現的功能通常就是設計該嵌入式系統所要達到的目標,它們也存儲在文件系統內。
3.1 Bootloader移植
對于支持ARM架構的Bootloader有U-Boot,Vivi等。U-Boot(Universal Boot Loader)即通用Bootloader,是遵循GPL條款的開放源代碼項目。它可以引導Linux,VxWorks,LynxOS等多種操作系統。支持PowerPC,x86,ARM等多種架構的CPU,具有豐富的設備驅動源碼,如串口、以太網、SDRAM,FLASH等。系統采用U-Boot的版本為1.1.6,它已支持SMDK2410開發板,在其基礎上進行修改。U-Boot 1.1.6中對NAND FLASH的支持有新舊兩套代碼,新代碼在drivers/nand目錄下,舊代碼在driver/nand_legacy目錄下。本次移植選用新代碼,它移植自Lin-ux2.6.12,更加智能。移植過程分以下幾步。
(1)根據具體輸入時鐘,修改時鐘定義參數。SMDK2410開發板的默認時鐘為12 MHz。
(2)依照實際開發板的內存地址分配情況修改lowlevel init.S文件。
(3)針對S3C2410,S3C2440 NAND FLASH控制器的不同,修改接口參數。
(4)仿照內核支持NAND FLASH的文件來編寫片選函數。命令和控制函數,查詢狀態函數。
(5)根據具體NAND FLASH芯片設置時序參數。
(6)增加從NAND FLASH燒寫,讀取YAFFS2文件系統映像功能。
(7)修改Makefile文件,將新建文件編入U-Boot中。
在編寫燒寫YAFFS2文件系統映像的命令時,要注意YAFFS2文件系統映像里除了2 KB的數據外,后面還包括了64 B的OOB數據,所以映像文件大小是以2 112 B為單位。OOB中已經包含了ECC,在燒寫時不需要再計算ECC校驗碼。燒寫時,首先檢查是否為壞塊,是就跳過,然后寫入2 KB的數據,最后寫入64 B的OOB數據。還要增加對skipfirstblk參數的支持。使燒寫YAFFS2文件系統映像時,跳過分區上第一個塊,這是由YAFFS2文件系統特性決定的。
由于不使用ECC校驗碼,燒寫過程中會不斷提示以下信息:
Writing data without ECC to NAND-FLASH is not reeom-mended
可以修改driver/mtd/nand/nand base.C文件的nand_write_page函數,將輸出這條信息的命令去掉。
最后執行make XX_config和make all命令,生成的U-Boot.bin文件即可以運行與目標板上了。將它燒入NOR FLASH后啟動,在串口工具中能夠看到提示信息。輸入nand info命令即可查看到NAND FLASH的信息,說明U-Boot識別出了NAND FLASH。
3.2 嵌入式Linux內核移植
目前Linux內核還沒有正式支持YAFFS文件系統,所以需要通過補丁修改Linux內核,另外YAFFS文件系統也需要MTD設備驅動的支持。首先下載最新版本的2.6內核,這里以linux-2.6.29.4為例。盡管Linux 2.6并不是一個真正的實時操作系統,但其改進的特性能夠滿足系統響應需求。再下載YAFFS代碼包。內有YAFFS和YAFFS 2兩個文件夾。其中YAFFS已經不再維護,進入YAFFS2。文件夾內有patch-ker.sh補丁文件,使用以下命令將YAFFS2加入到Linux內核。
以上命令完成了三件事情:
(1)修改內核fs/Kconfig。增加一行:source”fs/YAFFS2/Kconfig”。
(2)修改內核fs/Kconfig。增加一行:ojb-MYM(CONFIG_YAFFS_FS)+=YAFFS2/。
(3)在內核fs/目錄下創建YAFFS2目錄;將YAFFS2源碼目錄下面的Makefile.kernel文件復制為內核fs/YAFFS2/Makefie;將YAFFS2源碼目錄的Kconfig文件復制到內核fs/YAFFS2目錄下;將YAFFS2源碼目錄下的*.C*.h文件復制到內核fs/YAFFS2目錄下。
進入內核目錄,修改makefile,并對內核進行默認配置進行修改,使其支持本開發板。
結合U-Boot信息修改NAND FLASH分區,使其兩者結構大小保持一致。注意分區的大小要以128 kB為單位。
根據具體NAND FLASH芯片特性,修改tacls,twrph0,twrphl的值。
修改arch/arm/tools/math-types文件,使其Linux內核的機器號與Bootloader傳遞來的參數一致。建立好交叉編譯環境,在環境變量PATH中添加交叉編譯工具路徑?;蛘咧苯釉趍akefile文件內添加修改也可以。使用make s3c2410_defconfig命令,將2410的默認配置文件寫到當前目錄下的.config。使用make me-nuconfig命令配置內核模塊的功能,要選中MTD和YAFFS2支持。在Boot options選項中增加以下語句。
使用make zImage命令,生成是zlmage映像文件。再用mkimage工具制作ulmage,uImage是U-Boot專用的映像文件,它在zImage之前加上一個長度為0x40的“頭”,說明這個映像文件的類型、加載位置、生成時間、大小等信息。
3.3 制作文件系統
嵌入式Linux系統都需要構建根文件系統,構建根文件系統的規則在文件系統層次標準(Filesystem Hi-erarchy Standard,FHS)文檔中。首先建立根文件系統目錄和動態鏈接庫,然后使用Busybox工具可以生成根文件系統所需的bin,sbin,usr目錄和linuxrc文件。Bosybox是一個遵循GPL v2協議的開源項目,它在編寫過程總對文件大小進行優化,并考慮了系統資源有限(比如內存等)的情況,為嵌入式系統提供了一個比較完整的工具集。
YAFFS2源代碼包內除了本身文件系統代碼外,utils 目 錄下還包含了 mkYAFFSimage/mkYAFFS2image的代碼,修改Makefile里的內核路徑編譯出mkYAFFSimage/mkYAFFS2image工具。其中mkYAFFSimage用于制作512 B的小頁YAFFS文件系統,mkYAFFS2image用于制作2 KB以上的大頁YAFFS2文件系統。輸入以下格式命令,制作出支持大頁的YAFFS2文件系統映像。
mkYAFFS2image MYM{PRJROOT}rootfs rootfs.YAFFS
通過mkYAFFS2image制做出來的映像文件其OOB中包含的ECC是使用YAFFS2/YAFFS ecc.c文件中的YAFFS ECCCaimJlate函數計算出來的
ECC校驗碼,其校驗算法和nand ecc.c文件內的nand_calculate_ecc函數校驗算法不同,如果在內核中由MTD來處理ECC,當讀取NAND FLASH中的數據時,會通過nand_calculate_ecc函數的算法再生成一個新的ECC校驗和,校驗的時候,將從OOB區中讀出的原ECC校驗和新ECC校驗和按位異或,其錯誤的結果會造成系統認為所有的頁面都是錯誤的。解決辦法有兩種,一是在內核編譯時把Lets YAFFS do itsown ECC選上,同時修改內核把MTD驅動中的ECC校驗關閉;二是修改mkYAFFS2image.c文件,使其制作image時使用nand_caleulate_ecc函數的校驗算法,在內核編譯時不要把Lets YAFFS do its own ECC選上,同時打開MTD驅動中的ECC校驗。
3.4 系統測試
啟動系統后,Bootloader首先運行,然后它將內核復制到內存中,并且在內存某個固定的地址設置好要傳遞給內核的參數,最后運行內核。內核啟動之后,它會將文件系統掛載為根文件系統,接著啟動文件系統中的應用程序。啟動途中會顯示如下信息:
以上信息說明系統已經找到NAND FLASH設備,并識別出分區。進入系統后,輸入下面命令。
在輸出結果中,顯示了YAFFS2的相關信息,說明Linux內核已經支持YAFFS2文件系統。
建立掛載點,掛載blockdevice設備。
查看mount上的目錄,可以看到該目錄下有剛才拷貝的文件,將其umount后,再次mount上來,發現拷貝的文件仍然存在,這時刪除該文件然后umount,再次mount后,發現拷貝的文件已經被刪除,說明該分區能正常讀/寫。
在FLASH上建立根文件系統:
重新啟動,改變啟動參數:
重新啟動,內核可以從NAND FLASH啟動根文件系統。
4 結語
大頁NAND FLASH的快速擦除、讀/寫性能滿足了系統對實時性的要求,YAFFS2可靠的掉電保護和高效率的讀寫以及對NAND FLASH存儲設備的保護等優勢增加了整個系統的安全性和健壯性,兩者的結合達到了裝備對數據的大容量存儲和管理的需求。目前,該系統已裝備于某部,用于實時監測裝備的戰技術狀況,以及長時間實時記錄裝備工作數據,用于事后分析評估裝備性能和操作手水平,在部隊作訓中發揮了重大作用。
責任編輯:gt
-
嵌入式
+關注
關注
5087文章
19148瀏覽量
306179 -
存儲
+關注
關注
13文章
4332瀏覽量
85953 -
操作系統
+關注
關注
37文章
6856瀏覽量
123438
發布評論請先 登錄
相關推薦
評論