本文主要是關(guān)于nand和nor的相關(guān)介紹,并著重對(duì)nand和nor進(jìn)行了詳盡的對(duì)比區(qū)分。
NOR Flash
它是現(xiàn)在市場(chǎng)上兩種主要的非易失閃存技術(shù)之一。Intel于1988年首先開發(fā)出NOR Flash 技術(shù),徹底改變了原先由EPROM(Erasable Programmable Read-Only-Memory電可編程序只讀存儲(chǔ)器)和EEPROM(電可擦只讀存儲(chǔ)器Electrically Erasable Programmable Read - Only Memory)一統(tǒng)天下的局面。緊接著,1989年,東芝公司發(fā)表了NAND Flash 結(jié)構(gòu),強(qiáng)調(diào)降低每比特的成本,有更高的性能,并且像磁盤一樣可以通過接口輕松升級(jí)。NOR Flash 的特點(diǎn)是芯片內(nèi)執(zhí)行(XIP ,eXecute In Place),這樣應(yīng)用程序可以直接在Flash閃存內(nèi)運(yùn)行,不必再把代碼讀到系統(tǒng)RAM中。NOR 的傳輸效率很高,在1~4MB的小容量時(shí)具有很高的成本效益,但是很低的寫入和擦除速度大大影響到它的性能。NAND的結(jié)構(gòu)能提供極高的單元密度,可以達(dá)到高存儲(chǔ)密度,并且寫入和擦除的速度也很快。應(yīng)用NAND的困難在于Flash的管理需要特殊的系統(tǒng)接口。通常讀取NOR的速度比NAND稍快一些,而NAND的寫入速度比NOR快很多,在設(shè)計(jì)中應(yīng)該考慮這些情況。——《ARM嵌入式Linux系統(tǒng)開發(fā)從入門到精通》 李亞峰 歐文盛 等編著 清華大學(xué)出版社 P52 注釋 API Key
NOR和NAND是現(xiàn)在市場(chǎng)上兩種主要的非易失閃存技術(shù)。Intel于1988年首先開發(fā)出NOR flash技術(shù),徹底改變了原先由EPROM和EEPROM一統(tǒng)天下的局面。緊接著,1989年,東芝公司發(fā)表了NAND flash結(jié)構(gòu),強(qiáng)調(diào)降低每比特的成本,更高的性能,并且象磁盤一樣可以通過接口輕松升級(jí)。但是經(jīng)過了十多年之后,仍然有相當(dāng)多的硬件工程師分不清NOR和NAND閃存。
像“flash存儲(chǔ)器”經(jīng)??梢耘c相“NOR存儲(chǔ)器”互換使用。許多業(yè)內(nèi)人士也搞不清楚NAND閃存技術(shù)相對(duì)于NOR技術(shù)的優(yōu)越之處,因?yàn)榇蠖鄶?shù)情況下閃存只是用來存儲(chǔ)少量的代碼,這時(shí)NOR閃存更適合一些。而NAND則是高數(shù)據(jù)存儲(chǔ)密度的理想解決方案。
NOR的特點(diǎn)是芯片內(nèi)執(zhí)行(XIP, eXecute In Place),這樣應(yīng)用程序可以直接在flash閃存內(nèi)運(yùn)行,不必再把代碼讀到系統(tǒng)RAM中。NOR的傳輸效率很高,在1~4MB的小容量時(shí)具有很高的成本效益,但是很低的寫入和擦除速度大大影響了它的性能。
NAND結(jié)構(gòu)能提供極高的單元密度,可以達(dá)到高存儲(chǔ)密度,并且寫入和擦除的速度也很快。應(yīng)用NAND的困難在于flash的管理需要特殊的系統(tǒng)接口。
接口差別
NOR flash帶有SRAM接口,有足夠的地址引腳來尋址,可以很容易地存取其內(nèi)部的每一個(gè)字節(jié)。
NAND器件使用復(fù)雜的I/O口來串行地存取數(shù)據(jù),各個(gè)產(chǎn)品或廠商的方法可能各不相同。8個(gè)引腳用來傳送控制、地址和數(shù)據(jù)信息。
NAND讀和寫操作采用512字節(jié)的塊,這一點(diǎn)有點(diǎn)像硬盤管理此類操作,很自然地,基于NAND的存儲(chǔ)器就可以取代硬盤或其他塊設(shè)備。
容量成本
NAND flash的單元尺寸幾乎是NOR器件的一半,由于生產(chǎn)過程更為簡(jiǎn)單,NAND結(jié)構(gòu)可以在給定的模具尺寸內(nèi)提供更高的容量,也就相應(yīng)地降低了價(jià)格。
NOR flash占據(jù)了容量為1~16MB閃存市場(chǎng)的大部分,而NAND flash只是用在8~128MB的產(chǎn)品當(dāng)中,這也說明NOR主要應(yīng)用在代碼存儲(chǔ)介質(zhì)中,NAND適合于數(shù)據(jù)存儲(chǔ),NAND在CompactFlash、Secure Digital、PC Cards和MMC(多媒體存儲(chǔ)卡Multi Media Card)存儲(chǔ)卡市場(chǎng)上所占份額最大。
nand和nor區(qū)別
閃存芯片讀寫的基本單位不同
應(yīng)用程序?qū)OR芯片操作以“字”為基本單位。為了方便對(duì)大容量NOR閃存的管理,通常將NOR閃存分成大小為128KB或者64KB的邏輯塊,有時(shí)候塊內(nèi)還分成扇區(qū)。讀寫時(shí)需要同時(shí)指定邏輯塊號(hào)和塊內(nèi)偏移。應(yīng)用程序?qū)AND芯片操作是以“塊”為基本單位。NAND閃存的塊比較小,一般是8KB,然后每塊又分成頁(yè),頁(yè)的大小一般是512字節(jié)。要修改NAND芯片中一個(gè)字節(jié),必須重寫整個(gè)數(shù)據(jù)塊。
2)NOR閃存是隨機(jī)存儲(chǔ)介質(zhì),用于數(shù)據(jù)量較小的場(chǎng)合;NAND閃存是連續(xù)存儲(chǔ)介質(zhì),適合存放大的數(shù)據(jù)。
3) 由于NOR地址線和數(shù)據(jù)線分開,所以NOR芯片可以像SRAM一樣連在數(shù)據(jù)線上。NOR芯片的使用也類似于通常的內(nèi)存芯片,它的傳輸效率很高,可執(zhí)行程序可以在芯片內(nèi)執(zhí)行( XI P, eXecute In Place),這樣應(yīng)用程序可以直接在flash閃存內(nèi)運(yùn)行,不必再把代碼 讀到系統(tǒng)RAM中。由于NOR的這個(gè)特點(diǎn),嵌入式系統(tǒng)中經(jīng)常將NOR芯片做啟動(dòng)芯片使用。而NAND共用地址和數(shù)據(jù)總線,需要額外聯(lián)結(jié)一些控制的輸入輸出,所以直接將NAND芯片做啟動(dòng)芯片比較難。
4) N AN D閃存芯片因?yàn)楣灿玫刂泛蛿?shù)據(jù)總線的原因,不允許對(duì)一個(gè)字節(jié)甚至一個(gè)塊進(jìn)行的數(shù)據(jù)清空,只能對(duì)一個(gè)固定大小的區(qū)域進(jìn)行清零操作;而NOR芯片可以對(duì)字進(jìn)行操作。所以在處理小數(shù)據(jù)量的I/O操作的時(shí)候的速度要快與NAND的速度。比如一塊NOR芯片通 常寫一個(gè)字需要10微秒,那么在32位總線上寫512字節(jié)需要1280毫秒;而NAND閃存寫512字節(jié)需要的時(shí)間包括:512×每字節(jié)50納秒+10微秒的尋頁(yè)時(shí)間+200微秒的片擦寫時(shí)間=234微秒。
5)NAND閃存的容量比較大,目前最大容量己經(jīng)達(dá)到8G字節(jié)。為了方便管理,NAND的存儲(chǔ)空間使用了塊和頁(yè)兩級(jí)存儲(chǔ)體系,也就是說閃存的存儲(chǔ)空間是二維的,比如K9F5608UOA閃存塊的大小為16K,每頁(yè)的大小是512字節(jié),每頁(yè)還16字節(jié)空閑區(qū)用來存放錯(cuò)誤校驗(yàn)碼空間(有時(shí)也稱為out-of-band,OOB空間);在進(jìn)行寫操作的時(shí)候NAND閃存每次將一個(gè)字節(jié)的數(shù)據(jù)放入內(nèi)部的緩存區(qū),然后再發(fā)出“寫指令”進(jìn)行寫操作。由于對(duì)NAND閃存的操作都是以塊和頁(yè)為單位的,所以在向NAND閃存進(jìn)行大量數(shù)據(jù)的讀寫時(shí),NAND的速度要快于NOR閃存。
6)NOR閃存的可靠性要高于NAND閃存,這主要是因?yàn)镹OR型閃存的接口簡(jiǎn)單,數(shù)據(jù)操作少,位交換操作少,因此可靠性高,極少出現(xiàn)壞區(qū)塊,因而一般用在對(duì)可靠性要求高的地方。相反的,NAND型閃存接口和操作均相對(duì)復(fù)雜,位交換操作也很多,關(guān)鍵性數(shù)據(jù)更是需安錯(cuò)誤探測(cè)/錯(cuò)誤更正〔EDC/ECC)算法來確保數(shù)據(jù)的完整性,因此出現(xiàn)問題的幾率要大得多,壞區(qū)塊也是不可避免的,而且由于壞區(qū)塊是隨機(jī)分布的,連糾錯(cuò)也無法做到。
7)NAND Flash一般地址線和數(shù)據(jù)線共用,對(duì)讀寫速度有一定影響;而NOR Flash閃存數(shù)據(jù)線和地址線分開,所以相對(duì)而言讀寫速度快一些。
NAND和NOR芯片的共性首先表現(xiàn)在向芯片中寫數(shù)據(jù)必須先將芯片中對(duì)應(yīng)的內(nèi)容清空,然后再寫入,也就是通常說的“先擦后寫”。只不過NOR芯片只用擦寫一個(gè)字,而NAND需要擦寫整個(gè)塊。其次,閃存擦寫的次數(shù)都是有限的。當(dāng)閃存的使用接近使用壽命的時(shí)候,經(jīng)常會(huì)出現(xiàn)寫操作失敗;到達(dá)使用壽命時(shí),閃存內(nèi)部存放的數(shù)據(jù)雖然可以讀,但是不能再進(jìn)行寫操作了所以為了防止上面問題的發(fā)生,不能對(duì)某個(gè)特定的區(qū)域反復(fù)進(jìn)行寫操作。通常NAND的可擦寫次數(shù)高于NOR芯片,但是由于NAND通常是整塊擦寫,塊內(nèi)的頁(yè)面中如果有一位失效整個(gè)塊就會(huì)失效,而且由于擦寫過程復(fù)雜,失敗的概率相對(duì)較高,所以從整體上來說NOR的壽命較長(zhǎng)。
另一個(gè)共性是閃存的讀寫操作不僅僅是一個(gè)物理操作,實(shí)際上在閃存上存放數(shù)據(jù)必須使用算法實(shí)現(xiàn),這個(gè)模塊一般在驅(qū)動(dòng)程序的MTD‘ (Memory Technology Drivers)模塊中或者在FTLZ (Flash Translation Layer)層內(nèi)實(shí)現(xiàn),具體算法和芯片的生產(chǎn)廠商以及芯片型號(hào)有關(guān)系。
從使用角度來看,NOR閃存與NAND閃存是各有特點(diǎn)的:(1)NOR的存儲(chǔ)密度低,所以存儲(chǔ)一個(gè)字節(jié)的成本也較高,而NAND閃存的存儲(chǔ)密度和存儲(chǔ)容量均比較高;(2)NAND型閃存在擦、寫文件(特別是連續(xù)的大文件)時(shí)速度非???,非常適用于順序讀取的場(chǎng)合,而NOR的讀取速度很快,在隨機(jī)存取的應(yīng)用中有良好的表現(xiàn)。 NOR與NAND各有所長(zhǎng),但兩種優(yōu)勢(shì)無法在一個(gè)芯片上得到體現(xiàn)。所以,設(shè)計(jì)人員在選用芯片時(shí),只能趨其利而避其害,依照使用目的和主要功能在兩者之間進(jìn)行適當(dāng)?shù)倪x擇。
NAND與NOR技術(shù)的比較
一般的原則是:在大容量的多媒體應(yīng)用中選用NAND型閃存,而在數(shù)據(jù)/程序存貯應(yīng)用中選用NOR型閃存。根據(jù)這一原則,設(shè)計(jì)人員也可以把兩種閃存芯片結(jié)合起來使用,用NOR芯片存儲(chǔ)程序,用NAND芯片存儲(chǔ)數(shù)據(jù),使兩種閃存的優(yōu)勢(shì)互補(bǔ)。事實(shí)上,這種聰明的設(shè)計(jì)早已普遍應(yīng)用于手機(jī)、PocketPC、PDA及電子詞典等設(shè)備中了。
在選擇存儲(chǔ)解決方案時(shí),設(shè)計(jì)師必須在多種因素之間進(jìn)行權(quán)衡,以獲得較高的性價(jià)比。以手機(jī)為例,采用支持XIP技術(shù)的NOR閃存能夠直接運(yùn)行OS,速度很快,既簡(jiǎn)化了設(shè)計(jì),又降低了成本,所以許多手機(jī)都采用NOR+RAM的設(shè)計(jì)。NOR閃存的不足之處是存儲(chǔ)密度較低,所以也有采用NAND+RAM的設(shè)計(jì)。對(duì)于這兩種方案,很難說哪一種更好,因?yàn)槲覀儾荒茈x開具體的產(chǎn)品而從某一個(gè)方面單純地去評(píng)價(jià)。追求小巧優(yōu)雅的手機(jī)將需要NOR閃存支持;追求大存儲(chǔ)容量的手機(jī)則將更多地選擇NAND閃存;而同時(shí)追求功能和速度的手機(jī)則會(huì)采用NOR+NAND+RAM的設(shè)計(jì),這種取長(zhǎng)補(bǔ)短的設(shè)計(jì)能夠發(fā)揮NOR和NAND各自的優(yōu)勢(shì)。
除了速度、存儲(chǔ)密度的因素,設(shè)計(jì)師在選擇閃存芯片時(shí),還需要考慮接口設(shè)計(jì)、即插即用設(shè)計(jì)和驅(qū)動(dòng)程序等諸多問題,因?yàn)閮煞N類型的閃存在上述幾個(gè)方面也有很多的不同。譬如在驅(qū)動(dòng)程序方面,NOR器件運(yùn)行代碼不需要任何的軟件支持,而在NAND器件上進(jìn)行同樣操作時(shí)就需要存儲(chǔ)技術(shù)驅(qū)動(dòng)程序(MTD)的支持。雖然NAND和NOR器件在進(jìn)行寫入和擦除操作時(shí)都需要MTD,但對(duì)于NAND來說驅(qū)動(dòng)程序的開發(fā)難度更大,因?yàn)镹AND閃存的糾錯(cuò)和壞塊處理功能都需要通過驅(qū)動(dòng)程序來實(shí)現(xiàn)。
使用性差異
在使用性上體現(xiàn)出的差異也是與NOR和NAND自身的架構(gòu)設(shè)計(jì)分不開的,首先在接口方面,NOR的設(shè)計(jì)有明顯的傳統(tǒng)閃存的特征,因此實(shí)際應(yīng)用起來相對(duì)于NAND全新的復(fù)雜I/O設(shè)計(jì)要容易得多。而且,在使用NAND閃存時(shí),必須先寫入驅(qū)動(dòng)程序,才能繼續(xù)執(zhí)行其他操作。
其次,在可重復(fù)擦寫的能力方面,NAND的每塊可擦寫次數(shù)在10萬(wàn)至100萬(wàn)次之間,NOR則只是它的1/10,而且NAND的每個(gè)擦除塊的容量也只有NOR的1/8至1/2,這就表明,每個(gè)塊的擦寫的頻率要少于NOR閃存,從而有助于延長(zhǎng)使用壽命。在數(shù)據(jù)的保存時(shí)間上,兩者都差不多,為10年的水平。
不過,由于串聯(lián)的架構(gòu),NAND的晶體管之間更容易造成影響,使邏輯0變成邏輯1,并且也很難發(fā)現(xiàn)出問題的晶體管,這種現(xiàn)象可稱為位翻轉(zhuǎn)(Bit-Flipping),這就需要?jiǎng)佑肊DC/ECC(錯(cuò)誤檢測(cè)碼/錯(cuò)誤修正碼)來進(jìn)行校正,這方面的問題NOR則較少出現(xiàn)。
另外,NAND在使用中還存在著壞塊管理的問題,在NAND閃存中,由于壞塊是隨機(jī)分布的,因此需要進(jìn)行掃描并將壞塊打上標(biāo)記,就像對(duì)付硬盤中的壞扇區(qū)一樣。目前的產(chǎn)品中,可最多允許出現(xiàn)80個(gè)壞塊。壞塊的存在使得向NAND閃存寫入信息需要相當(dāng)?shù)募记?,因?yàn)樵O(shè)計(jì)師絕不能向壞塊寫入,這就意味著在NAND閃存上自始至終都必須進(jìn)行虛擬映射。
在軟件支持程度方面,應(yīng)該區(qū)別基本的讀/寫/擦操作和高一級(jí)的用于磁盤仿真和閃存管理算法的軟件,包括性能優(yōu)化。
在NOR閃存上運(yùn)行代碼不需要任何的軟件支持,在NAND閃存上進(jìn)行同樣操作時(shí),通常需要驅(qū)動(dòng)程序,也就是內(nèi)存技術(shù)驅(qū)動(dòng)程序(MTD),NAND和NOR閃存在進(jìn)行寫入和擦除操作時(shí)都需要MTD。
使用NOR閃存時(shí)所需要的MTD要相對(duì)少一些,許多廠商都提供用于NOR閃存的更高級(jí)軟件,這其中包括M-System的TrueFFS驅(qū)動(dòng),該驅(qū)動(dòng)被Wind River System、Microsoft、QNX Software System、Symbian和Intel等廠商所采用。
Linux-Nor Flash驅(qū)動(dòng)分析
一、Linux Flash驅(qū)動(dòng)結(jié)構(gòu)
1、Linux MTD系統(tǒng)層次
在Linux系統(tǒng)中,提供了MTD(內(nèi)存技術(shù)設(shè)備)系統(tǒng)來建立Flash針對(duì)Linux的統(tǒng)一、抽象的接口。
在引入MTD后,Linux系統(tǒng)中Flash設(shè)備驅(qū)動(dòng)及接口可分為4層,從上到下依次是:設(shè)備節(jié)點(diǎn)、MTD設(shè)備層、MTD原始設(shè)備層和硬件驅(qū)動(dòng)層。如下所示:
1) 設(shè)備節(jié)點(diǎn):通過mknod在/dev子目錄下建立MTD字符設(shè)備節(jié)點(diǎn)(主設(shè)備號(hào)為90)和MTD塊設(shè)備節(jié)點(diǎn)(主設(shè)備號(hào)為31),用戶通過訪問此設(shè)備節(jié)點(diǎn)即可訪問MTD字符設(shè)備和塊設(shè)備。
2) MTD設(shè)備層:分為MTD字符設(shè)備(mtdchar.c)和MTD塊設(shè)備(mtdblock.c),建立在MTD原始設(shè)備層之上,為應(yīng)用程序提供訪問Flash的接口。
3) MTD原始設(shè)備層:MTD原始設(shè)備層由兩部分組成,一部分是MTD原始設(shè)備的通用代碼,另一部分是各個(gè)特定的Flash的數(shù)據(jù),例如分區(qū)。
4) 硬件驅(qū)動(dòng)層:Flash 硬件驅(qū)動(dòng)層負(fù)責(zé)Flash硬件設(shè)備的讀、寫、擦除。

