閃存在嵌入式Linux系統(tǒng)中的應用
Linux系統(tǒng)自誕生以來,不斷發(fā)展壯大,支持越來越多的硬件體系,獲得了日益廣泛的應用,從服務器、桌面計算,到機頂盒、手機、路由器等,可以說無處不在。雖然都是Linux系統(tǒng),但是嵌入式環(huán)境和通用計算環(huán)境中的軟件/硬件配置大不相同。這是因為嵌入式系統(tǒng)大多都是為某一專門應用而特別設計的,有可能需要耐受各種惡劣環(huán)境(比如意外斷電、極端溫度、強沖擊/振動/輻射等),還受到體積、功耗、成本等諸多因素的限制,功能針對性強,需要酌情增加一些專用的硬件(如各種傳感器和專用接口),而許多通用計算機上常用的外設在嵌入式系統(tǒng)中不那么常見,典型的例子是硬盤、CD/DVD-ROM等大容量的非易失存儲設備,在嵌入式系統(tǒng)中,它們通常被各種形式的閃存所取代。閃存的存儲特性與硬盤等存儲設備的巨大差異,導致它必須使用專用存儲控制器、驅動程序及文件系統(tǒng)。對不同類型閃存及相應文件系統(tǒng)的選用,會影響最終形成系統(tǒng)的性能和穩(wěn)定性,必須綜合各種系統(tǒng)構件的特點及目標系統(tǒng)的需求做出慎重的抉擇。
1 閃存類型及特性
嵌入式系統(tǒng)中常用的閃存有兩類:NORFLASH和NANDFLASH。它們因內部結構與“或非”及“與非”門相似而得名。它們不僅在內部結構上不同,外部特性和應用也不一樣。NORFLASH的容量通常不大,常見的只有幾MB,可以重復擦寫10萬次到100萬次。NORFLASH遵循CFI標準,可以通過CFI命令查詢其制造商、器件型號、容量、內部扇區(qū)布局等參數(shù),實現(xiàn)軟件自動配置。NORFLASH的優(yōu)勢還在于它在出廠時能保證每個數(shù)據(jù)位都是有效的,不需要做壞塊處理。NORFLASH的線性尋址特性使之可以作為啟動存儲器使用。與NORFLASH相比,NANDFLASH的容量可以做得很大,常見的有幾十MB到幾GB,可以重復擦寫10萬次。NANDFLASH芯片上沒有地址與數(shù)據(jù)線之分,只有復用的I/O線和命令鎖存(CLE)、地址
鎖存(ALE)、讀/寫使能(RE,WE)和片選(CE)等控制線,必須通過特定的邏輯來操作。NANDFLASH不支持線性尋址,一般不能用作啟動ROM。但這也不是絕對的。有些微控制器(如AT91SAM926x)提供出廠前固化在芯片內部的BOOT-ROM,并在BOOT-ROM中提供對NANDFLASH啟動的支持。不過這樣一來,首先啟動的是BOOT-ROM中的程序,會產生啟動邏輯和延時方面的種種問題,設計時需要全面考慮。另外,生產廠商不保證NAND-FLASH中每一個數(shù)據(jù)位都是有效的,除芯片中的第一塊之外,允許有“初始壞塊”,并約定在壞塊的第一頁或第二頁帶外區(qū)(OOB)的特定位置標記壞塊。NANDFLASH還允許在使用過程中出現(xiàn)新的壞塊,以及非壞塊在讀出過程中出錯?;谶@些特點,使用這種閃存時要做額外的壞塊管理和校驗/糾錯工作。在寫入密集型系統(tǒng)中,必須提供ECC及壞塊換出算法,才能達到10萬次的寫入指標。
除了以上提到的兩種閃存之外,還有一種由NORFLASH衍生的串行閃存,通常是SPI接口。這種閃存繼承了NORFLASH沒有壞塊的優(yōu)點,但不支持CFI標準,并且由于是串行接口,線性尋址沒有意義,為了方便操作,有些產品中加入了類似NANDFLASH的塊/頁結構及基于片內SRAM的頁緩存,其優(yōu)勢在于硬件接口簡單,提供小尺寸的封裝,可以顯著減小PCB面積和布線復雜程度。
另外,基于NANDFLASH技術的串行閃存已經量產,使用的也是SPI接口,容量可以做到1Gb。
2 應用設計
目標應用系統(tǒng)是一臺專用的戶外顯示設備,要求其具有低功耗、抗振、寬溫操作及高可靠性等特點。為此,選擇了AT91SAM9261/AT91-SAM9G10,它是以ARM9為核心的集成片上液晶控制器的工業(yè)級微控制器,以DATA FLASH/NORFLASH和NANDFLASH存儲固件代碼和數(shù)據(jù)。在設計過程中,根據(jù)不同的閃存使用需求,采取了具有針對性的方案。[!--empirenews.page--]
2.1 啟動設計
在該系統(tǒng)中,結合微控制器提供的功能和各種閃存的特點,可以綜合使用不同類型的閃存,選擇不同的啟動方式。AT91SAM9261內部集成了啟動ROM,其中固化了支持啟動和操作閃存的程序。流程圖如圖1所示。當AT91SAM9261的啟動模式選擇(BMS)引腳在復位期間為高電平時,會運行內部固化的啟動程序;否則運行外部NORFLASH中的程序。從流程圖中可以看出,啟動程序支持從串行閃存中啟動。這是通過啟動程序將串行閃存中的代碼加載到內部SRAM中實現(xiàn)的。由于內部SRAM容量有限(依芯片型號不同,有16 KB和160 KB兩種),像U-BOOt(編譯后有170KB
左右,與配置有關)這樣的功能,若較全面地啟動加載程序(Bootloader)是不能直接從串行閃存中啟動的,而只能選擇兩級啟動程序,先從串行閃存中加載一段盡可能小的一級啟動程序(通常只有4~5 KB).用于初始化關鍵的硬件(如SDRAM控制器。由于時序、數(shù)據(jù)線寬等參數(shù)是可變的,不可能在AT91SAM9261內部固化的啟動程序中提供通用的SDRAM控制器初始化代碼),然后再由一級啟動程序把功能較全面的二級啟動程序載入到容量足夠大的SDRAM中運行,以啟動系統(tǒng)。從NORFLASH啟動時會跳過AT91SAM9261內部固化的啟動程序,系統(tǒng)復位后執(zhí)行的第一條指行就是NORFLASH中的。此時,啟動程序可以只有1級,當然,為了使軟件和串行閃存啟動方式有較好的兼容性,也仍然可以采用兩級啟動程序,這樣只需簡單修改第一級啟動程序即可適用于兩種不同的硬件啟動配置,為硬件設計留下更多的選擇空間。由于AT91SAM9261本身的原因,從NORFLASH啟動是實現(xiàn)寬溫工作的惟一選擇(AT91SAM9G10無此問題)。圖2顯示了不同的啟動配置。
在這個AT91SAM9261系統(tǒng)中,分別采用了2 MB的DATAFLASH或2 MB的NORFLASH作為啟動存儲器,由BMS引腳選擇具體使用何種啟動方式。閃
存中的地址劃分如圖3所示,其中的bootstrap是第一級啟動程序;U-Boot是第二級啟動程序。
2.2 系統(tǒng)內核及應用程序文件系統(tǒng)映像
系統(tǒng)內核映像和各MTD分區(qū)的文件系統(tǒng)映像大小在幾MB到幾十MB不等,需要存儲在容量較大的NANDFLASH中。對于系統(tǒng)內核,由于做了適當?shù)牟脺p,其長度不大,和初始根文件系統(tǒng)加在一起不過幾MB,如果不在乎稍長的啟動時間,還可以對它使用gzip壓縮,大幅度減小其尺寸。在使用U-Boot作為啟動程序的系統(tǒng)中,由于U-Boot具有直接讀取NANDFLASH塊/頁的能力,不需要使用文件系統(tǒng),將內核映像直接寫到閃存塊里。[!--empirenews.page--]
應用程序及其所需的庫文件、資源文件等,作為獨立的文件系統(tǒng)映像掛載,在此選擇了帶有壓縮及去除重復文件功能的只讀文件系統(tǒng),即SqLrashFS(SquashFs文件系統(tǒng)已經被廣泛用于各種Linux Live CD形式的發(fā)行版中,被充分證明是可靠的,并且從Linux 2.6.29版開始,它已加入到系統(tǒng)核心源碼)。在嵌入式系統(tǒng)中,使用只讀文件系統(tǒng)有許多好處,比如掛載時間短,不受掉電影響,不必在系統(tǒng)運行過程中處理壞塊及平衡損耗等。在使用過程中由于不涉及寫入,其可靠性優(yōu)于可寫的文件系統(tǒng)。
在此目標系統(tǒng)中,內核和初始根文件系統(tǒng)的U-Boot映像約為2.8 MB,應用程序、GUI子系統(tǒng),以及應用程序運行過程中所需的圖形和字體文件的SquashFS映像約為12 MB。系統(tǒng)中使用的NANDFLASH是一片總容量為64 MB的8位數(shù)據(jù)線寬的芯片,塊容量是16 KB+512 B,頁容量是512 B+16 B,其屬于塊尺寸較小的那種,與大塊NANDFLASH相比,操作命令稍有區(qū)別,在驅動程序中需要區(qū)別對待。該系統(tǒng)中的MTD分區(qū)結構如表1所示。
2.3 應用程序對閃存的使用
大多數(shù)情況下,僅提供對閃存的只讀操作是不夠的。比如,U-Boot至少在更新其自身以及保存環(huán)境變量時需要寫閃存;操作系統(tǒng)在記錄日志時要寫閃存;應用程序在保存用戶配置及工作數(shù)據(jù)時也要寫閃存。對于啟動加載程序來說,問題不是很嚴重。因為系統(tǒng)處于更新及配置狀態(tài)時,大多是脫離正常工作狀態(tài)的,且由專人操作,操作中途發(fā)生異常情況(如掉電)的可能性不大,即使發(fā)生了,也會被及時發(fā)現(xiàn)和處理。對于系統(tǒng)日志,在嵌入式系統(tǒng)中可以將其關閉,以減少對閃存的寫操作。應用程序對閃存的寫操作是不可避免的,而且處于設備自動工作期間,需要應對各種偶然發(fā)生的異常狀況,特別是意外掉電。
在Linux系統(tǒng)中,通過文件系統(tǒng)訪問閃存是順理成章的做法。目前支持NANDFLAsH的常用文件系統(tǒng)有YAFFS/YAFFS2,JFFS2和UBIFS等。它們都是記帳式的文件系統(tǒng),各有特點,也有不足。
YAFFS/YAFFS2是專為NANDFLASH寫的文件系統(tǒng)。在YAFFS的代碼里包括管理閃存帶外區(qū)(OOB)的部分,而這部分代碼一般認為屬于設備驅動的范疇,其他文件系統(tǒng)里是不含這部分代碼的。YAFFS是一種穩(wěn)鍵的記帳結構的文件系統(tǒng)。高效率是它追求的另一個目標。它可以用在各種操作系統(tǒng)中(已用于Linux,WinCE,pSOS,eCos,ThreadX及各種專用操作系統(tǒng)中),甚至可以在沒有操作系統(tǒng)的環(huán)境下工作。YAFFS2支持“檢查點(checkpoints)”,以避免掛載過程中耗時的掃描操作,實現(xiàn)快速掛載。
相對于JFFS,JFFS2有了一些改進,可以支持硬連接(hard Links),垃圾回收更有效,平衡損耗更均勻。但它在掛載時仍需要掃描尋找最新版本的閃存塊,并建立RAM中的數(shù)據(jù)結構,文件系統(tǒng)越大,掛載時間越長,RAM開銷也越大。雖然JFFS2已經通過小結節(jié)點技術減少了掛載時間,但結果仍不理想,掛載時間是s級的。
UBIFS是JFFS2的后繼(原來稱作JFFS3),第1個穩(wěn)定版本于2008年10月加入到Linux 2.6.27版核心中,它有一個競爭者叫LogFS。UBIFS與JFFS2的最大不同在于它的文件索引信息是寫在閃存中的,而JFFS2是暫存在RAM中的。因此,UBIFS在掛載時不需要掃描全部閃存空間,掛載耗時很短(ms級);UBIFS對RAM的消耗不會隨著文件系統(tǒng)的尺寸變大而線性增長,適用于大容量的文件系統(tǒng)。
除這這些不同之外,各種閃存文件系統(tǒng)也存在一些共性。由于閃存的寫入次數(shù)有限,為了避免局部因頻繁寫入而過早失效,必須使寫入操作盡量均勻分布到所有位置上,即平衡損耗(wear leveling)。這導致了更新文件時必須做異位更新,而不能像在磁盤或RAM中那樣簡單地原位更新,從而引起一系列復雜的問題。首先,異位更新會導致閃存塊中出現(xiàn)越來越多的過期頁面,它們與有效頁面混雜在一起,形成所謂的臟塊(dirty blocks)。當所有的閃存塊都成為臟塊后,就沒有閃存塊可供擦除再分配了。因此,基于閃存的文件系統(tǒng)都有垃圾回收器,用于將分散的過期頁面集中在一起,形成空閃存塊(free blocks)。由此引起的另一個問題是文件系統(tǒng)在使用時不能用到接近填滿,否則也會導致類似的問題。其次,樹狀結構的文件索引中存在大量的互相引用,某個節(jié)點的改變會引起該節(jié)點本身及直接和間接引用它的一系列節(jié)點的異位更新。
從以上的分析可以看出,NANDFLASH上的文件系統(tǒng)是一把雙刃劍。它確實可以提供清晰的軟件層次和使用上的方便,但同時也會降低操作效率,并具有潛在的可靠性問題。關鍵是如何合理使用,揚長避短。其實,對于寫入量小(一個擦除塊之內),并且不頻繁的數(shù)據(jù),可以跳過文件系統(tǒng),通過ioctrl()函數(shù)直接操作閃存。這樣做的缺點是破壞了軟件層次,要求應用軟件開發(fā)人員了解一部分硬件的細節(jié),在應用程序中完成一些本應屬于驅動程序的底層功能(如塊擦除,發(fā)現(xiàn)和標記壞塊等);優(yōu)點是可以拋開復雜的文件系統(tǒng),不需要掛載及卸載,更不存在文件系統(tǒng)的完整性問題,平衡損耗等措施可以視需要取舍,尤其在意外掉電時,該方法可將所有的讀/寫錯誤都限制在相對較小的局部,具有較好的應對掉電的能力。[!--empirenews.page--]
2.4 閃存燒寫支持
系統(tǒng)中的各種閃存可以用不同的方法寫入數(shù)據(jù),各種方法都有優(yōu)缺點。可供選擇的方法主要有兩種:在芯片焊接前用通用的編程器燒寫;在芯片焊接后進行在系統(tǒng)燒寫(ISP)。使用通用的編程器可以快速大量地燒寫芯片,適合大批量生產,但芯片一旦焊到印制板上,這
種方法就不能用了。在系統(tǒng)編程(ISP)適合燒寫已經焊在印制板上的芯片,通常1次只能寫1塊板子,但是不需要專用的設備,只要有1臺計算機和相應的連接電纜(如USB電纜)及配套軟件就可以工作,非常適合小批量生產和軟件升級。另外,通過ISP軟件提供的硬件寄存器讀/寫和目標存儲器讀/寫功能,還可以實現(xiàn)一定程度上的電路板測試和調試功能。
具體到AT91系列芯片可以借助芯片內固化的SAM-BA BOOT(見圖1)提供的支持,通過USB或調試串口燒寫系統(tǒng)中的閃存,尤其是通過USB燒寫十分方便快捷,燒寫Linux核心映像到NANDFLASH只需要幾秒。對于AT91SAM9261,使用這種編程方式需要滿足幾個條件:
(1)AT91SAM9261的BMS引腳在復位期間保持高電平;
(2)SPl0的CS0對應的芯片不存在,或者對應的芯片中不存在有效的啟動代碼;
(3)PC機與目標板之間通過串口或USB口連接;
(4)PC機上安裝SAM-BA工具軟件。
PC機上的SAM-BA工具軟件可以支持對目標系統(tǒng)多種存儲器的讀/寫,默認情況下可以支持DATAFLASH,NANDFLASH、內部SRAM和外部SDRA-M。尤其是對DATAFLASH的支持非常不錯,可以自動識別各種不同容量的芯片,寫入速度也比較快。但是它對NANDFLASH的支持并不理想,對于某些NANDFLASH芯片,操作會失敗。對于NORFLASH,則根本不提供現(xiàn)成的支持。不過它提供了基于COM技術的動態(tài)庫,并且公開了編程接口,可以使用C/C++程序或TCL腳本控制燒寫過程,對于不提供官方支持的芯片,可以自行編寫代碼擴展的SAMBA的功能。以擴展NORFLASH編程功能為例,需要自行編寫的有以下部分:
(1)下載到目標板上運行的ARM代碼。這部分程序在SAM-BA v2.4中稱為monitor,在SAM-BA v2.8中稱為applet,其實就是供芯片內固化的SAMBA B00T調用的功能擴展部分;
(2)PC機上的TCL腳本或C/C++程序。用于初始化硬件(如SDRAM控制器),向目標板下載monitor/applet,以及傳送目標程序代碼和控制燒寫過程。
如果使用TCL腳本,在相關腳本更改完成后,運行SAMBA工具軟件,會出現(xiàn)新添加的NORFLASH標簽頁,如圖4所示。在擴展的各部分功能基礎之上,還可以編寫一個綜合性的自動化腳本,將所有的程序代碼及數(shù)據(jù)(如Bootstrap,U-Boot,U-Boot的環(huán)境變量、內核映像、各分區(qū)的文件系統(tǒng)映像等)一次性寫入目標板上不同芯片內的各個指定地址,以簡化編程操作,提高生產效率。
3 結語
閃存是目前嵌入式系統(tǒng)中廣泛應用的非易失存儲介質,具有可以重復寫入和存儲容量大等優(yōu)點,但是也存在寫入次數(shù)有限,操作稍顯復雜和速度慢等缺陷。若使用不當,會引起性能和可靠性方面的問題。通過深入分析現(xiàn)有閃存相關的硬件、軟件特點,在系統(tǒng)中按需要采取具有針對性的應用方式,設計的系統(tǒng)在閃存應用方面獲得了較好的效果:系統(tǒng)啟動時間較短,工作穩(wěn)定,順利通過了高溫老化試驗及長達數(shù)月的現(xiàn)場應用考驗。另外,采用自動化腳本與監(jiān)控程序結合的閃存燒寫設計,不僅簡化了生產過程,還提供了一定程度上硬件調試的支持。