摘要:主要介紹了基于嵌入式Linux的NAND Flash壞塊管理設計和實現(xiàn)方案,詳細闡述了壞塊映射表的建立、維護及其相關算法,同時分析了此壞塊算法在Linux內核及Bootloader中的具體應用。測試結果表明該算法能夠處理NANDFlash的相關壞塊問題,具有較高的穩(wěn)定性。
關鍵詞:NAND Flash;嵌入式IAnux;映射表;壞塊管理
在擁有諸多優(yōu)點的同時,NAND Flash由于生產(chǎn)工藝的問題,其在出廠時可能存在一定的壞塊。這些固有壞塊不能用于存儲數(shù)據(jù),已被產(chǎn)家標識好。另外,使用過程中由于讀寫次數(shù)增多,好塊也會變得不穩(wěn)定或失效,成為壞塊,這就是出廠后產(chǎn)生的壞塊。
NAND Flash在生產(chǎn)及使用過程中都有可能產(chǎn)生壞塊,這將使得系統(tǒng)變得不穩(wěn)定。應用中一般采用跳塊策略來管理壞塊,但它不能解決系統(tǒng)運行中產(chǎn)生的壞塊情況。針對此情形,本文提出基于嵌入式Linux系統(tǒng)平臺下的一種基于壞塊映射的NAND Flash壞塊管理的方案,并詳細介紹其相關映射算法和整套系統(tǒng)的相關壞塊管理流程。
1 壞塊管理層次結構
Linux下的MTD(Memory Technology Device)是用于管理ROM、Flash等內存設備的一層子系統(tǒng),它使編寫管理內存設備驅動變得更加簡單。
MTD子系統(tǒng)將Flash設備或其分區(qū)抽象為MTD設備,使底層驅動只需實現(xiàn)MTD設備,而向上層文件系統(tǒng)提供標準的接口,如MTD字符設備、MTD塊設備。
如圖1所示,本方案設計中,將壞塊管理層(BBMlayer)緊靠在驅動層之上MTD層之下,從而使得MTD層對壞塊不可見,并使壞塊的管理是基于整個芯片而不是某個分區(qū),便于上層文件系統(tǒng)實現(xiàn)損耗平衡。
BBM層基于驅動層提供的讀、寫、擦除相關操作實現(xiàn)接口read()、write()、erase()、read_oob()、write_oob()、isbad()、mark_bad()。對于其上層MTD子系統(tǒng)而言,關于壞塊的相關接口將不存在,物理介質類似于NORFlash。其中read_oob()、write_oob()接口為文件系統(tǒng)提供相關用途,如JFFS2的cleanmarker相關載體。
2 壞塊管理模塊的設計實現(xiàn)
2.1 壞塊管理原理
本文的設計的壞塊管理是基于壞塊映射原理的一種實現(xiàn)。在本壞塊映射的設計中,NAND Flash被劃分為基本空間和預留空間。基本空間為用戶看到的NANDFlash的總的存儲空間?;究臻g中的壞塊被映射到預留空間中的相應好塊?;居成潢P系如圖2所示。映射管理信息記錄在壞塊映射表中,它存儲在預留空間。
[!--empirenews.page--]
2.2 壞塊映射表的描述
在預留空間存在4種形式的塊:空閑的好塊、壞塊、被映射的塊、存放映射表的塊。
存放映射表的塊較為特殊,其中映射表不僅描述基本空間中的壞塊映射相關信息,還描述預留空間占整個Flash空間的比例等。
設計中一張壞塊表存于一個Flash塊,表的信息存于塊中最前面的相關頁中。表的頭部長度固定,表的整個長度可變,與壞塊數(shù)目相關。
壞塊映射表結構描述如下:
其中hdr_crc和tbl_crc用于檢驗表的完整性;rese_start_blk即預留空間的起始塊號;version用于標識該表的版本;num_bad_blk用于描述已發(fā)現(xiàn)的壞塊數(shù),即壞塊映射表項的數(shù)目;map_tbl為記錄壞塊映射表項內容的首地址。任何一個映射表項包括壞塊塊號及其映射的好塊的塊號。
由于使用過程中會產(chǎn)生新的壞塊,映射表中的表項需要增加,從而要更新Flash中的映射表。為了防止系統(tǒng)意外掉電產(chǎn)生映射表不一致問題,采用日志技術。其中version版本號標識映射表的新舊,在更新Flash映射表的同時,版本號遞增,同時Flash舊版本映射表并不立即擦除。只有出現(xiàn)預留空間不足的情況,擦除舊版本映射表的動作才執(zhí)行。此方案還有利于調試,查看映射表的更改歷史記錄。
在出現(xiàn)壞塊Bn后,通常包括兩個動作:寫映射表和標識壞塊。標識壞塊是通過在塊的00B相應字節(jié)寫非0xFF來實現(xiàn)。
為了支持意外掉電情形,每個版本的映射表必須在Flash里保存兩份,如果發(fā)現(xiàn)最高的版本映射表沒有兩份,或者兩份不一致,則屬于非正常情況,必須重新建立映射表。
考慮如下情況:寫完映射表Vn,接著標識壞塊Bn,此時掉電,則下次系統(tǒng)啟動后,出現(xiàn)映射表的壞快Bn,實際上并沒有被標識,導致不一致問題。寫2份Vn可以解決此問題:寫第一份Vn后,標識壞塊Bn,接著再寫第二份Vn。這樣即使在標識壞塊Bn時掉電,下次系統(tǒng)加電時由于沒有發(fā)現(xiàn)2份版本相同且最高的映射表,從而識別出此非正常情況。
同時,維護2份同版本壞塊表可以處理存放映射表的塊突然壞死而導致系統(tǒng)無法啟動的異常,起到備份的作用。
2.2.1 壞塊映射表的管理算法
系統(tǒng)初始化時讀入壞塊表的內容,在內存中建立所有壞塊的映射信息。由于每次發(fā)現(xiàn)新的壞塊而更新壞塊表時,都會寫入兩個版本一樣的壞塊表,所以在讀入壞塊表時就要檢查兩個表是否有效和一致,可以分為以下情況:
①發(fā)現(xiàn)2張最高版本并且有效的壞塊表Vn+1——系統(tǒng)按表Vn+1建立映射;
②只發(fā)現(xiàn)1張最高版本并且有效的壞塊表Vn+1,并且有2張有效壞塊表Vn——發(fā)生在上次寫完一個Vn+1后突然掉電,使得第二個表Vn+1未寫入或寫入不完整,這時需要恢復,以建立完整映射,恢復算法如圖3所示。[!--empirenews.page--]
③只發(fā)現(xiàn)一張最高版本并且有效地壞塊表Vn+1,并且有1張有效壞塊表Vn——發(fā)生在寫第二張Vn+1突然掉電,并且之前寫第二張Vn也發(fā)生掉電;
④僅發(fā)現(xiàn)一張壞塊表V0——發(fā)生在系統(tǒng)寫第二張V0時掉電,此時系統(tǒng)需重新掃描建立映射表V1;
⑤沒有發(fā)現(xiàn)任何壞塊表——系統(tǒng)最初狀態(tài);
⑥兩個完整的壞塊表Vn+1,但num_bad_blk不一樣——這種情況發(fā)生在更新第二個壞塊表Vn+1時,寫的時候出錯,產(chǎn)生一個新的壞塊,從而第二次更新的壞塊表Vn+1的壞塊數(shù)增加了。
對于情況①,只需在系統(tǒng)最初建立前建立好映射關系即可。
對于情況②,它經(jīng)常出現(xiàn)在系統(tǒng)在寫或者擦除Flash數(shù)據(jù)塊時突然斷電,導致數(shù)據(jù)或者ECC變化,從而Flash讀導致ECC不正確。實際上Fl-ash塊并沒有壞。根據(jù)此種情況,將首先為此塊分配一個映射塊,并把數(shù)據(jù)拷入映射塊。接著對此塊進行torture操作,如果發(fā)現(xiàn)它為好塊,則將之前映射操作撤銷,將數(shù)據(jù)重新拷入此好塊。如果此塊確實已壞,則將此塊標記為壞塊,并更新映射表。
對于情況③,分配一個新的映射塊,把有效數(shù)據(jù)寫入新塊,并建立映射信息。
對于情況④,分配一個新的映射塊,并將此塊查出,然后建立映射信息。
對于情況⑤,掃描整個Flash,建立映射表Vn、V0。
對于情況⑥,則采用壞塊多的映射表Vn+1,并用它更新Vn+2、Vn+2。
2.2.2 壞塊管理及上層接口實現(xiàn)
該模塊實現(xiàn)基于上節(jié)所述壞塊管理算法對Flash的所有有效塊的使用。它主要是處理運行中產(chǎn)生壞塊的情況,并讓上層程序屏蔽此信息。
NAND Flash的壞塊包含如下三種類型:
◆Flash上存在的出廠壞塊;
◆讀過程發(fā)生比特反轉而被視為的壞塊;
◆操作過程(讀,寫,擦除)中產(chǎn)生的新的壞塊。
對于此模塊主要完成后兩種動態(tài)壞塊類型的處理過程。對于出廠壞塊,只需在初始化時檢測出來并將其映射到一個好塊,以后的讀寫過程中對映射塊操作即可。
對于運行中產(chǎn)生的壞塊,從操作類型(讀、寫、擦除)來進行分別處理。
①讀過程中的比特反轉導致ECC錯誤,由于比特反轉是NAND工藝決定的,且是不可避免的隨機行為,所以不能簡單地根據(jù)ECC錯誤就將其當作壞塊處理。具體處理流程如圖4所示,通過torture操作判斷此“壞塊”已真正成為壞塊。
如果NAND Flash在執(zhí)行擦除或寫操作過程時發(fā)生斷電,則所操作的塊內的數(shù)據(jù)具有不確定性。下次讀該塊的內容時,可能發(fā)生無法糾正的ECC錯誤。為了能處理這種情況,圖4中的torture處理,其實現(xiàn)原理就是選擇一些數(shù)據(jù)寫入該塊,再讀出,如果不一致則該塊已變成壞塊。[!--empirenews.page--]
②寫過程中發(fā)生錯誤,則該塊成為壞塊。處理方法為:為其分配一個新的有效塊,將壞塊原有數(shù)據(jù)拷貝到有效塊,并同時寫入新的數(shù)據(jù),最后更新映射表,標識壞塊。寫操作的錯誤處理算法如圖5所示。
③擦除過程發(fā)生錯誤,則該塊成為壞塊。處理方法為:為其分配一個新的有效塊,并擦除此有效塊,更新映射表,標識壞塊。
2.3 BootIoader的壞塊管理
在Bootloader層采用Linux內核相同的壞塊管理策略,并復用相關代碼。Bootloader在內存建立起的壞塊映射表可以通過內存共享的方式,傳遞給Linux內核,從而減少內核重新掃描壞塊映射表的時間,加快系統(tǒng)啟動速度。
3 測試
Cases測試方法:對一切可能情況實行模擬測試,最后進行壓力測試。
3.1 壞塊場景模擬測試
①出廠壞塊;
②運行中產(chǎn)生壞塊:讀操作產(chǎn)生壞塊,寫操作產(chǎn)生壞塊,擦操作產(chǎn)生壞塊,比特反轉產(chǎn)生偽壞塊。
3.2 壞塊表一致性場景模擬
①2張相同Vn+1;
②1張Vn+1和2張相同Vn;
③1張Vn+1和1張Vn;
④1張Vn;
⑤沒有任何壞塊表;
⑥2張不相同的Vn+1。
3.3 壓力測試
系統(tǒng)不間斷運行10天后,工作狀態(tài)仍然正常。
3.4 文件系統(tǒng)測試
系統(tǒng)能夠支持對壞塊敏感的文件系統(tǒng)squashfs、cramfs,其測試案例均通過。這表明該壞塊管理方法能有效管理NAND Flash。
4 總結
本文提出了一種基于嵌入式Linux整套系統(tǒng)的NAND Flash壞塊管理實現(xiàn)方案,并詳細介紹其壞塊映射算法。此方案目前已經(jīng)應用到數(shù)字電視開發(fā)平臺。在系統(tǒng)平臺上的相關壞塊動態(tài)產(chǎn)生、突然掉電等大量測試表明此方案穩(wěn)定可靠。