2、Linux MTD系統(tǒng)接口
在引入MTD后,底層Flash驅(qū)動(dòng)直接與MTD原始設(shè)備層交互,利用其提供的接口注冊(cè)設(shè)備和分區(qū)。
mtd_info是表示MTD原始設(shè)備的結(jié)構(gòu)體,每個(gè)分區(qū)也被認(rèn)為是一個(gè)mtd_info。例如:如果有兩個(gè)MTD原始設(shè)備,而每個(gè)上有3個(gè)分區(qū),在系統(tǒng)中就共有6個(gè)mtd_info結(jié)構(gòu)體,這些mtd_info的指針被存放在名為mtd_table的數(shù)組里。
struct mtd_info {
u_char type; /*內(nèi)存技術(shù)的類型*/
u_int32_t flags; /*標(biāo)志位*/
u_int32_t size; /*mtd設(shè)備的大小*/
u_int32_t erasesize; /*主要的擦除塊大小*/
u_int32_t writesize; /*最小的可寫單元的字節(jié)數(shù)*/
u_int32_t oobsize; /*OOB字節(jié)數(shù)*/
u_int32_t oobavail; /*可用的OOB字節(jié)數(shù)*/
char *name; /*分區(qū)的名字*/
int index; /*分區(qū)的索引號(hào)*/
struct nand_ecclayout *ecclayout; /*ECC布局結(jié)構(gòu)體指針*/
//不同的erasesize的區(qū)域
int numeraseregions; /*不同的erasesize的區(qū)域的數(shù)目*/
struct mtd_erase_region_info *eraseregions;
//擦除函數(shù)
int (*erase) (struct mtd_info *mtd, struct erase_info *instr);
//讀寫函數(shù)
int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
//oob讀寫函數(shù)
int (*read_oob) (struct mtd_info *mtd, loff_t from,
struct mtd_oob_ops *ops);
int (*write_oob) (struct mtd_info *mtd, loff_t to,
struct mtd_oob_ops *ops);
//設(shè)備鎖
int (*lock) (struct mtd_info *mtd, loff_t ofs, size_t len);
int (*unlock) (struct mtd_info *mtd, loff_t ofs, size_t len);
//電源管理函數(shù)
int (*suspend) (struct mtd_info *mtd);
void (*resume) (struct mtd_info *mtd);
//壞塊管理函數(shù)
int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
void *priv; /*私有數(shù)據(jù)*/
};
1) mtd_info的type字段給出底層物理設(shè)備的類型,包括MTD_RAM、MTD_ROM、MTD_NORFLASH、MTD_NANDFLASH等。
2) flags字段標(biāo)志可以是MTD_WRITEABLE、MTD_BIT_WRITEABLE、MTD_NO_ERASE、MTD_POWERUP_LOCK等的組合。
3) mtd_info中的的read()、write()、read_oob()、write_oob()、erase()是MTD設(shè)備驅(qū)動(dòng)要實(shí)現(xiàn)的主要函數(shù)。但是在NOR和NAND的驅(qū)動(dòng)代碼中幾乎看不到mtd_info的成員函數(shù),這是因?yàn)長(zhǎng)inux在MTD的下層實(shí)現(xiàn)了針對(duì)NOR Flash和NAND Flash的通用的mtd_info成員函數(shù)。
Flash驅(qū)動(dòng)中使用如下的兩個(gè)函數(shù)注冊(cè)和注銷MTD設(shè)備:
int add_mtd_device(struct mtd_info *mtd);
int del_mtd_device (struct mtd_info *mtd);
mtd_part結(jié)構(gòu)體用于表示分區(qū)(某一個(gè)分區(qū)),其mtd_info結(jié)構(gòu)體成員用于描述該分區(qū),它會(huì)被加入到mtd_table中。
struct mtd_part {
struct mtd_info mtd; //分區(qū)的信息
struct mtd_info *master; //該分區(qū)的主分區(qū)
u_int32_t offset; //該分區(qū)的偏移地址
int index; //分區(qū)號(hào)
struct list_head list;
int registered;
};
在MTD原始設(shè)備層中維護(hù)著一個(gè)mtd_part鏈表mtd_partitions(Flash的整個(gè)分區(qū))。
struct mtd_partition {
char *name; //標(biāo)識(shí)字符串
u_int32_t size; //分區(qū)大小
u_int32_t offset; //主MTD空間內(nèi)的偏移
u_int32_t mask_flags; //掩碼標(biāo)志
struct nand_ecclayout *ecclayout; //OOB布局
struct mtd_info **mtdp;
};
Flash驅(qū)動(dòng)中使用如下兩個(gè)函數(shù)注冊(cè)和注銷分區(qū):
int add_mtd_partitions(struct mtd_info *master,
const struct mtd_partition *parts,
int nbparts);
int del_mtd_partitions(struct mtd_info *master);
①add_mtd_partitions()會(huì)對(duì)每一個(gè)新建分區(qū)建立一個(gè)新的mtd_part結(jié)構(gòu)體,將其加入mtd_partition中,并調(diào)用add_mtd_device()將此分區(qū)作為MTD設(shè)備加入mtd_table。
②del_mtd_partitions()的作用是對(duì)于mtd_partition上的每一個(gè)分區(qū),如果它的主分區(qū)是master,則將它從mtd_partition和mtd_table中刪除并釋放掉,這個(gè)函數(shù)會(huì)調(diào)用del_mtd_device()。
二、NOR Flash驅(qū)動(dòng)結(jié)構(gòu)
在Linux系統(tǒng)中,實(shí)現(xiàn)了針對(duì)CFI(公共Flash接口)等接口的通用NOR驅(qū)動(dòng),這一層的驅(qū)動(dòng)直接面向mtd_info的成員函數(shù),這使得NOR的芯片級(jí)驅(qū)動(dòng)變得非常的簡(jiǎn)單,只需要定義具體的內(nèi)存映射情況結(jié)構(gòu)體map_info并使用指定接口類型調(diào)用do_map_probe()。
NOR Flash驅(qū)動(dòng)的核心是定義map_info結(jié)構(gòu)體,它指定了NOR Flash的基址、位寬、大小等信息以及Flash的讀寫函數(shù)。
struct map_info {
char *name; /*NOR FLASH的名字*/
unsigned long size; /*NOR FLASH的大小*/
resource_size_t phys; /*NOR FLASH的起始物理地址*/
void __iomem *virt; /*NOR FLASH的虛擬地址*/
void *cached;
int bankwidth; /*NOR FLASH的總線寬度*/
//緩存的虛擬地址
void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
void (*set_vpp)(struct map_info *, int);
};
NOR Flash驅(qū)動(dòng)在Linux中實(shí)現(xiàn)非常簡(jiǎn)單,如下圖所示:
①定義map_info的實(shí)例,初始化其中的成員,根據(jù)目標(biāo)板的情況為name、size、bankwidth和phys賦值。
②如果Flash要分區(qū),則定義mtd_partition數(shù)組,將實(shí)際電路板中Flash分區(qū)信息記錄于其中。
③以map_info和探測(cè)的接口類型(如“cfi_probe”等)為參數(shù)調(diào)用do_map_probe(),探測(cè)Flash得到mtd_info。
三、NOR Flash驅(qū)動(dòng)程序
需要說明的是,我用的是GQS3C2440的開發(fā)板,程序如下所示:
#include 《linux/module.h》
#include 《linux/init.h》
#include 《linux/kernel.h》 /*printk*/
#include 《asm/io.h》 /*ioremap*/
#include 《linux/types.h》 /*ARRAY_SIZE*/
#include 《linux/mtd/mtd.h》 /*mtd_info*/
#include 《linux/mtd/map.h》 /*map_info*/
#include 《linux/mtd/partitions.h》 /*mtd_partition*/
#define WINDOW_ADDR 0x00000000 /*NOR FLASH的物理地址*/
#define WINDOW_SIZE 0x00200000 /*NOR FLASH大小*/
#define BUSWIDTH 2 /*NOR FLASH總線寬度A0~A19*/
//探測(cè)的接口類型
#define PROBETYPES {“cfi_probe”,NULL}
//用于打印信息
#define MSG_PREFIX “S3C2440-NOR:”
static struct mtd_info *mymtd=0; /*定義MTD原始設(shè)備的結(jié)構(gòu)體*/
//定義并初始化map_info結(jié)構(gòu)體
struct map_info s3c2440nor_map={
.name = “NOR flash on S3C2440”, /*初始化NOR FLASH的名字*/
.size = WINDOW_SIZE, /*初始化NOR FLASH的大小*/
.bankwidth = BUSWIDTH, /*初始化NOR FLASH的位寬*/
.phys = WINDOW_ADDR, /*初始化NOR FLASH的物理地址*/
};
//MTD分區(qū)的信息
static struct mtd_partition static_partitions[]=
{
//bootloader存放的區(qū)域
{
.name = “U-boot”,
.size = 0x040000,
.offset= 0x0
},
};
static int mtd_parts_nb=0; /*定義分區(qū)數(shù)*/
static struct mtd_partition *mtd_parts=0; /*定義分區(qū)*/
static int __init s3c2440nor_init(void)
{
static const char *rom_probe_types[]=PROBETYPES; /*定義探測(cè)的接口類型*/
const char **type;
const char *part_type=0; //定義分區(qū)的類型
printk(KERN_NOTICE MSG_PREFIX“0x%08x at 0x%08x\n”,WINDOW_SIZE,WINDOW_ADDR);
//將NOR FLASH的物理地址映射為虛擬地址
s3c2440nor_map.virt=ioremap(WINDOW_ADDR,WINDOW_SIZE);
if(!s3c2440nor_map.virt)
{
printk(MSG_PREFIX“failed to ioremap\n”);
return -EIO;
}
//初始化read、copy_from、write、copy_to函數(shù)
simple_map_init(&s3c2440nor_map);
//探測(cè)NOR FLASH
type=rom_probe_types;
for(;!mymtd && *type;type++)
mymtd=do_map_probe(*type,&s3c2440nor_map);
//找到NOR FLASH
if(mymtd)
{
mymtd-》owner=THIS_MODULE;
mtd_parts=static_partitions; /*初始化分區(qū)*/
mtd_parts_nb=ARRAY_SIZE(static_partitions); /*得到分區(qū)數(shù)*/
part_type=“static”;
if(mtd_parts_nb==0)
printk(KERN_NOTICE MSG_PREFIX“no partition info available\n”);
else
{
printk(KERN_NOTICE MSG_PREFIX “using %s partition definition\n”,part_type);
add_mtd_partitions(mymtd,mtd_parts,mtd_parts_nb); /*注冊(cè)分區(qū)*/
}
return 0;
}
return -ENXIO;
}
static void s3c2440nor_exit(void)
{
if(mymtd)
{
del_mtd_partitions(mymtd); //刪除分區(qū)
map_destroy(mymtd); //注銷mtd_info結(jié)構(gòu)體
}
//取消虛擬地址的映射
iounmap((void *)s3c2440nor_map.virt);
}
module_init(s3c2440nor_init);
module_exit(s3c2440nor_exit);
MODULE_AUTHOR(“chenqi”);
MODULE_LICENSE(“GPL”);
結(jié)語(yǔ)
關(guān)于nand和nor的相關(guān)介紹就到這了,如有不足之處歡迎指正。
-
FlaSh
+關(guān)注
關(guān)注
10文章
1758瀏覽量
155857 -
存儲(chǔ)器
+關(guān)注
關(guān)注
39文章
7753瀏覽量
172144
發(fā)布評(píng)論請(qǐng)先 登錄
NAND Flash和NOR Flash的差別
NAND FLASH與NOR FLASH的技術(shù)對(duì)比
NOR型flash與NAND型flash的區(qū)別
NOR型flash與NAND型flash的區(qū)別
SPI NAND Flash和SPI NOR Flash的區(qū)別在哪里?
嵌入式Linux系統(tǒng)下NOR Flash的配置和使用
nand nor flash區(qū)別
NAND Flash與NOR Flash的區(qū)別
NOR Flash和NAND FLASH的區(qū)別是什么
NAND Flash和NOR Flash的區(qū)別
nand和nor區(qū)別 Linux-Nor Flash驅(qū)動(dòng)分析
評(píng)論