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