本文主要是關(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)常可以與相“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,然后每塊又分成頁,頁的大小一般是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微秒的尋頁時(shí)間+200微秒的片擦寫時(shí)間=234微秒。
5)NAND閃存的容量比較大,目前最大容量己經(jīng)達(dá)到8G字節(jié)。為了方便管理,NAND的存儲(chǔ)空間使用了塊和頁兩級(jí)存儲(chǔ)體系,也就是說閃存的存儲(chǔ)空間是二維的,比如K9F5608UOA閃存塊的大小為16K,每頁的大小是512字節(jié),每頁還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閃存的操作都是以塊和頁為單位的,所以在向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)的頁面中如果有一位失效整個(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萬至100萬次之間,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é)語
關(guān)于nand和nor的相關(guān)介紹就到這了,如有不足之處歡迎指正。
-
FlaSh
+關(guān)注
關(guān)注
10文章
1642瀏覽量
148664 -
存儲(chǔ)器
+關(guān)注
關(guān)注
38文章
7528瀏覽量
164342
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論