nand falsh 111

copy from http://blog.csdn.net/renpine/article/details/4570538

目錄

Architecture

NAND Flash是由4096個Blocks所組成的,每個Block是由128個Pages所組成的,而每個Page是由4KBytes的User Data加上128Bytes的Spare Data所構成的,故每個Block的容量為528Kbytes,每個Page的容量為4224Bytes。其中,Spare Data主要是用來存放ECC(Error Correcting Code)、Bad Block Information和File System的資料。

Figure 1.Flash Memory Geometry

NAND Flash的操作特點為:抹除(Erase)的最小單位是Block,而讀取(Read)和寫入(Write)則是以Page為單位。因NAND Flash的每個bit只能由1變為0,而不能從0變為1,所以對Flash做寫入時一定要將其對應的Block先抹除掉,才能做寫入的動作,也因此同樣一個page只能夠寫入一次。

Constraints and Functionalities

Constraints

Sequential Page program

在一個Block裡,Page必須從LSB(least significant bit) Page依序寫到MSB(most significant bit) Page,隨意不照Page address來寫入是禁止的。另外,LSB是寫入的Pages中最小的位址,不一定是Page 0。

 

Figure 2.Sequential Page program [1]

Partial Page program

在NAND Flash中,存取資料的最小單位是Page。在SLC Flash中,若想修改Page中的Data時可以更改部分的Bit而不需要將整個Page抹除後才更改。例如Page中的Data為1001011101,若想將Data改成1001010001,只需將其中的2個Bit更改為0即可,不用抹除後寫入。但之後的MLC Flash,已經不允許此功能了。

Performance-Improving Commands

Copy Back Program

Copy Back Program可以快速地將1頁的資料複製(Copy)到另1個指定的頁中,也對於垃圾收集(Garbage Collection)非常的有用。例如當1頁裡的資料壞掉造成整個區塊(Block)為損壞區塊(Bad Block, or Worn-Out Block)時,Copy Back Program可以有效率地將所有有效頁(Valid Page)的資料複製到指定的區塊中。

Copy Back Program是將1整頁的資料(來源Page)讀取且複製到內部頁緩衝器(Internal Page Buffer)中,再將它寫到另1整頁中(目標Page)。因為它不像一般的讀取、寫入指令將資料存取到外部記憶體(Memory),而是將資料存在內部頁緩衝器中,所以會比一般的讀取加上寫入少了將資料讀寫到外部記憶體的時間,執行上也更快且更有效率。

Figure 3.Copy Back Program [1]

Random data input/output

當對Page的資料做讀寫時,必須將1整頁的所有資料都存在於外部記憶體中,當外部的RAM不夠大時,無法一次存放整個頁的資料,故利用NAND Flash的Internal Page Buffer來存放整個頁的資料,並使用Random Data Input/Output就可以對頁中任意位址的資料做存取。

對1頁裡的資料做一般的讀寫時,資料都是Sequential的,但若想要隨意存取1頁裡的資料,如想要存取ECC的資料,便可使用Random data input/output跳至User Data的尾端去存取ECC的資料。

-Plane program

NAND Flash Vendor將Memory Array分成2個Plane,可以同時對2個不同Block addresses做Read/Write/Erase的操作。

 

Figure 4.2-Plane Program [6]

NAND-flash Management Issues

Address Translation

NAND Flash Memory的同1個page不能做重覆寫入的行為。再者,在寫入1個sector資料之前,必須要有抹除1個Block的資料才能做寫入的動作,但抹除 1個Block的動作需要耗費相當多的時間,此舉造成了NAND Flash效能下降的最大原因。為了改善效能,最有效的方法就是減少Erase的次數,因此有了Mapping Table。

Mapping Table的管理分為Block level、Sector level以及改良的Hybrid level。

Block level的address mapping是指1個Logical Block對應到1個Physical Block,它的mapping table相對於sector-level的mapping table來的小,能夠節省mapping table所佔RAM的使用量。但當Logical Block的個數少於Physical Block個數時,會發生Logical Block時常被overwrite的狀況,選定要overwrite的Logical block和它mapping的Physical Block都要將資料更新到新的Physical Block上,且做erase-before-write的動作,而造成效能的下降,此外轉換單位大,每次寫入的單位也大,因此會帶來額外的資料寫入成本。

而Sector-Level的address mapping是1個Logical Sector可以對應到任1個Physical Block裡的Sector,雖然這種mapping的方式彈性佳,可以減少因轉換單位大而帶來額外的資料寫入成本,但是mapping table的Size過大,例如1GB的Flash,1個sector的大小為512byte的話,RAM就要維護二百萬筆的sector資訊。

 

Figure 5. 資料區塊,紀錄區塊,以及備用區塊的使用。

(a)完整的資料區塊(b)資料依序寫入紀錄區塊的可寫頁中(c)區塊鏈的Merge

改良的Hybrid level,擷取Block level和Sector level的優點,採用Block level的方式,再加上有限數量的Block做為Sector level的mapping,除了讓mapping table的size限制住不至於龐大,也減少了erase-before-write的動作。Hybrid level中,將Physical Block取名為資料區塊(Data Block),因為資料不能直接更新於資料區塊裡,我們找了一段可寫的Block來紀錄更新的資料,並將它取名為紀錄區塊(Log Block)。經過一段時間的寫入,一個LBA(Logical Block Address)對應會對應一個資料區塊,而此資料區塊會跟著數個紀錄區塊,整個形成一個區塊鏈(Block Chain),如圖5(b)所示。

 

Figure 6.Hybrid Level mapping table [7]

Hybrid Level在做write的時候,在寫第1、2筆資料時(sector 4,5),會由block level的mapping table找出Data Block 10,因為對應sector裡內容是空的,因此就直接寫入Data Block 10裡。而寫第3筆資料時(sector 4),由Block level的mapping table找到Data Block 10,但裡面已有寫入的資料,故改由sector level的mapping table找尋空的Log Block,寫入第3筆資料。在寫第4筆資料時(sector 4),因為sector level的mapping table裡已有mapped的Log Block,故將第4筆資料依序寫入對映的Log Block裡。

而在讀取時,會先由Sector level的mapping table裡,找出最新的資料,而Log Block裡沒有的資料,則由Block Level mapping table裡找到的Data Block裡。

Garbage Collection

主要是用於將不必要存在且浪費空間的Block做回收,來增加可用的Block數。當需要新的Log Block時,會從已經使用的Log Block裡選取符合回收條件的Block來做Garbage Collection,如free sector低於threshold值。

被選定要回收的Log Block,會和它的Data Block做merge的動作,意即選取新的Data Block,將Log Block中sector資料copy到此新的Data Block中,再將原先Data Block中剩餘的sector資料複製到此新的Data Block中。

更新block-level table對應到新的Data Block,並將sector-level table裡將剛纔回收的Log Block移除。原先的Log Block和Data Block做抹除的動作,即完成Garbage Collection了。

例如Figure 4中,要將Log block(pbn=20)做回收時,會將此log block中最新的資料(sector 4)複製到新的Data Block中(假設為pbn=12),再將它的Data block(pbn=10)中,其餘的資料(sector 5)複製到新的Data Block(pbn=12)中。並將block level table中對應到pbn=20的資料改為對應到pbn=12,即新的data block,再將sector level table中pbn=20(回收的log block)這筆資料刪除。最後將pbn=20,pbn=10舊的block做抹除的動作即可。

Merge在一種特殊情況下,可以做switch的動作,例如像Figure 4中,Log Block(pbn=30)裡是照sector的順序寫入,因此它的Data Block(pbn=11)裡的資料都是不需要使用的舊資料,要做Garbage Collection,只需要將Log Block和Data Block對調即可,即block-level table裡對應到pbn=11這筆資料改為對應到pbn=30,而sector-level table裡對應到pbn=30這筆刪除,然後將舊的Data Block(pbn=11)抹除就達到Garbage Collection了。

Figure 7.Garbage Collection Operation [3]

當在做Garbage Collection時,會希望用最少的cleaning work來獲得最多的free space,因此會選擇最多garbage的segment來做回收。另外,將資料的型態分為靜態和動態的資料。其中,Read-only data屬於靜態資料,即一旦創造就不會去修改它,而動態資料是會被修改的。動態資料依其資料修改頻率分為cold data(較少修改的資料)和hot data(修改頻繁的資料)。

依不同的資料型態,做資料搬移時的方式也分為三種:

Read-only Data mix with dynamic data

當要被回收的segment中有read-only data時,會先將所有的read-only data搬到新的segment裡。若此新的segment又會被回收時,之前搬移過的read-only data仍然會再被搬移一次。另外,當一個segment中的資料都為read-only data時,則此segment永遠不會被回收的。

 

Figure 8.Repeatedly migrating read-only data when they are mixed with dynamic data [9]

Cold data mix with hot data

當要被回收的segment中有cold data和hot data時,因cold data更改的頻率較少,在cleaning的期間cold data有較高的可能性為valid的,因此會將cold data搬移到新的segment裡。

 

Figure 9.Migrating cold data when they are mixed with hot data [9]

Data have high locality of reference

當要被回收segment中的data是有高度被參考性的,這些hot data在cleaning的過程中仍可能是valid,但在被搬移到新的segment時,hot data又被更新一次而成為garbage,這類的搬移即稱為useless migration。

Figure 10.Useless migration when hot data are updated soon after being migrated [9]

Wear-Leveling

當在使用Flash時,常會對某個檔案做修改的動作,當此時檔案變動而要用到更多的Page且Flash中仍有空的Block時,會將空的 Block配置給此檔案來使用,若Flash中已經沒有空的Block時,則會執行Garbage Collection來清出空的Block以供使用。在挑選空的Block或執行Garbage Collection清出空的Block時,可能會造成部分的Block時常被挑選,這些Block可能因為被過度使用而造成損毀。為了避免這種情況發生,會使用Wear-Leveling,讓大部分Block的存取次數平均,而不會常常挑選到某些固定的Block上,造成Block的過度存取而損毀。

再者,NAND Flash抹除和寫入的reliability有使用的次數(100,000次),使用wear-leveling可以紀錄並平均每個block被使用的次數。

Wear-Leveling有兩種方式來實現,一種是在FileSystem和NAND Flash中間的FTL(Flash Translation Layer)裡實現的。FTL可以讓上層的OS透過FTL以disk的方式去讀寫下層的NAND Flash,另外也提供了virtual address和physical address的轉換。

 

Figure 11. Wear Leveling in the FTL [4]

另一種的實現方法為Wear Leveling直接在FileSystem裡實現,OS直接透過HAL和NAND Flash溝通。

 

Figure 12.Wear Leveling in the File System [4]

Flow Chart

Read

 

Figure 13 Read Operation Flow Chart

Erase

 

Figure 14 Erase Operation Flow Chart

Write

 

Figure 15 Write Operation Flow Chart

Timing/Power

Timing

Read Operation

 

BandWidth:39.82MB/s

Write Operation

 

BandWidth:4.66MB/s~1.36MB/s

Erase Operation

 

Power

P(typ)=3.3V*15mA=49.5mW

P(max)=3.6V*30mA=108mW

Read Operation

E(typ)=49.5mW*(195+180+4224*25+100)ns=49.5mW*106075ns

=

J

E(max)=108mW*(195+180+4224*25+100)ns=108mW*106075ns

=

J

Write Operation

E(typ)=49.5mW*(295+4224*25+100+

+200)ns

=49.5mW*906195ns

=

J

    E(max)=108mW*(295+4224*25+100+

+200)ns

=108mW*3106195ns

=

J

Erase Operation

E(typ)=49.5mW*(245+

+200)ns=49.5mW*1500445ns

=

J

E(max)=108mW*(245+

+200)ns=108mW*10000445ns

=

J

Reference

  • Samsung Electronics, "K9GAG08UXM Specification"
  • Alex Kuo, "Application Note: Partial Page Program MirrorBit ORNAND with NAND interface", Spansion
  • STMicroelectronics, "AN1821 Garbage Collection in Single Level Cell NAND Flash memories"
  • STMicroelectronics, "AN1822 Wear Leveling in Single Level Cell NAND Flash memories"
  • STMicroelectronics, "AN1728 How to use the Copy Back feature of ST Small Page NAND Flash memories"
  • Amber Huffman, ONFI Technical Chair, "Flash Performance Enhancements through ONFI", Intel Corporation
  • S.-W. Lee, D.-J. Park, T.-S. Chung, D.-H. Lee, S.-W. Park, H.-J. Song, "A Log Buffer-Based Flash Translation Layer Using Fully-Associative Sector Translation", ACM Transactions on Embedded Computing Systems, Vol.6,No.3,Article 18,Publication date: July 2007
  • STMicroelectronics, "AN1820 How to use the FTL and HAL Software Modules to Manage Data in Single Level Cell NAND Flash Memories"
  • Mei-Ling Chiang, Paul C. H. Lee, Ruei-Chuan Chang, "Cleaning Policies in Mobile Computers Using Flash Memory", Journal of Systems and Software, v.48 n.3, p.213-231, Nov. 1, 1999



第一章緒論 7-15

1.1課題來源 7-8

1.2研究背景與意義 8-14

1.2.1Flash介紹 8

1.2.2NAND Flash介紹 8-10

1.2.3NAND FlashNORFlash比較 10-13

1.2.4研究目的 13-14

1.3論文章節安排 14-15

第二章NANDFlash結構與原理 15-31

2.1NAND Flash種類 15-17

2.1.1SLC 15

2.1.2MLC 15-17

2.2NAND Flash結構 17-29

2.2.1NAND Flash結構 17-22

2.2.2NAND Flash的主要流程 22-29

2.2.2.1讀操作 22-23

2.2.2.2頁編程操作 23-25

2.2.2.3塊擦除操作 25-26

2.2.2.4COPY-BACK編程 26-27

2.2.2.5Two Plane相關操作 27-29

2.3小結 29-31

第三章NANDFlash動態壞塊管理算法 31-61

3.1NAND Flash壞塊管理 31-33

3.1.1壞塊管理概念的提出 31-32

3.1.2壞塊管理的一般方法 32-33

3.2NAND Flash動態壞塊管理算法研究與實現 33-56

3.2.1NAND Flash動態壞塊管理設計思想 33-35

3.2.2動態壞塊管理算法步驟流程及具體函數實現 35-55

3.2.3動態壞塊管理算法與一般壞塊管理算法比較總結 55-56

3.3損耗平衡 56-58

3.3.1損耗平衡原理和使用意義 56-57

3.3.2損耗平衡算法 57-58

3.4垃圾回收機制 58-61

NANDFLASH內存詳解與讀寫尋址方式



一、內存詳解

NAND閃存陣列分爲一系列128kB的區塊(block),這些區塊是NAND器件中最小的可擦除實體。擦除一個區塊就是把所有的位(bit)設置爲"1"(而所有字節(byte)設置爲FFh)。有必要通過編程,將已擦除的位從"1"變爲"0"。最小的編程實體是字節(byte)。一些NOR閃存能同時執行讀寫操作(見下圖1)。雖然NAND不能同時執行讀寫操作,它可以採用稱爲"映射(shadowing)"的方法,在系統級實現這一點。這種方法在個人電腦上已經沿用多年,即將BIOS從速率較低的ROM加載到速率較高的RAM上。

NAND的效率較高,是因爲NAND串中沒有金屬觸點。NAND閃存單元的大小比NOR要小(4F210F2)的原因,是NOR的每一個單元都需要獨立的金屬觸點。NAND與硬盤驅動器類似,基於扇區(),適合於存儲連續的數據,如圖片、音頻或個人電腦數據。雖然通過把數據映射到RAM上,能在系統級實現隨機存取,但是,這樣做需要額外的RAM存儲空間。此外,跟硬盤一樣,NAND器件存在壞的扇區,需要糾錯碼(ECC)來維持數據的完整性。

存儲單元面積越小,裸片的面積也就越小。在這種情況下,NAND就能夠爲當今的低成本消費市場提供存儲容量更大的閃存產品。NAND閃存用於幾乎所有可擦除的存儲卡。NAND的複用接口爲所有最新的器件和密度都提供了一種相似的引腳輸出。這種引腳輸出使得設計工程師無須改變電路板的硬件設計,就能從更小的密度移植到更大密度的設計上。

NANDNOR閃存比較

NAND閃存的優點在於寫(編程)和擦除操作的速率快,而NOR的優點是具有隨機存取和對字節執行寫(編程)操作的能力(見下圖圖2)NOR的隨機存取能力支持直接代碼執行(XiP),而這是嵌入式應用經常需要的一個功能。NAND的缺點是隨機存取的速率慢,NOR的缺點是受到讀和擦除速度慢的性能制約。NAND較適合於存儲文件。如今,越來越多的處理器具備直接NAND接口,並能直接從NAND(沒有NOR)導入數據。

NAND的真正好處是編程速度快、擦除時間短。NAND支持速率超過5Mbps的持續寫操作,其區塊擦除時間短至2ms,而NOR750ms。顯然,NAND在某些方面具有絕對優勢。然而,它不太適合於直接隨機存取。

對於16位的器件,NOR閃存大約需要41I/O引腳;相對而言,NAND器件僅需24個引腳。NAND器件能夠複用指令、地址和數據總線,從而節省了引腳數量。複用接口的一項好處,就在於能夠利用同樣的硬件設計和電路板,支持較大的NAND器件。由於普通的TSOP-1封裝已經沿用多年,該功能讓客戶能夠把較高密度的NAND器件移植到相同的電路板上。NAND器件的另外一個好處顯然是其封裝選項:NAND提供一種厚膜的2Gb裸片或能夠支持最多四顆堆疊裸片,容許在相同的TSOP-1封裝中堆疊一個8Gb的器件。這就使得一種封裝和接口能夠在將來支持較高的密度。




2NOR閃存的隨機存取時間爲0.12ms,而NAND閃存的第一字節隨機存取速度要慢得多

NOR閃存的隨機存取時間爲0.12ms,而NAND閃存的第一字節隨機存取速度要慢得多

NAND基本操作

2GbNAND器件爲例,它由2048個區塊組成,每個區塊有64個頁(見下圖):

每一個頁均包含一個2048字節的數據區和64字節的空閒區,總共包含2,112字節。空閒區通常被用於ECC、耗損均衡(wearleveling)和其它軟件開銷功能,儘管它在物理上與其它頁並沒有區別。NAND器件具有816位接口。通過816位寬的雙向數據總線,主數據被連接到NAND存儲器。在16位模式,指令和地址僅僅利用低8位,而高8位僅僅在數據傳輸週期使用。

擦除區塊所需時間約爲2ms。一旦數據被載入寄存器,對一個頁的編程大約要300μs。讀一個頁面需要大約25μs,其中涉及到存儲陣列訪問頁,並將頁載入16,896位寄存器中。

除了I/O總線,NAND接口由6個主要控制信號構成:

1.芯片啓動(ChipEnable, CE#):如果沒有檢測到CE信號,那麼,NAND器件就保持待機模式,不對任何控制信號作出響應。

2.寫使能(WriteEnable, WE#): WE#負責將數據、地址或指令寫入NAND之中。

3.讀使能(ReadEnable, RE#): RE#允許輸出數據緩衝器。

4.指令鎖存使能(CommandLatch Enable, CLE): CLE爲高時,在WE#信號的上升沿,指令被鎖存到NAND指令寄存器中。

5.地址鎖存使能(AddressLatch Enable, ALE):當ALE爲高時,在WE#信號的上升沿,地址被鎖存到NAND地址寄存器中。

6.就緒/(Ready/Busy,R/B#):如果NAND器件忙,R/B#信號將變低。該信號是漏極開路,需要採用上拉電阻。

數據每次進/NAND寄存器都是通過16位或8位接口。當進行編程操作的時候,待編程的數據進入數據寄存器,處於在WE#信號的上升沿。在寄存器內隨機存取或移動數據,要採用專用指令以便於隨機存取。


數據寄存器輸出數據的方式與利用RE#信號的方式類似,負責輸出現有的數據,並增加到下一個地址。WE#RE#時鐘運行速度極快,達到30ns的水準。當RE#CE#不爲低的時候,輸出緩衝器將爲三態。這種CE#RE#的組合使能輸出緩衝器,容許NAND閃存與NORSRAMDRAM等其它類型存儲器共享數據總線。該功能有時被稱爲"無需介意芯片啓動(chipenable don't care)"。這種方案的初衷是適應較老的NAND器件,它們要求CE#在整個週期爲低(譯註:根據上下文改寫)


4輸入寄存器接收到頁編程(80h)指令時,內部就會全部重置爲1s,使得用戶可以只輸入他想以0位編程的數據字節


5帶有隨機數據輸入的編程指令。圖中加亮的扇區顯示,該指令只需要後面跟隨着數據的2個字節的地址

所有NAND操作開始時,都提供一個指令週期(1)




當輸出一串WE#時鐘時,通過在I/O70上設置指令、驅動CE#變低且CLE變高,就可以實現一個指令週期。注意:在WE#信號的上升沿上,指令、地址或數據被鎖存到NAND器件之中。如表1所示,大多數指令在第二個指令週期之後要佔用若干地址週期。注意:復位或讀狀態指令例外,如果器件忙,就不應該發送新的指令。
2GbNAND器件的尋址方案爲例,第一和第二地址週期指定列地址,該列地址指定頁內的起始字節表:



注意:因爲最後一列的位置是2112,該最後位置的地址就是08h(在第二字節中)3Fh(在第一字節中)PA5:0指定區塊內的頁地址,BA16:6指定區塊的地址。雖然大多編程和讀操作需要完整的5字節地址,在頁內隨機存取數據的操作僅僅用到第一和第二字節。塊擦除操作僅僅需要三個最高字節(第三、第四和第五字節)來選擇區塊。




總體而言,NAND的基本操作包括:復位(Reset,FFh)操作、讀ID(ReadID, 00h)操作、讀狀態(ReadStatus, 70h)操作、編程(Program)操作、隨機數據輸入(Randomdata input, 85h)操作和讀(Read)操作等。


選擇內置NAND接口的處理器或控制器的好處很多。如果沒有這個選擇,有可能在NAND和幾乎任何處理器之間設計一個"無粘接邏輯(glueless)"接口。NANDNOR閃存的主要區別是複用地址和數據總線。該總線被用於指定指令、地址或數據。CLE信號指定指令週期,而ALE信號指定地址週期。利用這兩個控制信號,有可能選擇指令、地址或數據週期。把ALE連接到處理器的第五地址位,而把CLE連接到處理器的第四地址位,就能簡單地通過改變處理器輸出的地址,任意選擇指令、地址或數據。這容許CLEALE在合適的時間自動設置爲低。

爲了提供指令,處理器在數據總線上輸出想要的指令,並輸出地址0010h;爲了輸出任意數量的地址週期,處理器僅僅要依次在處理器地址0020h之後輸出想要的NAND地址。注意,許多處理器能在處理器的寫信號周圍指定若干時序參數,這對於建立合適的時序是至關重要的。利用該技術,你不必採用任何粘接邏輯,就可以直接從處理器存取指令、地址和數據。

多級單元

多級單元(MLC)的每一個單元存儲兩位,而傳統的SLC僅僅能存儲一位。MLC技術有顯著的密度優越性,然而,與SLC相比(下表),其速度或可靠性稍遜。因此,SLC被用於大多數媒體卡和無線應用,而MLC器件通常被用於消費電子和其它低成本產品。

如上所述,NAND需要ECC以確保數據完整性。NAND閃存的每一個頁面上都包括額外的存儲空間,它就是64個字節的空閒區(512字節的扇區有16字節)。該區能存儲ECC代碼及其它像磨損評級或邏輯到物理塊映射之類的信息。ECC能在硬件或軟件中執行,但是,硬件執行有明顯的性能優勢。在編程操作期間,ECC單元根據扇區中存儲的數據來計算誤碼校正代碼。數據區的ECC代碼然後被分別寫入到各自的空閒區。當數據被讀出時,ECC代碼也被讀出;運用反操作可以覈查讀出的數據是否正確。

有可能採用ECC算法來校正數據錯誤。能校正的錯誤的數量取決於所用算法的校正強度。在硬件或軟件中包含ECC,就提供了強大的系統級解決方案。最簡單的硬件實現方案是採用簡單的漢明(SimpleHamming)碼,但是,只能校正單一位錯誤。瑞德索羅門(Reed-Solomon)碼提供更爲強大的糾錯,並被目前的控制器廣爲採用。此外,BCH碼由於比瑞德索羅門方法的效率高,應用也日益普及。

要用軟件執行NAND閃存的區塊管理。該軟件負責磨損評級或邏輯到物理映射。該軟件還提供ECC碼,如果處理器不包含ECC硬件的話。

編程或擦除操作之後,重要的是讀狀態寄存器,因爲它確認是否成功地完成了編程或擦除操作。如果操作失敗,要把該區塊標記爲損壞且不能再使用。以前已編寫進去的數據要從損壞的區塊中搬出,轉移到新的(好的)存儲塊之中。2GbNAND的規範規定,它可以最多有40個壞的區塊,這個數字在器件的生命週期(額定壽命爲10萬次編程/擦除週期)內都適用。一些有壞塊的NAND器件能夠出廠,主要就歸根於其裸片面積大。管理器件的軟件負責映射壞塊並由好的存儲塊取而代之。

利用工廠對這些區塊的標記,軟件通過掃描塊可以確定區塊的好壞。壞塊標記被固定在空閒區的第一個位置(列地址2048)。如果在01頁的列地址2048上的數據是"non-FF",那麼,該塊要標記爲壞,並映射出系統。初始化軟件僅僅需要掃描所有區塊確定以確定哪個爲壞,然後建一個壞塊表供將來參考。


小心不要擦除壞塊標記,這一點很重要。工廠在寬溫和寬電壓範圍內測試了NAND;一些由工廠標記爲壞的區塊可能在一定的溫度或電壓條件下仍然能工作,但是,將來可能會失效。如果壞塊信息被擦除,就無法再恢復。


二、NAND FLASH讀寫尋址方式

NAND Flash的尋址方式和NANDFlashmemory組織方式緊密相關。NANDFlash的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。
    
這些Line會再組成Page,通常是528Byte/page或者264Word/page。然後,每32page形成一個BlockSizeof(block)=16kByte.
    Block
NANDFlash中最大的操作單元,擦除就是按照block爲單位完成的,而
編程/讀取是按照page爲單位完成的。
    
所以,按照這樣的組織方式可以形成所謂的三類地址:
    -Block   Address
     -Page   Address
     -Column Address
    
首先,必須清楚一點,對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度可以是8位或者16位,但是,對於x16NANDDeviceI/O[15:8]只用於傳遞數據。
    
清楚了這一點,我們就可以開始分析NANDFlash的尋址方式了。
    
528Byte/page總容量512Mbit+512kbyteNAND器件爲例:
因爲,
    1 block=16kbyte

    512Mbit=64Mbyte

    Numberof(block)=1024
     1block=32page,
    1page=528byte=512byte(Main Area)+16byte(Spare Area)
用戶數據保存在mainarea中。
    512byte
需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由所謂的pointeroperation命令來選擇,也就是選擇了bit8的高低。因此A8就是halfpagepointerA[7:0]就是所謂的columnaddress
    32
page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,共8192block,則blockaddressA[26:14]表示。而pageaddress就是blcokaddress|page address in block
NAND Flash
的地址表示爲:
     Block Address|Page Address in block|halfpage pointer|ColumnAddress
地址傳送順序是ColumnAddress,Page Address,BlockAddress
由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。
    
例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。
NAND_ADDR爲例:
    
1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫,而真正的bit8的值是don'tcare的。
    
2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0];
    
3步將NAND_ADDR[24:17]放到I/O;
    
4步需要將NAND_ADDR[25]放到I/O;
    
因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing
    
如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。

NandFlash結構與讀寫分析及NandFlash尋址方式【ZZ


vivi代碼的head.S的時候,看到copy_myself的部分,尤其nand_read_ll函數,看不太明白,不瞭解nandflash原理,結合nandflashdatasheet和網上的文章,對那個函數就大概瞭解一點了

http://www.mcuol.com/Solution/195/21883.htm

下面的內容也是別人轉載的,我繼續轉載http://hi.baidu.com/luyun21/blog/item/e0fa82af6de3c6c87dd92a6b.html,內容好像有點亂,我只看了一點點,對其尋址明白了一點,暫時就這樣了,暫時還沒需要繼續研究,有需要在研究

NandFlash結構與讀寫分析

NAND Flash 的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。這些Line會再組成Page(NandFlash有多種結構,我使用的NandFlashK9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32page形成一個BlockSizeof(block)=16kByte1block=16kbyte512Mbit=64MbyteNumberof(block)=10241block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)


Nand flash
以頁爲單位讀寫數據,而以塊爲單位擦除數據。按照這樣的組織方式可以形成所謂的三類地址:--Block Address --Page Address   --Column Address(即爲頁內偏移地址)


對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度是8位。


512byte
需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的columnaddress32page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,則blockaddressA[26:14]表示。而pageaddress就是blcokaddress|page address in block, NAND Flash 的地址表示爲:Block Address|PageAddress in block|halfpage pointer|Column Address地址傳送順序是ColumnAddress,Page Address,Block Address。由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR爲例: 第1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上,而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫。而真正的bit8的值是don\'tcare的。 第2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0]上第3步將NAND_ADDR[24:17]放到I/O上 第4步需要將NAND_ADDR[25]放到I/O上 因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing。 如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。

下面,就x16NANDflash器件稍微進行一下說明。由於一個pagemainarea的容量爲256word,仍相當於512byte。但是,這個時候沒有所謂的1st halfpage 2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個時候bit8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點之外,x16NAND使用方法和x8的使用方法完全相同。


norflash
nandflash的區別
norflash
中可以運行程序,nandflash不可以
Norflash
sector可擦除,按bit可讀寫。NandFlashBlock可擦除,按Page可讀寫。
最主要是尋址方式不同

*********************************************************************************************************************************

NandFlash尋址方式

NAND Flash的尋址方式和NANDFlashmemory組織方式緊密相關。NANDFlash的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。
    
這些Line會再組成Page,通常是528Byte/page或者264Word/page。然後,每32page形成一個BlockSizeof(block)=16kByte.
    Block
NANDFlash中最大的操作單元,擦除就是按照block爲單位完成的,而
編程/讀取是按照page爲單位完成的。

     所以,按照這樣的組織方式可以形成所謂的三類地址:
    -Block   Address
     -Page   Address
     -Column Address

     首先,必須清楚一點,對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度可以是8位或者16位,但是,對於x16NANDDeviceI/O[15:8]只用於傳遞數據。

     清楚了這一點,我們就可以開始分析NANDFlash的尋址方式了。

     528Byte/page總容量512Mbit+512kbyteNAND器件爲例:
因爲,
    1 block=16kbyte

    512Mbit=64Mbyte

    Numberof(block)=1024
     1block=32page,
    1page=528byte=512byte(Main Area)+16byte(Spare Area)
用戶數據保存在mainarea中。

    512byte需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由所謂的pointeroperation命令來選擇,也就是選擇了bit8的高低。因此A8就是halfpagepointerA[7:0]就是所謂的columnaddress
    32
page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,共8192block,則blockaddressA[26:14]表示。而pageaddress就是blcokaddress|page address in block
NAND Flash
的地址表示爲:
     Block Address|Page Address in block|halfpage pointer|ColumnAddress
地址傳送順序是ColumnAddress,Page Address,BlockAddress
由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。
    
例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。

NAND_ADDR爲例:
    
1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫,而真正的bit8的值是don'tcare的。
    
2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0];
    
3步將NAND_ADDR[24:17]放到I/O;
    
4步需要將NAND_ADDR[25]放到I/O;
    
因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing
    
如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。




NANDFlash Architecture



Architecture
NANDFlash
是由4096Blocks所組成的,每個Block是由128Pages所組成的,而每個Page是由4KBytesUserData加上128BytesSpareData所構成的,故每個Block的容量為528Kbytes,每個Page的容量為4224Bytes。其中,SpareData主要是用來存放ECC(ErrorCorrecting Code)BadBlock InformationFileSystem的資料。

 

Figure 1.Flash MemoryGeometry
NANDFlash
的操作特點為:抹除(Erase)的最小單位是Block,而讀取(Read)和寫入(Write)則是以Page為單位。因NANDFlash的每個bit只能由1變為0,而不能從0變為1,所以對Flash做寫入時一定要將其對應的Block先抹除掉,才能做寫入的動作,也因此同樣一個page只能夠寫入一次。


Constraints andFunctionalities

Constraints

Sequential Pageprogram
在一個Block裡,Page必須從LSB(leastsignificant bit) Page依序寫到MSB(mostsignificant bit) Page,隨意不照Pageaddress來寫入是禁止的。另外,LSB是寫入的Pages中最小的位址,不一定是Page0

 
Figure2.Sequential Page program [1]


Partial Pageprogram
NANDFlash中,存取資料的最小單位是Page。在SLCFlash中,若想修改Page中的Data時可以更改部分的Bit而不需要將整個Page抹除後才更改。例如Page中的Data1001011101,若想將Data改成1001010001,只需將其中的2Bit更改為0即可,不用抹除後寫入。但之後的MLCFlash,已經不允許此功能了。


Performance-ImprovingCommands

Copy Back Program
CopyBack Program
可以快速地將1頁的資料複製(Copy)到另1個指定的頁中,也對於垃圾收集(GarbageCollection)非常的有用。例如當1頁裡的資料壞掉造成整個區塊(Block)為損壞區塊(BadBlock, or Worn-Out Block)時,CopyBack Program可以有效率地將所有有效頁(ValidPage)的資料複製到指定的區塊中。

Copy BackProgram是將1整頁的資料(來源Page)讀取且複製到內部頁緩衝器(InternalPageBuffer)中,再將它寫到另1整頁中(目標Page)。因為它不像一般的讀取、寫入指令將資料存取到外部記憶體(Memory),而是將資料存在內部頁緩衝器中,所以會比一般的讀取加上寫入少了將資料讀寫到外部記憶體的時間,執行上也更快且更有效率。


Figure 3.Copy BackProgram [1]


Random datainput/output
當對Page的資料做讀寫時,必須將1整頁的所有資料都存在於外部記憶體中,當外部的RAM不夠大時,無法一次存放整個頁的資料,故利用NANDFlashInternalPage Buffer來存放整個頁的資料,並使用RandomData Input/Output就可以對頁中任意位址的資料做存取。

1頁裡的資料做一般的讀寫時,資料都是Sequential的,但若想要隨意存取1頁裡的資料,如想要存取ECC的資料,便可使用Randomdata input/output跳至UserData的尾端去存取ECC的資料。


-Plane program
NANDFlash Vendor
MemoryArray分成2Plane,可以同時對2個不同BlockaddressesRead/Write/Erase的操作。

 
Figure 4.2-PlaneProgram [6]


NAND-flash ManagementIssues

Address Translation
NANDFlashMemory
的同1page不能做重覆寫入的行為。再者,在寫入1sector資料之前,必須要有抹除1Block的資料才能做寫入的動作,但抹除1Block的動作需要耗費相當多的時間,此舉造成了NANDFlash效能下降的最大原因。為了改善效能,最有效的方法就是減少Erase的次數,因此有了MappingTable

Mapping Table的管理分為BlocklevelSectorlevel以及改良的Hybridlevel

Block leveladdressmapping是指1LogicalBlock對應到1PhysicalBlock,它的mappingtable相對於sector-levelmappingtable來的小,能夠節省mappingtable所佔RAM的使用量。但當LogicalBlock的個數少於PhysicalBlock個數時,會發生LogicalBlock時常被overwrite的狀況,選定要overwriteLogicalblock和它mappingPhysicalBlock都要將資料更新到新的PhysicalBlock上,且做erase-before-write的動作,而造成效能的下降,此外轉換單位大,每次寫入的單位也大,因此會帶來額外的資料寫入成本。

Sector-Leveladdressmapping1LogicalSector可以對應到任1PhysicalBlock裡的Sector,雖然這種mapping的方式彈性佳,可以減少因轉換單位大而帶來額外的資料寫入成本,但是mappingtableSize過大,例如1GBFlash1sector的大小為512byte的話,RAM就要維護二百萬筆的sector資訊。

 
Figure 5.
資料區塊,紀錄區塊,以及備用區塊的使用。

(a)完整的資料區塊(b)資料依序寫入紀錄區塊的可寫頁中(c)區塊鏈的Merge

改良的Hybridlevel,擷取BlocklevelSectorlevel的優點,採用Blocklevel的方式,再加上有限數量的Block做為Sectorlevelmapping,除了讓mappingtablesize限制住不至於龐大,也減少了erase-before-write的動作。Hybridlevel中,將PhysicalBlock取名為資料區塊(DataBlock),因為資料不能直接更新於資料區塊裡,我們找了一段可寫的Block來紀錄更新的資料,並將它取名為紀錄區塊(LogBlock)。經過一段時間的寫入,一個LBA(LogicalBlock Address)對應會對應一個資料區塊,而此資料區塊會跟著數個紀錄區塊,整個形成一個區塊鏈(BlockChain),如圖5(b)所示。

 
Figure 6.HybridLevel mapping table [7]

HybridLevel在做write的時候,在寫第12筆資料時(sector4,5),會由blocklevelmappingtable找出DataBlock 10,因為對應sector裡內容是空的,因此就直接寫入DataBlock 10裡。而寫第3筆資料時(sector4),由Blocklevelmappingtable找到DataBlock 10,但裡面已有寫入的資料,故改由sectorlevelmappingtable找尋空的LogBlock,寫入第3筆資料。在寫第4筆資料時(sector4),因為sectorlevelmappingtable裡已有mappedLogBlock,故將第4筆資料依序寫入對映的LogBlock裡。

而在讀取時,會先由Sectorlevelmappingtable裡,找出最新的資料,而LogBlock裡沒有的資料,則由BlockLevel mapping table裡找到的DataBlock裡。


GarbageCollection
主要是用於將不必要存在且浪費空間的Block做回收,來增加可用的Block數。當需要新的LogBlock時,會從已經使用的LogBlock裡選取符合回收條件的Block來做GarbageCollection,如freesector低於threshold值。

被選定要回收的LogBlock,會和它的DataBlockmerge的動作,意即選取新的DataBlock,將LogBlocksector資料copy到此新的DataBlock中,再將原先DataBlock中剩餘的sector資料複製到此新的DataBlock中。

更新block-leveltable對應到新的DataBlock,並將sector-leveltable裡將剛纔回收的LogBlock移除。原先的LogBlockDataBlock做抹除的動作,即完成GarbageCollection了。

例如Figure4中,要將Logblock(pbn=20)做回收時,會將此logblock中最新的資料(sector4)複製到新的DataBlock(假設為pbn=12),再將它的Datablock(pbn=10)中,其餘的資料(sector5)複製到新的DataBlock(pbn=12)中。並將blocklevel table中對應到pbn=20的資料改為對應到pbn=12,即新的datablock,再將sectorlevel tablepbn=20(回收的logblock)這筆資料刪除。最後將pbn=20,pbn=10舊的block做抹除的動作即可。

Merge在一種特殊情況下,可以做switch的動作,例如像Figure4中,LogBlock(pbn=30)裡是照sector的順序寫入,因此它的DataBlock(pbn=11)裡的資料都是不需要使用的舊資料,要做GarbageCollection,只需要將LogBlockDataBlock對調即可,即block-leveltable裡對應到pbn=11這筆資料改為對應到pbn=30,而sector-leveltable裡對應到pbn=30這筆刪除,然後將舊的DataBlock(pbn=11)抹除就達到GarbageCollection了。


Figure 7.GarbageCollection Operation [3]

當在做GarbageCollection時,會希望用最少的cleaningwork來獲得最多的freespace,因此會選擇最多garbagesegment來做回收。另外,將資料的型態分為靜態和動態的資料。其中,Read-onlydata屬於靜態資料,即一旦創造就不會去修改它,而動態資料是會被修改的。動態資料依其資料修改頻率分為colddata(較少修改的資料)hotdata(修改頻繁的資料)

依不同的資料型態,做資料搬移時的方式也分為三種:


Read-only Data mix withdynamic data
當要被回收的segment中有read-onlydata時,會先將所有的read-onlydata搬到新的segment裡。若此新的segment又會被回收時,之前搬移過的read-onlydata仍然會再被搬移一次。另外,當一個segment中的資料都為read-onlydata時,則此segment永遠不會被回收的。

 
Figure8.Repeatedly migrating read-only data when they are mixed withdynamic data [9]


Cold data mix with hotdata
當要被回收的segment中有colddatahotdata時,因colddata更改的頻率較少,在cleaning的期間colddata有較高的可能性為valid的,因此會將colddata搬移到新的segment裡。

 
Figure 9.Migratingcold data when they are mixed with hot data [9]


Data have high localityof reference
當要被回收segment中的data是有高度被參考性的,這些hotdatacleaning的過程中仍可能是valid,但在被搬移到新的segment時,hotdata又被更新一次而成為garbage,這類的搬移即稱為uselessmigration


Figure 10.Uselessmigration when hot data are updated soon after being migrated [9]


Wear-Leveling
當在使用Flash時,常會對某個檔案做修改的動作,當此時檔案變動而要用到更多的PageFlash中仍有空的Block時,會將空的Block配置給此檔案來使用,若Flash中已經沒有空的Block時,則會執行GarbageCollection來清出空的Block以供使用。在挑選空的Block或執行GarbageCollection清出空的Block時,可能會造成部分的Block時常被挑選,這些Block可能因為被過度使用而造成損毀。為了避免這種情況發生,會使用Wear-Leveling,讓大部分Block的存取次數平均,而不會常常挑選到某些固定的Block上,造成Block的過度存取而損毀。

再者,NANDFlash抹除和寫入的reliability有使用的次數(100,000),使用wear-leveling可以紀錄並平均每個block被使用的次數。

Wear-Leveling有兩種方式來實現,一種是在FileSystemNANDFlash中間的FTL(FlashTranslation Layer)裡實現的。FTL可以讓上層的OS透過FTLdisk的方式去讀寫下層的NANDFlash,另外也提供了virtualaddressphysicaladdress的轉換。

 
Figure 11. WearLeveling in the FTL [4]

另一種的實現方法為WearLeveling直接在FileSystem裡實現,OS直接透過HALNANDFlash溝通。

 
Figure 12.WearLeveling in the File System [4]


Flow Chart

Read
 
Figure 13Read Operation Flow Chart


Erase
 
Figure14 Erase Operation Flow Chart


Write
 
Figure15 Write Operation Flow Chart


Timing/Power

Timing

ReadOperation
 
BandWidth
39.82MB/s


WriteOperation
 
BandWidth
4.66MB/s~1.36MB/s


Erase Operation
 

Power
P(typ)=3.3V*15mA=49.5mW
P(max)=3.6V*30mA=108mW


ReadOperation
E(typ)=49.5mW*(195+180+4224*25+100)ns=49.5mW*106075ns

=

 
J

E(max)=108mW*(195+180+4224*25+100)ns=108mW*106075ns

=

 
J


WriteOperation
E(typ)=49.5mW*(295+4224*25+100+

 
+200)ns

=49.5mW*906195ns

=

 
J

      E(max)=108mW*(295+4224*25+100+
 
+200)ns
 

=108mW*3106195ns

=

 
J


EraseOperation
E(typ)=49.5mW*(245+

 
+200)ns=49.5mW*1500445ns

=

 
J

E(max)=108mW*(245+

 
+200)ns=108mW*10000445ns

=

 
J


Reference
SamsungElectronics, "K9GAG08UXM Specification"
Alex Kuo,"Application Note: Partial Page Program MirrorBit ORNAND withNAND interface", Spansion
STMicroelectronics, "AN1821Garbage Collection in Single Level Cell NAND Flash memories"
STMicroelectronics, "AN1822 Wear Leveling in Single LevelCell NAND Flash memories"
STMicroelectronics, "AN1728How to use the Copy Back feature of ST Small Page NAND Flashmemories"
Amber Huffman, ONFI Technical Chair, "FlashPerformance Enhancements through ONFI", Intel Corporation
S.-W.Lee, D.-J. Park, T.-S. Chung, D.-H. Lee, S.-W. Park, H.-J. Song, "ALog Buffer-Based Flash Translation Layer Using Fully-AssociativeSector Translation", ACM Transactions on Embedded ComputingSystems, Vol.6,No.3,Article 18,Publication date: July 2007
STMicroelectronics, "AN1820 How to use the FTL and HALSoftware Modules to Manage Data in Single Level Cell NAND FlashMemories"
Mei-Ling Chiang, Paul C. H. Lee, Ruei-Chuan Chang,"Cleaning Policies in Mobile Computers Using Flash Memory",Journal of Systems and Software, v.48 n.3, p.213-231, Nov. 1, 1999

本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/renpine/archive/2009/09/19/4570538.aspx

爲什麼MicronNANDFlash能達到200MB/s的讀取速度

 

      今天看到新聞Intel,Micron claim world’s fastest NANDflash,就直接到Micron的網站上瀏覽了一下。Micron的新產品分類爲HighSpeed NAND Flash Products,用“HighSpeed”與原有NAND產品系列區分(估計ONFI3.0兼容的產品出來後,還要加上“Ultra”,才能再分出一個類別來)。 riple 
      Micron
HighSpeed系列目前按照容量分爲8Gb16Gb32Gb三種,按照接口個數分爲單端口(8Gb)和雙端口(1632Gb)兩種。在Micron的網站上還看不到詳細的datasheet,只能看到一個ProductBriefFlyer。 riple 
     
通過ProductBrief可以得到8Gb芯片的如下信息:採用了50nm而不是72nm工藝生產;是SLC而不是MLC結構;BGA封裝取代了TSOP封裝;4096Byte/Page128Page/Block512Blockx1/Plane4PlanesI/O分爲異步和同步(DDR)兩種模式;速度最高的同步傳輸模式,讀寫I/O時間都是6ns/Toggle;讀Array30us/Page,寫Array160us/Page,擦Array3ms/Block。 riple 
     
從上面的信息可以看出,HighSpeed特性要歸功於6ns/ToggleI/O時間,對於8bit的接口來說,相當於166MB/s的傳輸速度。 riple 
     
但是,NANDFlash的訪問速度不僅僅取決於I/O速度,還和Array傳輸時間、芯片內部緩衝結構和Plane數量有關。 riple

 

〇、NANDFlash訪問時間分析 riple

      訪問操作 命令輸入+I/O操作+Array傳輸操作,第一項的操作時間所佔比例很小,在性能估算中可以忽略。 riple 
     
訪問時間 = I/O時間+ Array傳輸時間,在上一代NANDFlash中,第一項佔的比例最大,是第二項的4-5倍。 riple

     Micron主要採用瞭如下的4種技術縮短了平均的訪問時間。其中第一種技術是第一次在NANDFlash上應用,也是這次“大提速”的核心技術。正是這項技術的採用,使上述公式中的第一項縮小到上一代的1/5,才使得其他3項技術發揮了最佳的效果。 riple

 

 

一、接口傳輸模式對I/O速度的影響 riple

      採用ONFi2.0提出的DDR接口,提高了I/O數據傳輸速率:源同步(縮小了建立保持時間要求)、雙邊沿觸發(加倍了數據傳輸速率)。 riple

 

二、Block結構和生產工藝對Array傳輸速度的影響 riple

      與上一代NANDFlash相比,Page容量加倍,在Array傳輸時間基本不變的情況下,等效地加倍了Array傳輸速度。 riple 
     72nm
50nm的工藝改進,縮小了芯片面積,提高了芯片速度(讀Array速度提升不明顯,寫Array速度提升了1倍),降低了功耗。 riple

 

 

三、緩衝與緩存對速度的影響 riple

      MicronNANDFlash的一大特點是:每一個Plane對應一個Page大小的緩衝(dataregister)和一個Page大小的緩存(cacheregister)。數據寫入的順序是:I/O-> cache register -> data register ->Plane,數據讀出的順序剛好相反。緩衝(dataregister)與緩存(cacheregister)之間的數據傳輸速度很快,dataregister可以把I/O操作和Array操作分隔開,形成I/O操作和Array操作的“兩級流水線”。這種結構與上一代NANDFlash一樣。(其實,4Plane對應4dataregister1cacheregister即可) riple

 

四、多Plane操作對速度的影響 riple

     4Plane對應4組緩衝與緩存,每一組可以分別操作。2Plane交替操作,可以實現“乒乓操作”,達到2倍的Array訪問帶寬。4Plane交替操作,可以實現“乒乒乓乓操作”,達到4倍的Array訪問帶寬。在上一代的NANDFlash芯片中,採用2Plane結構是比較常見的。 riple

 

五、200MB/s的讀速度和100MB/s的寫速度是怎樣得到的 riple

      I/O時間:1Toggle/Bytex 6ns/Toggle x 4096Byte/Page =24.6us/Page,與讀Array時間30us/Page近似。在採用cache模式的讀操作下,兩級流水線的速度取決於“I/O速度”和“讀Array速度”中較慢的一個,不採用多Plane操作,平均速度只能達到讀Array速度,即4096Byte/30us=136MB/s;在2Plane模式下,讀Array時間縮短至15us/Page,小於讀I/O時間24.6us/Page,兩級流水線的速度取決於“I/O速度”,平均速度達到I/O速度4096Byte/24.6us=166MB/s,這與宣傳中200MB/s的速度還有些差距。我們採用的I/O週期值是數據手冊給出的,芯片實際能夠運行的I/O速度往往要略高一些:在上面的分析中,只要I/O週期縮短至5ns/Toggle,“超頻”後的讀I/O時間就縮短至20us/Page,大於讀Array時間15us/Page,兩級流水線的速度仍然取決於“I/O速度”,這樣一來平均讀取速度就能達到4096Byte/20us=200MB/s。(從上面的分析看,如果不對I/O速度進行“超頻”,平均讀取速度是達不到200MB/s的,看來宣傳還是略有誇張的) riple 
     
I/O時間:1Toggle/Bytex 6ns/Toggle x 4096Byte/Page =24.6us/Page,與寫Array時間160us/Page相差很多,單獨採用cache模式不夠,還要採用4Plane的“乒乒乓乓操作”,縮短寫Array時間,儘量均衡流水線的兩級操作時間。4Plane模式平均Array寫操作時間爲一次Array寫操作時間的1/440us/Page。所以在cache模式配合4Plane模式的寫操作下,流水線的速度等於流水線兩級中最慢的“平均Array寫速度”,可以近似爲:4096Byte/40us =102MB/s。 riple

 

 

      從上面的分析可以看出,I/O速度限制了讀取速度的最大值,在ONFi3.0預計的400MB/sI/O速度實現後,NANDFlash的平均讀取速度也能夠達到400MB/s(這回就要採用4Plane模式了);Array傳輸速度限制了寫入速度的最大值,如果不對芯片的內部結構和生產工藝進行改進的話,NANDFlash的平均寫入速度很難進一步提高。 riple



nandflash總結

flash2009-12-09 13:21:37 閱讀118評論0  字號:大中小 訂閱

 

NANDFlash產品可以分爲三大架構,分別是SingleLevel CellSLC,包括三星電子、HynixMicron以及東芝都是此技術使用者,第二種則是MultiLevelCellMLC,目前有東芝、Renesas使用,不過三星電子將在2005第四季推出相關產品,最後則是InfineonSaifunSemiconductors合資利用NROM技術所共同開發的MultiBit CellMBC

MLCIntel19979月最先開發成功的,其作用是將兩個位的信息存入一個Floating GateNADAFlash存儲單元中存放電荷的部分),然後利用不同Level的電荷,透過內存儲存格的電壓控制精準讀寫,假設以4種電壓控制、1個晶體管可存取2bits的數據,若是控制8種電壓就可以存取3bits的數據,使Flash的容量大幅提升,類似RambusQRSL技術,通過精確控制浮動柵上的電荷數量,使其呈現出4種不同的存儲狀態,每種狀態代表兩個二進制數值(從0011)。

當然不光是NORNANDFlash在使用,東芝在20032月推出第一款MLC型的NANDFlash,並接續20044月推出採用MLC技術的4Gbit8GbitNAND Flash,顯然這對於本來就以容量見長的NANDFlash更是如虎添翼。根據SemiconductorInsights研究,東芝利用90nmMLC技術所開發出來的4Gb,其die面積爲144mm2

至於SLC技術與EEPROM相同,但在FloatinggateSourcegate之中的氧化薄膜更薄,其數據的寫入是透過對浮置閘極的電荷加電壓,然後可以透過源極,即可將所儲存的電荷消除,藉由這樣的方式,便可儲存1個個信息位,這種技術的單一位細胞方式能提供快速的程序編程與讀取,不過此技術受限於Siliconefficiency的問題,必須要藉由較先進的流程強化技術Processenhancements,才能向上提升SLC製程技術。

將上述所言,做一個比較,SLC架構是01兩個充電值,而MLC架構可以一次儲存4個以上的充電值,因此MLC架構可以有比較好的儲存密度,再加上可利用比較老舊的生產設備來提高產品的容量,而無須額外投資生產設備,可以享有成本與良率的優勢。

不過MLC架構有着讓使用者很難容忍的缺點,就是使用壽命較短,其次MLC架構只能承受約1萬次的存取,遠低於SLC架構的10萬次。至於存取速度,SLC架構比MLC架構要快速三倍以上,加上MLC架構對於電力的消耗較多,因此使用者若是考慮長久使用、安全儲存數據以及高速的存取速度等要求,恐怕會改採用SLC架構。

其實在NANDFlash市場中,若以理論數據比較,RenesasAG-AND技術或是InfineonMBC技術,其實並不遜於三星電子、東芝或是其它業者,甚至於有過之而無不及,不過這兩家業者因爲產能、技術開發等問題造成延遲擴大市場佔有率時機,這也印證商場中的一句話,任何東西都必須要能夠適時適地推出,否則只是將市場拱手讓給對方。

Nand Flash結構與讀寫分析

NAND Flash 的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。這些Line會再組成Page(NandFlash有多種結構,我使用的NandFlashK9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32page形成一個BlockSizeof(block)=16kByte1block=16kbyte512Mbit=64MbyteNumberof(block)=10241block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

Nand flash以頁爲單位讀寫數據,而以塊爲單位擦除數據。按照這樣的組織方式可以形成所謂的三類地址:--Block Address --Page Address   --Column Address(即爲頁內偏移地址)

對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度是8位。

512byte需要9bit來表示,對於528byte系列的NAND,這512byte被分成1st half2ndhalf,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的columnaddress32page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,則blockaddressA[26:14]表示。而pageaddress就是blcokaddress|page address in block, NAND Flash 的地址表示爲:Block Address|PageAddress in block|halfpage pointer|Column Address地址傳送順序是ColumnAddress,Page Address,Block Address。由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR爲例: 第1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上,而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫。而真正的bit8的值是don\'tcare的。 第2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0]上第3步將NAND_ADDR[24:17]放到I/O上 第4步需要將NAND_ADDR[25]放到I/O上 因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing。 如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。

下面,就x16NANDflash器件稍微進行一下說明。由於一個pagemainarea的容量爲256word,仍相當於512byte。但是,這個時候沒有所謂的1st halfpage 2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個時候bit8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點之外,x16NAND使用方法和x8的使用方法完全相同。

norflashnandflash的區別

norflash中可以運行程序,nandflash不可以

Norflashsector可擦除,按bit可讀寫。NandFlashBlock可擦除,按Page可讀寫。

最主要是尋址方式不同

*********************************************************************************************************************************

Nand Flash 尋址方式

NAND Flash的尋址方式和NANDFlashmemory組織方式緊密相關。NANDFlash的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。

    這些Line會再組成Page,通常是528Byte/page或者264Word/page。然後,每32page形成一個BlockSizeof(block)=16kByte.

     BlockNANDFlash中最大的操作單元,擦除就是按照block爲單位完成的,而

編程/讀取是按照page爲單位完成的。

     所以,按照這樣的組織方式可以形成所謂的三類地址:

     -Block  Address

     -Page   Address

     -ColumnAddress

     首先,必須清楚一點,對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度可以是8位或者16位,但是,對於x16NANDDeviceI/O[15:8]只用於傳遞數據。

     清楚了這一點,我們就可以開始分析NANDFlash的尋址方式了。

     528Byte/page總容量512Mbit+512kbyteNAND器件爲例:

因爲,

     1block=16kbyte

     512Mbit=64Mbyte

     Numberof(block)=1024

     1block=32page,

     1page=528byte=512byte(MainArea)+16byte(Spare Area)

用戶數據保存在mainarea中。

    512byte需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由所謂的pointeroperation命令來選擇,也就是選擇了bit8的高低。因此A8就是halfpagepointerA[7:0]就是所謂的columnaddress

    32page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,共8192block,則blockaddressA[26:14]表示。而pageaddress就是blcokaddress|page address in block

NAND Flash的地址表示爲:

      BlockAddress|Page Address in block|halfpage pointer|Column Address

地址傳送順序是ColumnAddress,Page Address,Block Address

由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。

     例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。

NAND_ADDR爲例:

     1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫,而真正的bit8的值是don'tcare的。

    2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0];

     3步將NAND_ADDR[24:17]放到I/O;

     4步需要將NAND_ADDR[25]放到I/O;

     因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing

     如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。

NAND Flash 的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。這些Line會再組成Page.

(Nand Flash有多種結構,下面內容針對三星的K9F1208U0M),每頁528Byte,每32page形成一個BlockSizeof(block)=16kByte

1 block="16kbyte"

512Mbit=64Mbyte

Numberof(block)=40961block=32page

1page=528byte=512byte(MainArea)+16byte(Spare Area)

Nand flash以頁爲單位讀寫數據,而以塊爲單位擦除數據。

按照這樣的組織方式可以形成所謂的三類地址:

--Block Address

-- Page Address

--Column Address

對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度是8位。

512byte需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的columnaddress

32 page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,則blockaddressA[26:24]表示。而pageaddress就是blcokaddress|page address in block

NAND Flash 的地址表示爲:

Block Address|Page Addressin block|halfpage pointer|Column Address

地址傳送順序是ColumnAddressPageAddressBlockAddress

由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。

NAND_ADDR爲例:

1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上,而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫。而真正的bit8的值是don'tcare的。

2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0]

3步將NAND_ADDR[24:17]放到I/O

4步需要將NAND_ADDR[25]放到I/O

因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing。 如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。下面,就x16NANDflash器件稍微進行一下說明。由於一個pagemainarea的容量爲256word,仍相當於512byte。但是,這個時候沒有所謂的1st halfpage 2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個時候bit8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點之外,x16NAND使用方法和x8的使用方法完全相同。

正如硬盤的盤片被分爲磁道,每個磁道又分爲若干扇區,一塊nandflash也分爲若干block,每個block分爲如干page。一般而言,blockpage之間的關係隨着芯片的不同而不同,典型的分配是這樣的:

1block = 32page

1page = 512bytes(datafield)+ 16bytes(oob)

需要注意的是,對於flash的讀寫都是以一個page開始的,但是在讀寫之前必須進行flash的擦寫,而擦寫則是以一個block爲單位的。同時必須提醒的是,512bytes理論上被分爲1sthalf2sdhalf,每個half各佔256個字節。

我們討論的K9F1208U0B總共有4096Blocks,故我們可以知道這塊flash的容量爲4096*(32 *528)= 69206016 Bytes = 66 MB但事實上每個Page上的最後16Bytes是用於存貯檢驗碼和其他信息用的,並不能存放實際的數據,所以實際上我們可以操作的芯片容量爲4096*(32 *512) = 67108864 Bytes = 64 MB由上圖所示,1Page總共由528Bytes組成,這528個字節按順序由上而下以列爲單位進行排列(1列代表一個Byte。第0行爲第0Byte,第1行爲第1Byte,以此類推,每個行又由8個位組成,每個位表示1Byte裏面的1bit)。這528Bytes按功能分爲兩大部分,分別是DataFieldSpareField,其中SpareField528Bytes裏的16Bytes,16Bytes是用於在讀寫操作的時候存放校驗碼用的,一般不用做普通數據的存儲區,除去這16Bytes,剩下的512Bytes便是我們用於存放數據用的DataField,所以一個Page上雖然有528Bytes,但我們只按512Bytes進行容量的計算。

讀 命令有兩個,分別是Read1,Read2其中Read1用於讀取DataField的數據,而Read2則是用於讀取SpareField的數據。對於NandFlash來說,讀操作的最小操作單位爲Page,也就是說當我們給定了讀取的起始位置後,讀操作將從該位置開始,連續讀取到本Page的最後一個Byte爲止(可以包括SpareField

Nand Flash的尋址

    NandFlash的地址寄存器把一個完整的NandFlash地址分解成ColumnAddressPageAddress.進行尋址。

Column Address: 列地址。ColumnAddress其實就是指定Page上的某個Byte,指定這個Byte其實也就是指定此頁的讀寫起始地址。

PaageAddress:頁地址。由於頁地址總是以512Bytes對齊的,所以它的低9位總是0。確定讀寫操作是在Flash上的哪個頁進行的。

Read1命令

當我們得到一個NandFlash地址src_addr時我們可以這樣分解出ColumnAddressPageAddress

column_addr=src_addr%512;                    // column address

page_address=(src_addr>>9);                     // page address

也可以這麼認爲,一個NandFlash地址的A0~A7是它的column_addrA9~A25是它的PageAddress(注意地址位A8並沒有出現,也就是A8被忽略,在下面你將瞭解到這是什麼原因)

Read1命令的操作分爲4Cycle,發送完讀命令00h01h00h01h的區別請見下文描述)之後將分4Cycle發送參數,1st.Cycle是發送ColumnAddress2nd.Cycle,3rd.Cycle4th.Cycle則是指定PageAddress(每次向地址寄存器發送的數據只能是8位,所以17位的PageAddress必須分成3次進行發送

Read1的命令裏面出現了兩個命令選項,分別是00h01h。這裏出現了兩個讀命是否令你意識到什麼呢?是的,00h是用於讀寫1sthalf的命令,而01h是用於讀取2ndhalf的命令。現在我可以結合上圖給你說明爲什麼K9F1208U0BDataField被分爲2half了。

如上文我所提及的,Read11st.Cycle是發送ColumnAddress,假設我現在指定的ColumnAddress0,那麼讀操作將從此頁的第0Byte開始一直讀取到此頁的最後一個Byte(包括SpareField),如果我指定的ColumnAddress127,情況也與前面一樣,但不知道你發現沒有,用於傳遞ColumnAddress的數據線有8條(I/O0~I/O7,對應A0~A7,這也是A8爲什麼不出現在我們傳遞的地址位中),也就是說我們能夠指定的ColumnAddress範圍爲0~255,但不要忘了,1PageDataField是由512Byte組成的,假設現在我要指定讀命令從第256個字節處開始讀取此頁,那將會發生什麼情景?我必須把ColumnAddress設置爲256,但ColumnAddress最大隻能是255,這就造成數據溢出。。。正是因爲這個原因我們才把DataField分爲兩個半區,當要讀取的起始地址(ColumnAddress)在0~255內時我們用00h命令,當讀取的起始地址是在256~511時,則使用01h命令.假設現在我要指定從第256byte開始讀取此頁,那麼我將這樣發送命令串

column_addr=256;

NF_CMD=0x01; ?                                  2ndhalf開始讀取

NF_ADDR=column_addr&0xff;                     1st Cycle

NF_ADDR=page_address&0xff;                 2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;         3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;          4th.Cycle

其中NF_CMDNF_ADDR分別是NandFlash的命令寄存器和地址寄存器的地址解引用,我一般這樣定義它們,

#define rNFCMD       (*(volatile unsigned char *)0x4e000004)       //NADD Flash command

#define rNFADDR       (*(volatile unsigned char *)0x4e000008)       //NAND Flash address

事實上,當NF_CMD=0x01時,地址寄存器中的第8位(A8)將被設置爲1(如上文分析,A8位不在我們傳遞的地址中,這個位其實就是硬件電路根據01h或是00h這兩個命令來置高位或是置低位),這樣我們傳遞column_addr的值256隨然由於數據溢出變爲1,但A8位已經由於NF_CMD=0x01的關係被置爲1了,所以我們傳到地址寄存器裏的值變成了

A0   A1  A2   A3   A4   A5   A6  A7   A8

1     0   0    0 0     0 0 0    1

8個位所表示的正好是256,這樣讀操作將從此頁的第256byte2ndhalf的第0byte)開始讀取數據。nand_flash.c中包含3個函數

void nf_reset(void);

void nf_init(void);

void nf_read(unsigned intsrc_addr,unsigned   char *desc_addr,int size);

nf_reset()將被nf_init()調用。nf_init()nand_flash的初始化函數,在對nandflash進行任何操作之前,nf_init()必須被調用。

nf_read(unsigned intsrc_addr,unsigned   char *desc_addr,intsize);爲讀函數,src_addrnandflash上的地址,desc_addr是內存地址,size是讀取文件的長度。

nf_resetnf_read函數中存在兩個宏

NF_nFCE_L();

NF_nFCE_H();

你可以看到當每次對NandFlash進行操作之前NF_nFCE_L()必定被調用,操作結束之時NF_nFCE_H()必定被調用。這兩個宏用於啓動和關閉Flash芯片的工作(片選/取消片選)。至於nf_reset()中的

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

這一行代碼是對NandFlash的控制寄存器進行初始化配置,rNFCONFNandFlash的配置寄存器,各個位的具體功能請參閱s3c2410數據手冊。

現在舉一個例子,假設我要從NandFlash中的第5000字節處開始讀取1024個字節到內存的0x30000000處,我們這樣調用read函數

nf_read(5000,0x30000000,1024);

我們來分析5000這個src_addr.

根據

column_addr=src_addr%512;      

page_address=(src_addr>>9);  

我們可得出column_addr=5000%512=392

page_address=(5000>>9)=9

於是我們可以知道5000這個地址是在第9頁的第392個字節處,於是我們的nf_read函數將這樣發送命令和參數

column_addr=5000%512;

>page_address=(5000>>9);

NF_CMD=0x01;                                     2ndhalf開始讀取

NF_ADDR= column_addr &0xff;                 1st Cycle

NF_ADDR=page_address&0xff;                 2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;         3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;          4th.Cycle

NandFlash的命令寄存器和地址寄存器發送完以上命令和參數之後,我們就可以從rNFDATA寄存器(NandFlash數據寄存器)讀取數據了.

我用下面的代碼進行數據的讀取.

for(i=column_addr;i<512;i++)

{

       *buf++=NF_RDDATA();

}

每當讀取完一個Page之後,數據指針會落在下一個Page0Column(0Byte).

下面是源代碼:

/*

    http://www.another-prj.com/    

    author:caiyuqing    

    本代碼只屬於交流學習,不得用於商業開發

*/

#include "s3c2410.h"

#include "nand_flash.h"

static unsigned charseBuf[16]={0xff};

//--------------------------------------------------------------------------------------

unsigned shortnf_checkId(void)

{

    int i;

    unsignedshort id;

    NF_nFCE_L();       //chip enable

   

    NF_CMD(0x90);       //Read ID

    NF_ADDR(0x0);

    for(i=0;i<10;i++);   //wait tWB(100ns)

   

    id="NF"_RDDATA()<<8;   // Maker code(K9S1208V:0xec)

    id|=NF_RDDATA();   // Devide code(K9S1208V:0x76)

   

    NF_nFCE_H();       //chip enable

    returnid;

}

//--------------------------------------------------------------------------------------

static void nf_reset(void)

{

    int i;

    NF_nFCE_L();       //chip enable

    NF_CMD(0xFF);       //reset command

    for(i=0;i<10;i++);    //tWB = 100ns.

    NF_WAITRB();        //wait 200~500us;

    NF_nFCE_H();       //chip disable

}

//--------------------------------------------------------------------------------------

void nf_init(void)

{

   rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);   

    //        1     1       1         1      1      xxx     rxxx,      r xxx       

    //        En     r   r       ECCR    nFCE="H"tACLS   tWRPH0      tWRPH1

    nf_reset();

}

//--------------------------------------------------------------------------------------

void nf_read(unsigned intsrc_addr,unsigned char *desc_addr,int size)

{

    int i;

    unsignedint column_addr = src_addr % 512;           // column address

    unsignedint page_address = (src_addr >> 9);       // page addrress

    unsignedchar *buf = desc_addr;

    while((unsignedint)buf < (unsigned int)(desc_addr) + size)

    {

        NF_nFCE_L();                  // enable chip

       

       /*NF_ADDRNF_CMDnand_flash的地址和命令寄存器的解引用*/

        if(column_addr> 255)               // 2end halft   

           NF_CMD(0x01);               // Read2command.   cmd 0x01: Read command(start from 2end halfpage)       

        else

           NF_CMD(0x00);               // 1sthalft?

       

        NF_ADDR(column_addr& 0xff);               // Column Address

        NF_ADDR(page_address& 0xff);           // Page Address

        NF_ADDR((page_address>> 8) & 0xff);        // ...

        NF_ADDR((page_address>> 16) & 0xff);        // ..

        for(i= 0; i < 10; i++);               // wait tWB(100ns)/////??????

           NF_WAITRB();                  // Wait tR(max 12us)

   

        //Read from main area

        for(i= column_addr; i < 512; i++)

        {

            *buf++=NF_RDDATA();

        }

        NF_nFCE_H();                  // disable chip

        column_addr= 0;

        page_address++;

    }

    return ;

}

今天在利用ARM7上的nandflash控制器驅動,ID已讀取成功,擦寫,讀取等尚未完成,晚上就在網上查查相關的知識,覺得有一個不錯,轉貼如下:

NAND Flash 的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。這些Line會再組成Page.

(Nand Flash 有多種結構,我使用的NandFlashK9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32page形成一個BlockSizeof(block)=16kByte

1block="16kbyte"512Mbit=64MbyteNumberof(block)=40961block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

Nand flash以頁爲單位讀寫數據,而以塊爲單位擦除數據。

按照這樣的組織方式可以形成所謂的三類地址:

--Block Address -- PageAddress --Column Address

對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度是8位。

512byte需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的columnaddress

32 page需要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A[25:14],如果是1Gbit528byte/pageNANDFlash,則blockaddressA[26:24]表示。而pageaddress就是blcokaddress|page address in block

NAND Flash 的地址表示爲:

Block Address|Page Addressin block|halfpage pointer|Column Address

地址傳送順序是ColumnAddress,Page Address,Block Address

由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR爲例: 第1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上,而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫。而真正的bit8的值是don'tcare的。 第2步就是將NAND_ADDR右移9位,將NAND_ADDR[16:9]傳到I/O[7:0]上第3步將NAND_ADDR[24:17]放到I/O上 第4步需要將NAND_ADDR[25]放到I/O上 因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing。 如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。下面,就x16NANDflash器件稍微進行一下說明。由於一個pagemainarea的容量爲256word,仍相當於512byte。但是,這個時候沒有所謂的1st halfpage 2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個時候bit8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點之外,x16NAND使用方法和x8的使用方法完全相同。

正如硬盤的盤片被分爲磁道,每個磁道又分爲若干扇區,一塊nandflash也分爲若干block,每個block分爲如干page。一般而言,blockpage之間的關係隨着芯片的不同而不同,典型的分配是這樣的:

1block = 32page

1page = 512bytes(datafield)+ 16bytes(oob)

需要注意的是,對於flash的讀寫都是以一個page開始的,但是在讀寫之前必須進行flash的擦寫,而擦寫則是以一個block爲單位的。同時必須提醒的是,512bytes理論上被分爲1sthalf2sdhalf,每個half各佔256個字節。

我們討論的K9F1208U0B總共有4096Blocks,故我們可以知道這塊flash的容量爲4096*(32 *528)= 69206016 Bytes = 66 MB但事實上每個Page上的最後16Bytes是用於存貯檢驗碼和其他信息用的,並不能存放實際的數據,所以實際上我們可以操作的芯片容量爲4096*(32 *512) = 67108864 Bytes = 64 MB由上圖所示,1Page總共由528Bytes組成,這528個字節按順序由上而下以列爲單位進行排列(1列代表一個Byte。第0行爲第0Byte,第1行爲第1Byte,以此類推,每個行又由8個位組成,每個位表示1Byte裏面的1bit)。這528Bytes按功能分爲兩大部分,分別是DataFieldSpareField,其中SpareField528Bytes裏的16Bytes,16Bytes是用於在讀寫操作的時候存放校驗碼用的,一般不用做普通數據的存儲區,除去這16Bytes,剩下的512Bytes便是我們用於存放數據用的DataField,所以一個Page上雖然有528Bytes,但我們只按512Bytes進行容量的計算。

讀 命令有兩個,分別是Read1,Read2其中Read1用於讀取DataField的數據,而Read2則是用於讀取SpareField的數據。對於NandFlash來說,讀操作的最小操作單位爲Page,也就是說當我們給定了讀取的起始位置後,讀操作將從該位置開始,連續讀取到本Page的最後一個Byte爲止(可以包括SpareField

Nand Flash的尋址

    NandFlash的地址寄存器把一個完整的NandFlash地址分解成ColumnAddressPageAddress.進行尋址。

Column Address: 列地址。ColumnAddress其實就是指定Page上的某個Byte,指定這個Byte其實也就是指定此頁的讀寫起始地址。

PaageAddress:頁地址。由於頁地址總是以512Bytes對齊的,所以它的低9位總是0。確定讀寫操作是在Flash上的哪個頁進行的。

Read1命令

當我們得到一個NandFlash地址src_addr時我們可以這樣分解出ColumnAddressPageAddress

column_addr=src_addr%512;                    // column address

page_address=(src_addr>>9);                     // page address

也可以這麼認爲,一個NandFlash地址的A0~A7是它的column_addrA9~A25是它的PageAddress(注意地址位A8並沒有出現,也就是A8被忽略,在下面你將瞭解到這是什麼原因)

Read1命令的操作分爲4Cycle,發送完讀命令00h01h00h01h的區別請見下文描述)之後將分4Cycle發送參數,1st.Cycle是發送ColumnAddress2nd.Cycle,3rd.Cycle4th.Cycle則是指定PageAddress(每次向地址寄存器發送的數據只能是8位,所以17位的PageAddress必須分成3次進行發送

Read1的命令裏面出現了兩個命令選項,分別是00h01h。這裏出現了兩個讀命是否令你意識到什麼呢?是的,00h是用於讀寫1sthalf的命令,而01h是用於讀取2ndhalf的命令。現在我可以結合上圖給你說明爲什麼K9F1208U0BDataField被分爲2half了。

如上文我所提及的,Read11st.Cycle是發送ColumnAddress,假設我現在指定的ColumnAddress0,那麼讀操作將從此頁的第0Byte開始一直讀取到此頁的最後一個Byte(包括SpareField),如果我指定的ColumnAddress127,情況也與前面一樣,但不知道你發現沒有,用於傳遞ColumnAddress的數據線有8條(I/O0~I/O7,對應A0~A7,這也是A8爲什麼不出現在我們傳遞的地址位中),也就是說我們能夠指定的ColumnAddress範圍爲0~255,但不要忘了,1PageDataField是由512Byte組成的,假設現在我要指定讀命令從第256個字節處開始讀取此頁,那將會發生什麼情景?我必須把ColumnAddress設置爲256,但ColumnAddress最大隻能是255,這就造成數據溢出。。。正是因爲這個原因我們才把DataField分爲兩個半區,當要讀取的起始地址(ColumnAddress)在0~255內時我們用00h命令,當讀取的起始地址是在256~511時,則使用01h命令.假設現在我要指定從第256byte開始讀取此頁,那麼我將這樣發送命令串

column_addr=256;

NF_CMD=0x01; ?                                  2ndhalf開始讀取

NF_ADDR=column_addr&0xff;                     1st Cycle

NF_ADDR=page_address&0xff;                 2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;         3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;          4th.Cycle

其中NF_CMDNF_ADDR分別是NandFlash的命令寄存器和地址寄存器的地址解引用,我一般這樣定義它們,

#define rNFCMD       (*(volatile unsigned char *)0x4e000004)       //NADD Flash command

#define rNFADDR       (*(volatile unsigned char *)0x4e000008)       //NAND Flash address

事實上,當NF_CMD=0x01時,地址寄存器中的第8位(A8)將被設置爲1(如上文分析,A8位不在我們傳遞的地址中,這個位其實就是硬件電路根據01h或是00h這兩個命令來置高位或是置低位),這樣我們傳遞column_addr的值256隨然由於數據溢出變爲1,但A8位已經由於NF_CMD=0x01的關係被置爲1了,所以我們傳到地址寄存器裏的值變成了

A0   A1  A2   A3   A4   A5   A6  A7   A8

1     0   0    0 0     0 0 0    1

8個位所表示的正好是256,這樣讀操作將從此頁的第256byte2ndhalf的第0byte)開始讀取數據。nand_flash.c中包含3個函數

void nf_reset(void);

void nf_init(void);

void nf_read(unsigned intsrc_addr,unsigned   char *desc_addr,int size);

nf_reset()將被nf_init()調用。nf_init()nand_flash的初始化函數,在對nandflash進行任何操作之前,nf_init()必須被調用。

nf_read(unsigned intsrc_addr,unsigned   char *desc_addr,intsize);爲讀函數,src_addrnandflash上的地址,desc_addr是內存地址,size是讀取文件的長度。

nf_resetnf_read函數中存在兩個宏

NF_nFCE_L();

NF_nFCE_H();

你可以看到當每次對NandFlash進行操作之前NF_nFCE_L()必定被調用,操作結束之時NF_nFCE_H()必定被調用。這兩個宏用於啓動和關閉Flash芯片的工作(片選/取消片選)。至於nf_reset()中的

rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

這一行代碼是對NandFlash的控制寄存器進行初始化配置,rNFCONFNandFlash的配置寄存器,各個位的具體功能請參閱s3c2410數據手冊。

現在舉一個例子,假設我要從NandFlash中的第5000字節處開始讀取1024個字節到內存的0x30000000處,我們這樣調用read函數

nf_read(5000,0x30000000,1024);

我們來分析5000這個src_addr.

根據

column_addr=src_addr%512;      

page_address=(src_addr>>9);  

我們可得出column_addr=5000%512=392

page_address=(5000>>9)=9

於是我們可以知道5000這個地址是在第9頁的第392個字節處,於是我們的nf_read函數將這樣發送命令和參數

column_addr=5000%512;

>page_address=(5000>>9);

NF_CMD=0x01;                                     2ndhalf開始讀取

NF_ADDR= column_addr &0xff;                 1st Cycle

NF_ADDR=page_address&0xff;                 2nd.Cycle

NF_ADDR=(page_address>>8)&0xff;         3rd.Cycle

NF_ADDR=(page_address>>16)&0xff;          4th.Cycle

NandFlash的命令寄存器和地址寄存器發送完以上命令和參數之後,我們就可以從rNFDATA寄存器(NandFlash數據寄存器)讀取數據了.

我用下面的代碼進行數據的讀取.

for(i=column_addr;i<512;i++)

{

       *buf++=NF_RDDATA();

}

每當讀取完一個Page之後,數據指針會落在下一個Page0Column(0Byte).

下面是源代碼:

/*

    http://www.another-prj.com/    

    author:caiyuqing    

    本代碼只屬於交流學習,不得用於商業開發

*/

#include "s3c2410.h"

#include "nand_flash.h"

static unsigned charseBuf[16]={0xff};

//--------------------------------------------------------------------------------------

unsigned shortnf_checkId(void)

{

    int i;

    unsignedshort id;

    NF_nFCE_L();       //chip enable

   

    NF_CMD(0x90);       //Read ID

    NF_ADDR(0x0);

    for(i=0;i<10;i++);   //wait tWB(100ns)

   

    id="NF"_RDDATA()<<8;   // Maker code(K9S1208V:0xec)

    id|=NF_RDDATA();   // Devide code(K9S1208V:0x76)

   

    NF_nFCE_H();       //chip enable

    returnid;

}

//--------------------------------------------------------------------------------------

static void nf_reset(void)

{

    int i;

    NF_nFCE_L();       //chip enable

    NF_CMD(0xFF);       //reset command

    for(i=0;i<10;i++);    //tWB = 100ns.

    NF_WAITRB();        //wait 200~500us;

    NF_nFCE_H();       //chip disable

}

//--------------------------------------------------------------------------------------

void nf_init(void)

{

   rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);   

    //        1     1       1         1      1      xxx     rxxx,      r xxx       

    //        En     r   r       ECCR    nFCE="H"tACLS   tWRPH0      tWRPH1

    nf_reset();

}

//--------------------------------------------------------------------------------------

void nf_read(unsigned intsrc_addr,unsigned char *desc_addr,int size)

{

    int i;

    unsignedint column_addr = src_addr % 512;           // column address

    unsignedint page_address = (src_addr >> 9);       // page addrress

    unsignedchar *buf = desc_addr;

    while((unsignedint)buf < (unsigned int)(desc_addr) + size)

    {

        NF_nFCE_L();                  // enable chip

       

       /*NF_ADDRNF_CMDnand_flash的地址和命令寄存器的解引用*/

        if(column_addr> 255)               // 2end halft   

           NF_CMD(0x01);               // Read2command.   cmd 0x01: Read command(start from 2end halfpage)       

        else

           NF_CMD(0x00);               // 1sthalft?

       

        NF_ADDR(column_addr& 0xff);               // Column Address

        NF_ADDR(page_address& 0xff);           // Page Address

        NF_ADDR((page_address>> 8) & 0xff);        // ...

        NF_ADDR((page_address>> 16) & 0xff);        // ..

        for(i= 0; i < 10; i++);               // wait tWB(100ns)/////??????

           NF_WAITRB();                  // Wait tR(max 12us)

   

        //Read from main area

        for(i= column_addr; i < 512; i++)

        {

            *buf++=NF_RDDATA();

        }

        NF_nFCE_H();                  // disable chip

        column_addr= 0;

        page_address++;

    }

    return ;

}

 

NandFlash結構與讀寫分析



今天在利用ARM7上的nandflash控制器驅動,ID已讀取成功,擦寫,讀取等尚未完成,晚上就在網上查查相關的知識,覺得有一個不錯,轉貼如下:

NAND Flash
的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。這些Line會再組成Page.
(Nand Flash
有多種結構,我使用的NandFlashK9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32page形成一個BlockSizeof(block)=16kByte
1block="16kbyte"
512Mbit=64MbyteNumberof(block)=40961block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)
Nand flash
以頁爲單位讀寫數據,而以塊爲單位擦除數據。
按照這樣的組織方式可以形成所謂的三類地址:
--BlockAddress-- PageAddress--ColumnAddress
對於NANDFlash來講,地址和命令只能在I/O7:0】上傳遞,數據寬度是8位。
512byte
需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf2ndhalf,各自的訪問由地址指針命令來選擇,A7:0】就是所謂的columnaddress
32
page需要5bit來表示,佔用A13:9】,即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512MbNAND,共4096block,因此,需要12bit來表示,即A25:14】,如果是1Gbit528byte/pageNANDFlash,則blockaddressA26:24】表示。而pageaddress就是blcokaddress|page address in block

NAND Flash
的地址表示爲:
BlockAddress|Page Address in block|halfpage pointer|Column Address
地址傳送順序是ColumnAddress,Page Address,Block Address
由於地址只能在I/O7:0】上傳遞,因此,必須採用移位的方式進行。例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR爲例: 第1步是傳遞columnaddress,就是NAND_ADDR7:0】,不需移位即可傳遞到I/O7:0】上,而halfpagepointerbit8是由操作指令決定的,即指令決定在哪個halfpage上進行讀寫。而真正的bit8的值是don‘tcare的。 第2步就是將NAND_ADDR右移9位,將NAND_ADDR16:9】傳到I/O7:0】上第3步將NAND_ADDR24:17】放到I/O上 第4步需要將NAND_ADDR25】放到I/O上 因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing。 如果NANDFlash的容量是256Mbit以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。下面,就x16NANDflash器件稍微進行一下說明。由於一個pagemainarea的容量爲256word,仍相當於512byte。但是,這個時候沒有所謂的1st halfpage 2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個時候bit8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點之外,x16NAND使用方法和x8的使用方法完全相同。



正如硬盤的盤片被分爲磁道,每個磁道又分爲若干扇區,一塊nandflash也分爲若干block,每個block分爲如干page。一般而言,blockpage之間的關係隨着芯片的不同而不同,典型的分配是這樣的:
1block = 32page
1page = 512bytes(datafield) + 16bytes(oob)


需要注意的是,對於flash的讀寫都是以一個page開始的,但是在讀寫之前必須進行flash的擦寫,而擦寫則是以一個block爲單位的。同時必須提醒的是,512bytes理論上被分爲1sthalf2sdhalf,每個half各佔256個字節。

我們討論的K9F1208U0B總共有4096Blocks,故我們可以知道這塊flash的容量爲4096*(32 *528)= 69206016 Bytes = 66 MB但事實上每個Page上的最後16Bytes是用於存貯檢驗碼和其他信息用的,並不能存放實際的數據,所以實際上我們可以操作的芯片容量爲4096*(32 *512) = 67108864 Bytes = 64 MB由上圖所示,1Page總共由528Bytes組成,這528個字節按順序由上而下以列爲單位進行排列(1列代表一個Byte。第0行爲第0Byte,第1行爲第1Byte,以此類推,每個行又由8個位組成,每個位表示1Byte裏面的1bit)。這528Bytes按功能分爲兩大部分,分別是DataFieldSpareField,其中SpareField528Bytes裏的16Bytes,16Bytes是用於在讀寫操作的時候存放校驗碼用的,一般不用做普通數據的存儲區,除去這16Bytes,剩下的512Bytes便是我們用於存放數據用的DataField,所以一個Page上雖然有528Bytes,但我們只按512Bytes進行容量的計算。

讀命令有兩個,分別是 Read1,Read2其中Read1用於讀取DataField的數據,而Read2則是用於讀取SpareField的數據。對於NandFlash來說,讀操作的最小操作單位爲Page,也就是說當我們給定了讀取的起始位置後,讀操作將從該位置開始,連續讀取到本Page的最後一個Byte爲止(可以包括SpareField

NandFlash
的尋址
NandFlash
的地址寄存器把一個完整的NandFlash地址分解成ColumnAddressPageAddress.進行尋址。
ColumnAddress:
列地址。ColumnAddress其實就是指定Page上的某個Byte,指定這個Byte其實也就是指定此頁的讀寫起始地址。
PaageAddress
:頁地址。由於頁地址總是以512Bytes對齊的,所以它的低9位總是0。確定讀寫操作是在Flash上的哪個頁進行的。
Read1
命令
當我們得到一個NandFlash地址src_addr時我們可以這樣分解出ColumnAddressPageAddress
column_addr=src_addr%512; // column address
page_address=(src_addr>>9); // page address
也可以這麼認爲,一個NandFlash地址的A0~A7是它的column_addrA9~A25是它的PageAddress(注意地址位A8並沒有出現,也就是A8被忽略,在下面你將瞭解到這是什麼原因)
Read1
命令的操作分爲4Cycle,發送完讀命令00h01h00h01h的區別請見下文描述)之後將分4Cycle發送參數,1st.Cycle是發送ColumnAddress2nd.Cycle,3rd.Cycle4th.Cycle則是指定PageAddress(每次向地址寄存器發送的數據只能是8位,所以17位的PageAddress必須分成3次進行發送
Read1
的命令裏面出現了兩個命令選項,分別是00h01h。這裏出現了兩個讀命是否令你意識到什麼呢?是的,00h是用於讀寫1sthalf的命令,而01h是用於讀取2ndhalf的命令。現在我可以結合上圖給你說明爲什麼K9F1208U0BDataField被分爲2half了。
如上文我所提及的,Read11st.Cycle是發送ColumnAddress,假設我現在指定的ColumnAddress0,那麼讀操作將從此頁的第0Byte開始一直讀取到此頁的最後一個Byte(包括SpareField),如果我指定的ColumnAddress127,情況也與前面一樣,但不知道你發現沒有,用於傳遞ColumnAddress的數據線有8條(I/O0~I/O7,對應A0~A7,這也是A8爲什麼不出現在我們傳遞的地址位中),也就是說我們能夠指定的ColumnAddress範圍爲0~255,但不要忘了,1PageDataField是由512Byte組成的,假設現在我要指定讀命令從第256個字節處開始讀取此頁,那將會發生什麼情景?我必須把ColumnAddress設置爲256,但ColumnAddress最大隻能是255,這就造成數據溢出。。。正是因爲這個原因我們才把DataField分爲兩個半區,當要讀取的起始地址(ColumnAddress)在0~255內時我們用00h命令,當讀取的起始地址是在256~511時,則使用01h命令.假設現在我要指定從第256byte開始讀取此頁,那麼我將這樣發送命令串
column_addr=256;
NF_CMD=0x01; ?
2ndhalf開始讀取
NF_ADDR=column_addr&0xff;1st Cycle
NF_ADDR=page_address&0xff; 2nd.Cycle
NF_ADDR=(page_address>>8)&0xff; 3rd.Cycle
NF_ADDR=(page_address>>16)&0xff; 4th.Cycle
其中NF_CMDNF_ADDR分別是NandFlash的命令寄存器和地址寄存器的地址解引用,我一般這樣定義它們,
#define rNFCMD(*(volatile unsigned ch ar *)0x4e000004) //NADD Flash command
#define rNFADDR (*(volatile unsigned ch ar *)0x4e000008) //NANDFlash address
事實上,當NF_CMD=0x01時,地址寄存器中的第8位(A8)將被設置爲1(如上文分析,A8位不在我們傳遞的地址中,這個位其實就是硬件電路根據01h或是00h這兩個命令來置高位或是置低位),這樣我們傳遞column_addr的值256隨然由於數據溢出變爲1,但A8位已經由於NF_CMD=0x01的關係被置爲1了,所以我們傳到地址寄存器裏的值變成了

A0 A1 A2 A3A4 A5 A6 A7 A8
1 0 0 0 0 0 0 0 1

8個位所表示的正好是256,這樣讀操作將從此頁的第256byte2ndhalf的第0byte)開始讀取數據。nand_flash.c中包含3個函數
voidnf_reset(void);
void nf_init(void);
void nf_read(unsigned intsrc_addr,unsigned ch ar *desc_addr,int size);
nf_reset()
將被nf_init()調用。nf_init()nand_flash的初始化函數,在對nandflash進行任何操作之前,nf_init()必須被調用。
nf_read(unsignedint src_addr,unsigned ch ar *desc_addr,int size);
爲讀函數,src_addrnandflash上的地址,desc_addr是內存地址,size是讀取文件的長度。
nf_resetnf_read函數中存在兩個宏
NF_nFCE_L();
NF_nFCE_H();
你可以看到當每次對NandFlash進行操作之前NF_nFCE_L()必定被調用,操作結束之時NF_nFCE_H()必定被調用。這兩個宏用於啓動和關閉Flash芯片的工作(片選/取消片選)。至於nf_reset()中的
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
這一行代碼是對NandFlash的控制寄存器進行初始化配置,rNFCONFNandFlash的配置寄存器,各個位的具體功能請參閱s3c2410數據手冊。
現在舉一個例子,假設我要從NandFlash中的第5000字節處開始讀取1024個字節到內存的0x30000000處,我們這樣調用read函數
nf_read(5000,0x30000000,1024);
我們來分析5000這個src_addr.
根據
column_addr=src_addr%512;
page_address=(src_addr>>9);
我們可得出column_addr=5000%512=392
page_address=(5000>>9)=9
於是我們可以知道5000這個地址是在第9頁的第392個字節處,於是我們的nf_read函數將這樣發送命令和參數
column_addr=5000%512;
>page_address=(5000>>9);
NF_CMD=0x01;
2ndhalf開始讀取
NF_ADDR=column_addr &0xff; 1st Cycle
NF_ADDR=page_address&0xff;2nd.Cycle
NF_ADDR=(page_address>>8)&0xff; 3rd.Cycle
NF_ADDR=(page_address>>16)&0xff; 4th.Cycle
NandFlash的命令寄存器和地址寄存器發送完以上命令和參數之後,我們就可以從rNFDATA寄存器(NandFlash數據寄存器)讀取數據了.
我用下面的代碼進行數據的讀取.
for(i=column_addr;i<512;i++)
{
*buf++=NF_RDDATA();
}
每當讀取完一個Page之後,數據指針會落在下一個Page0Column(0Byte).
下面是源代碼:
/*
www.another-prj.com
author: caiyuqing
本代碼只屬於交流學習,不得用於商業開發
*/
#include"s3c2410.h"
#include "nand_flash.h"
staticunsigned ch ar seBuf
16={0xff};
//
--------------------------------------------------------------------------------------
unsigned shortnf_checkId(void)
{
int i;
unsigned short id;
NF_nFCE_L(); //chip enable

NF_CMD(0x90); //Read ID
NF_ADDR(0x0);
for(i=0;i<10;i++); //wait tWB(100ns)

id="NF"_RDDATA()<<8; // Makercode(K9S1208V:0xec)
id|=NF_RDDATA(); // Devidecode(K9S1208V:0x76)

NF_nFCE_H(); //chip enable
return id;
}
//
--------------------------------------------------------------------------------------
static voidnf_reset(void)
{
int i;
NF_nFCE_L(); //chip enable
NF_CMD(0xFF); //reset command
for(i=0;i<10;i++); //tWB =100ns.
NF_WAITRB(); //wait 200~500us;
NF_nFCE_H(); //chipdisable
}
//
--------------------------------------------------------------------------------------
voidnf_init(void)
{
rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
// 1 1 1 1 1 xxx r xxx, r xxx
// En r r ECCR nFCE="H"tACLS tWRPH0 tWRPH1
nf_reset();
}
//
--------------------------------------------------------------------------------------

voidnf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size)
{
int i;
unsigned int column_addr = src_addr % 512; // columnaddress
unsigned int page_address = (src_addr >> 9); //page addrress
unsigned ch ar *buf = desc_addr;
while((unsignedint)buf < (unsigned int)(desc_addr) + size)
{
NF_nFCE_L();// enable chip

/*NF_ADDRNF_CMDnand_flash的地址和命令寄存器的解引用*/
if(column_addr > 255) // 2end halft
NF_CMD(0x01); // Read2command. cmd 0x01: Read command(start from 2end half page)
else
NF_CMD(0x00); // 1st halft?

NF_ADDR(column_addr &0xff); // Column Address
NF_ADDR(page_address & 0xff); //Page Address
NF_ADDR((page_address >> 8) & 0xff); //...
NF_ADDR((page_address >> 16) & 0xff); // ..
for(i= 0; i < 10; i++); // wait tWB(100ns)/////??????
NF_WAITRB();// Wait tR(max 12us)

// Read from main area
for(i =column_addr; i < 512; i++)
{
*buf++= NF_RDDATA();
}
NF_nFCE_H(); // disable chip
column_addr = 0;
page_address++;
}
return ;
}

NAND Flash結構與驅動分析

一、NANDflash的物理組成
NANDFlash
的數據是以bit的方式保存在memorycell,一般來說,一個cell中只能存儲一個bit。這些cell8個或者16個爲單位,連成bitline,形成所謂的byte(x8)/word(x16),這就是NANDDevice的位寬。這些Line會再組成Page(NANDFlash有多種結構,我使用的NANDFlashK9F1208,下面內容針對三星的K9F1208U0M),每頁528Bytes(512byte(MainArea)+16byte(SpareArea)),每32page形成一個Block(32*528B)。具體一片flash上有多少個Block視需要所定。我所使用的三星k9f1208U0M具有4096block,故總容量爲4096*32*528B=66MB,但是其中的2MB是用來保存ECC校驗碼等額外數據的,故實際中可使用的爲64MB
NANDflash
以頁爲單位讀寫數據,而以塊爲單位擦除數據。按照這樣的組織方式可以形成所謂的三類地址:
ColumnAddress
StartingAddress of the Register.翻成中文爲列地址,地址的低8
PageAddress
:頁地址
BlockAddress
:塊地址
對於NANDFlash來講,地址和命令只能在I/O[7:0]上傳遞,數據寬度是8位。

二、NANDFlash地址的表示
512byte
需要9bit來表示,對於528byte系列的NAND,這512byte被分成1sthalf Page Register2ndhalf Page Register各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的columnaddress(列地址),在進行擦除操作時不需要它,why?因爲以塊爲單位擦除。32page需要5bit來表示,佔用A[13:9]即該page在塊內的相對地址。A8這一位地址被用來設置512byte1sthalf page還是2ndhalf page0表示1st1表示2ndBlock的地址是由A14以上的bit來表示。
例如64MB512Mb)的NANDflash(實際中由於存在sparearea,故都大於這個值),共4096block,因此,需要12bit來表示,即A[25:14],如果是128MB(1Gbit)528byte/pageNANDFlash,則blockaddressA[26:14]表示。而pageaddress就是blcokaddress|page address in block NAND Flash 的地址表示爲:BlockAddress|Page Address in block|halfpage pointer|Column Address地址傳送順序是ColumnAddress,Page Address,Block Address
由於地址只能在I/O[7:0]上傳遞,因此,必須採用移位的方式進行。例如,對於512Mbitx8NANDflash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR爲例:
1步是傳遞columnaddress,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上,而halfpagepointerA8是由操作指令決定的,即指令決定在哪個halfpage上進行讀
寫,而真正的A8的值是不需程序員關心的
2步就是將NAND_ADDR右移9,將NAND_ADDR[16:9]傳到I/O[7:0]上;
3步將NAND_ADDR[24:17]放到I/O上;
4步需要將NAND_ADDR[25]放到I/O上;
因此,整個地址傳遞過程需要4步才能完成,即4-stepaddressing。 如果NANDFlash的容量是32MB256Mbit)以下,那麼,blockadress最高位只到bit24,因此尋址只需要3步。
下面,就x16NANDflash器件稍微進行一下說明。由於一個pagemainarea的容量爲256word,仍相當於512byte。但是,這個時候沒有所謂的1sthalfpage2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個時候A8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點之外,x16NAND使用方法和x8的使用方法完全相同。

三、NANDflash驅動解讀
以前由於做移植多一些,那些工作很簡單(現在看來),從來都不用去關心驅動裏面到底怎麼實現的,這幾次面試才發現真的是學的太淺了,似乎我還在學習仰泳而那些牛人基本都屬於潛水級的了,潛的不知有多深。我對照着開發板所帶的NANDflash驅動和k9f1208的芯片資料把這些代碼通讀了一遍,終於明白了NANDflash的讀寫過程是如何實現的了。我所參考的驅動是mizi公司爲三星芯片所寫的,我看看了,大概和官方2.4.18內核的nand.c差不多。
s3c2410處理器中有專門的NANDflash控制器,他們位於SFR區,具體可以參看s3c2410用戶手冊。以下的這些代碼均可以在vivi或者kernel裏面找到,文中會標明程序出自何處。在vivi中,有關NANDflash的驅動都在driver/mtd/nand/下,該目錄中包含的源文件:smc_core.cNANDflash的主要驅動。
NANDflash
芯片定義了一個很長的結構,這個結構中包含了操作NANDflash的函數和一些必要的變量(include/mtd/nand.h)。
structnand_chip {
#ifdef CONFIG_MTD_NANDY     /* =y*/
    void (*hwcontrol)(int cmd);
   void (*write_cmd)(u_char val);
    void(*write_addr)(u_char val);
    u_char(*read_data)(void);
    void (*write_data)(u_charval);
    void (*wait_for_ready)(void);
   int page_shift;
    u_char *data_buf;
   u_char *data_cache;
    int   cache_page;
    struct nand_smc_dev *dev;
   u_char spare[SMC_OOB_SIZE];
#else    /*CONFIG_MTD_NANDY */
    ……
#ifdefCONFIG_MTD_NAND_ECC
    u_char ecc_code_buf[6];
   u_char reserved[2];
#endif
#endif    /*CONFIG_MTD_NANDY */
};
縱觀對NANDflash的各種操作(readwriteerase),無外乎如下幾種操作:
1
.選擇flash   nand_select()
2
.發送命令    nand_command()
3
.進行相應操作readwrite……
4
.反選NANDflash   nand_deselect()

下面是以上四步的實現代碼:
1
、選擇NANDflash
#define nand_select()  this->hwcontrol(NAND_CTL_SETNCE); \
               nand_command(mtd, NAND_CMD_RESET, -1, -1); \
               udelay (10);
hwcontrol(NAND_CTL_SETNCE)
的作用是設置2410NANDFLASH CONFIGURATION (NFCONF) REGISTERNANDFlash Memory chip enable位爲0,這位寄存器在自動重啓後就被系統自動清零。如果要訪問NANDflash的內存,這位必須置1
nand_command(mtd,NAND_CMD_RESET, -1, -1)
;向flash發送命令,此命令爲reset,即爲重置NANDflash
然後是10us的延遲,給flash個反應時間。
2
、發送命令
Nand_command()
同樣在smc_core.c中實現。NANDflash的命令有如下幾種:

    命令                        命令值               描述
NAND_CMD_READ0                   0               
讀操作
NAND_CMD_READ1                   1               
讀操作
NAND_CMD_PAGEPROG               0x10           
頁編程操作
NAND_CMD_READOOB               0x50           
讀寫OOB
NAND_CMD_ERASE1                0x60           
讀寫操作
NAND_CMD_STATUS                   0x70           
讀取狀態
NAND_CMD_STATUS_MULTI           0x71           
讀取狀態
NAND_CMD_SEQIN                   0x80           
寫操作
NAND_CMD_READID                   0x90           
FlashID
NAND_CMD_ERASE2                0xd0           
擦寫操作
NAND_CMD_RESET                   oxff               
復位操作

按照程序的註釋,可以將該函數的實現分爲如下幾步:
1
Begincommand latch cycle
實現代碼:
this->hwcontrol(NAND_CTL_SETCLE);
this->hwcontrol(NAND_CTL_DAT_OUT);
找到第二條語句的定義,發現什麼都麼做,不解!!希望達人解答。我猜想可能是一個數據讀出的使能操作,允許數據讀出。
CommandLatch Enable(CLE) and Address Latch Enable(ALE) are used to multiplexcommand and address respectively, via the I/O pins. The CLE inputcontrols the path activation for commands sent to the commandregister. When active high, commands are latched into the commandregister through the I/O ports on the rising edge of the nWE signal.
看了這段英文相信對第一條語句的作用已經十分清楚了,他就是用來控制向命令寄存(COMMANDSET (NFCMD) REGISTER)發送命令的。
2
Write out thecommand to thedevice
這部分對於不同的命令來說,操作的步驟也不太相同,如果爲寫操作,那麼還有根據flash不同的容量決定操作步驟,具體可以參看代碼。如果爲其他命令,那麼就是簡單的一行:
this->write_cmd(command);
將命令直接想到命令寄存器(NFCMD[7:0])中。
3
Set ALE andclear CLE to start address cycle & Serially inputaddress
1
中已經提到了ALECLE的作用,現在開始發送地址。
實現代碼:
this->hwcontrol(NAND_CTL_CLRCLE);// clear the command latch enable
this->hwcontrol(NAND_CTL_SETALE);// set the address latch enable
然後按位操作,是用函數write_addr()將地址寫到NANDFLASH ADDRESS SET (NFADDR) REGISTER中。
4
Latch inaddress
實現代碼:
this->hwcontrol(NAND_CTL_CLRALE);
this->hwcontrol(NAND_CTL_DAT_IN);
地址發送完畢,清楚ALE
5
Pause for15us
我使用的VIVI中,使用udelay(15)延時15us,但這個時間會因NANDFlash的不同而不同。
三、Operation
根據函數的不同,操作部分會不一樣,但是主要的是對NANDFLASH DATA (NFDATA)REGISTER的操作,或寫(編程)或者讀。通過讀或寫函數的參數來返回或傳遞讀出的值或寫入的值。寫得操作通常比較麻煩,他要將寫到flash的內容重新讀出後進行ECC校驗,如果數據正確則在重新真正的寫(編程),如果錯誤,則將數據寫入flash的另一個塊。讀和寫都是以頁爲單位進行操作。而擦除則以塊爲單位,三個週期發送完地址。擦除完畢後同樣需要進行檢察以確定是否擦除成功。
四、De-selectthe NAND device
實現代碼:
#definenand_deselect() this->hwcontrol(NAND_CTL_CLRNCE);
反選flash吧,不知這樣叫正確與否,跟selectthe NAND device相反,亦即使用完後將使能flash位清0,代碼是NFCONF位於0x4e00_0000的位置(NFCONF|= NFCONF_nFCE_HIGH;),有興趣的可以讀讀代碼,看看這是怎麼實現的,我的感覺就是關於寄存器的清置讀起來都比較暈。

NAND閃存技術深入解析類別:存儲器  閱讀:1057 對於許多消費類音視頻產品而言,NAND閃存是一種比硬盤驅動器更好的存儲方案,這在不超過4GB的低容量應用中表現得猶爲明顯。隨着人們持續追求功耗更低、重量更輕和性能更佳的產品,NAND正被證明極具吸引力。

  NAND閃存陣列分爲一系列128kB的區塊(block),這些區塊是NAND器件中最小的可擦除實體。擦除一個區塊就是把所有的位(bit)設置爲“1”(而所有字節(byte)設置爲FFh)。有必要通過編程,將已擦除的位從“1”變爲“0”。最小的編程實體是字節(byte)。一些NOR閃存能同時執行讀寫操作(見下圖1)。雖然NAND不能同時執行讀寫操作,它可以採用稱爲“映射(shadowing)”的方法,在系統級實現這一點。這種方法在個人電腦上已經沿用多年,即將BIOS從速率較低的ROM加載到速率較高的RAM上。

  NAND的效率較高,是因爲NAND串中沒有金屬觸點。NAND閃存單元的大小比NOR要小(4F2:10F2)的原因,是NOR的每一個單元都需要獨立的金屬觸點。NAND與硬盤驅動器類似,基於扇區(頁),適合於存儲連續的數據,如圖片、音頻或個人電腦數據。雖然通過把數據映射到RAM上,能在系統級實現隨機存取,但是,這樣做需要額外的RAM存儲空間。此外,跟硬盤一樣,NAND器件存在壞的扇區,需要糾錯碼(ECC)來維持數據的完整性。

  存儲單元面積越小,裸片的面積也就越小。在這種情況下,NAND就能夠爲當今的低成本消費市場提供存儲容量更大的閃存產品。NAND閃存用於幾乎所有可擦除的存儲卡。NAND的複用接口爲所有最新的器件和密度都提供了一種相似的引腳輸出。這種引腳輸出使得設計工程師無須改變電路板的硬件設計,就能從更小的密度移植到更大密度的設計上。

  NAND與NOR閃存比較

  NAND閃存的優點在於寫(編程)和擦除操作的速率快,而NOR的優點是具有隨機存取和對字節執行寫(編程)操作的能力(見下圖圖2)。NOR的隨機存取能力支持直接代碼執行(XiP),而這是嵌入式應用經常需要的一個功能。NAND的缺點是隨機存取的速率慢,NOR的缺點是受到讀和擦除速度慢的性能制約。NAND較適合於存儲文件。如今,越來越多的處理器具備直接NAND接口,並能直接從NAND(沒有NOR)導入數據。

  NAND的真正好處是編程速度快、擦除時間短。NAND支持速率超過5Mbps的持續寫操作,其區塊擦除時間短至2ms,而NOR是750ms。顯然,NAND在某些方面具有絕對優勢。然而,它不太適合於直接隨機存取。

  對於16位的器件,NOR閃存大約需要41個I/O引腳;相對而言,NAND器件僅需24個引腳。NAND器件能夠複用指令、地址和數據總線,從而節省了引腳數量。複用接口的一項好處,就在於能夠利用同樣的硬件設計和電路板,支持較大的NAND器件。由於普通的TSOP-1封裝已經沿用多年,該功能讓客戶能夠把較高密度的NAND器件移植到相同的電路板上。NAND器件的另外一個好處顯然是其封裝選項:NAND提供一種厚膜的2Gb裸片或能夠支持最多四顆堆疊裸片,容許在相同的TSOP-1封裝中堆疊一個8Gb的器件。這就使得一種封裝和接口能夠在將來支持較高的密度。   圖1 不同閃存單元的對比  圖2 NOR閃存的隨機存取時間爲0.12ms,而NAND閃存的第一字節隨機存取速度要慢得多

  NAND基本操作

  以2Gb NAND器件爲例,它由2048個區塊組成,每個區塊有64個頁(見圖3)。  圖3 2GB NAND閃存包含2,048個區塊

  每一個頁均包含一個2048字節的數據區和64字節的空閒區,總共包含2,112字節。空閒區通常被用於ECC、耗損均衡(wear leveling)和其它軟件開銷功能,儘管它在物理上與其它頁並沒有區別。NAND器件具有8或16位接口。通過8或16位寬的雙向數據總線,主數據被連接到NAND存儲器。在16位模式,指令和地址僅僅利用低8位,而高8位僅僅在數據傳輸週期使用。

  擦除區塊所需時間約爲2ms。一旦數據被載入寄存器,對一個頁的編程大約要300μs。讀一個頁面需要大約25μs,其中涉及到存儲陣列訪問頁,並將頁載入16,896位寄存器中。

  除了I/O總線,NAND接口由6個主要控制信號構成:

  1.芯片啓動(Chip Enable, CE#):如果沒有檢測到CE信號,那麼,NAND器件就保持待機模式,不對任何控制信號作出響應。

  2.寫使能(Write Enable, WE#): WE#負責將數據、地址或指令寫入NAND之中。

  3.讀使能(Read Enable, RE#): RE#允許輸出數據緩衝器。

  4.指令鎖存使能(Command Latch Enable, CLE): 當CLE爲高時,在WE#信號的上升沿,指令被鎖存到NAND指令寄存器中。

  5.地址鎖存使能(Address Latch Enable, ALE):當ALE爲高時,在WE#信號的上升沿,地址被鎖存到NAND地址寄存器中。

  6.就緒/忙(Ready/Busy, R/B#):如果NAND器件忙,R/B#信號將變低。該信號是漏極開路,需要採用上拉電阻。

  數據每次進/出NAND寄存器都是通過16位或8位接口。當進行編程操作的時候,待編程的數據進入數據寄存器,處於在WE#信號的上升沿。在寄存器內隨機存取或移動數據,要採用專用指令以便於隨機存取。

  數據寄存器輸出數據的方式與利用RE#信號的方式類似,負責輸出現有的數據,並增加到下一個地址。WE#和RE#時鐘運行速度極快,達到30ns的水準。當RE#或CE#不爲低的時候,輸出緩衝器將爲三態。這種CE#和RE#的組合使能輸出緩衝器,容許NAND閃存與NOR、SRAM或DRAM等其它類型存儲器共享數據總線。該功能有時被稱爲“無需介意芯片啓動(chip enable don't care)”。這種方案的初衷是適應較老的NAND器件,它們要求CE#在整個週期爲低(譯註:根據上下文改寫)。  圖4 輸入寄存器接收到頁編程(80h)指令時,內部就會全部重置爲1s,使得用戶可以只輸入他想以0位編程的數據字節  圖5 帶有隨機數據輸入的編程指令。圖中加亮的扇區顯示,該指令只需要後面跟隨着數據的2個字節的地址

  所有NAND操作開始時,都提供一個指令週期(表1)。

  當輸出一串WE#時鐘時,通過在I/O位7:0上設置指令、驅動CE#變低且CLE變高,就可以實現一個指令週期。注意:在WE#信號的上升沿上,指令、地址或數據被鎖存到NAND器件之中。如表1所示,大多數指令在第二個指令週期之後要佔用若干地址週期。注意:復位或讀狀態指令例外,如果器件忙,就不應該發送新的指令。

  以2Gb NAND器件的尋址方案爲例,第一和第二地址週期指定列地址,該列地址指定頁內的起始字節(表2)。

  注意:因爲最後一列的位置是2112,該最後位置的地址就是08h(在第二字節中)和3Fh(在第一字節中)。PA5:0指定區塊內的頁地址,BA16:6指定區塊的地址。雖然大多編程和讀操作需要完整的5字節地址,在頁內隨機存取數據的操作僅僅用到第一和第二字節。塊擦除操作僅僅需要三個最高字節(第三、第四和第五字節)來選擇區塊。  圖6 典型的存儲方法   圖7 頁讀緩存模式

  總體而言,NAND的基本操作包括:復位(Reset, FFh)操作、讀ID(Read ID, 00h)操作、讀狀態(Read Status, 70h)操作、編程(Program)操作、隨機數據輸入(Random data input, 85h)操作和讀(Read)操作等。

  將NAND連接到處理器

  選擇內置NAND接口的處理器或控制器的好處很多。如果沒有這個選擇,有可能在NAND和幾乎任何處理器之間設計一個“無粘接邏輯(glueless)”接口。NAND和NOR閃存的主要區別是複用地址和數據總線。該總線被用於指定指令、地址或數據。CLE信號指定指令週期,而ALE信號指定地址週期。利用這兩個控制信號,有可能選擇指令、地址或數據週期。把ALE連接到處理器的第五地址位,而把CLE連接到處理器的第四地址位,就能簡單地通過改變處理器輸出的地址,任意選擇指令、地址或數據。這容許CLE和ALE在合適的時間自動設置爲低。

  爲了提供指令,處理器在數據總線上輸出想要的指令,並輸出地址0010h;爲了輸出任意數量的地址週期,處理器僅僅要依次在處理器地址0020h之後輸出想要的NAND地址。注意,許多處理器能在處理器的寫信號周圍指定若干時序參數,這對於建立合適的時序是至關重要的。利用該技術,你不必採用任何粘接邏輯,就可以直接從處理器存取指令、地址和數據。

  多層單元

  多層單元(MLC)的每一個單元存儲兩位,而傳統的SLC僅僅能存儲一位。MLC技術有顯著的密度優越性,然而,與SLC相比(表3),其速度或可靠性稍遜。因此,SLC被用於大多數媒體卡和無線應用,而MLC器件通常被用於消費電子和其它低成本產品。

  如上所述,NAND需要ECC以確保數據完整性。NAND閃存的每一個頁面上都包括額外的存儲空間,它就是64個字節的空閒區(每512字節的扇區有16字節)。該區能存儲ECC代碼及其它像磨損評級或邏輯到物理塊映射之類的信息。ECC能在硬件或軟件中執行,但是,硬件執行有明顯的性能優勢。在編程操作期間,ECC單元根據扇區中存儲的數據來計算誤碼校正代碼。數據區的ECC代碼然後被分別寫入到各自的空閒區。當數據被讀出時,ECC代碼也被讀出;運用反操作可以覈查讀出的數據是否正確。

  有可能採用ECC算法來校正數據錯誤。能校正的錯誤的數量取決於所用算法的校正強度。在硬件或軟件中包含ECC,就提供了強大的系統級解決方案。最簡單的硬件實現方案是採用簡單的漢明(Simple Hamming)碼,但是,只能校正單一位錯誤。瑞德索羅門(Reed-Solomon)碼提供更爲強大的糾錯,並被目前的控制器廣爲採用。此外,BCH碼由於比瑞德索羅門方法的效率高,應用也日益普及。

  要用軟件執行NAND閃存的區塊管理。該軟件負責磨損評級或邏輯到物理映射。該軟件還提供ECC碼,如果處理器不包含ECC硬件的話。

  編程或擦除操作之後,重要的是讀狀態寄存器,因爲它確認是否成功地完成了編程或擦除操作。如果操作失敗,要把該區塊標記爲損壞且不能再使用。以前已編寫進去的數據要從損壞的區塊中搬出,轉移到新的(好的)存儲塊之中。2Gb NAND的規範規定,它可以最多有40個壞的區塊,這個數字在器件的生命週期(額定壽命爲10萬次編程/擦除週期)內都適用。一些有壞塊的NAND器件能夠出廠,主要就歸根於其裸片面積大。管理器件的軟件負責映射壞塊並由好的存儲塊取而代之。

  利用工廠對這些區塊的標記,軟件通過掃描塊可以確定區塊的好壞。壞塊標記被固定在空閒區的第一個位置(列地址2048)。如果在0或1頁的列地址2048上的數據是“non-FF”,那麼,該塊要標記爲壞,並映射出系統。初始化軟件僅僅需要掃描所有區塊確定以確定哪個爲壞,然後建一個壞塊表供將來參考。

  小心不要擦除壞塊標記,這一點很重要。工廠在寬溫和寬電壓範圍內測試了NAND;一些由工廠標記爲壞的區塊可能在一定的溫度或電壓條件下仍然能工作,但是,將來可能會失效。如果壞塊信息被擦除,就無法再恢復。

nandflash壞塊管理OOB,BBT,ECC



0.NAND的操作管理方式

     NANDFLASH的管理方式:以三星FLAHS爲例,一片Nandflash爲一個設備(device)1(Device) = xxxx (Blocks)1(Block) = xxxx (Pages)1(Page) =528(Bytes) = 數據塊大小(512Bytes)+ OOB塊大小(16Bytes,除OOB第六字節外,通常至少把OOB的前3個字節存放NandFlash硬件ECC)

 1.爲什麼會出現壞塊
   由於NANDFlash的工藝不能保證NANDMemoryArray在其生命週期中保持性能的可靠,因此,在NAND的生產中及使用過程中會產生壞塊。壞塊的特性是:當編程/擦除這個塊時,會造成PageProgramBlockErase操作時的錯誤,相應地反映到StatusRegister的相應位。

2.壞塊的分類
  總體上,壞塊可以分爲兩大類:(1)固有壞塊:這是生產過程中產生的壞塊,一般芯片原廠都會在出廠時都會將每個壞塊第一個pagesparearea的第6byte標記爲不等於0xff值。(2)使用壞塊:這是在NANDFlash使用過程中,如果BlockErase或者PageProgram錯誤,就可以簡單地將這個塊作爲壞塊來處理,這個時候需要把壞塊標記起來。爲了和固有壞塊信息保持一致,將新發現的壞塊的第一個pagesparearea的第6Byte標記爲非0xff的值。

3.壞塊管理
   根據上面的這些敘述,可以瞭解NANDFlash出廠時在sparearea中已經反映出了壞塊信息,因此,如果在擦除一個塊之前,一定要先check一下第一頁的sparearea的第6byte是否是0xff,如果是就證明這是一個好塊,可以擦除;如果是非0xff,那麼就不能擦除,以免將壞塊標記擦掉。當然,這樣處理可能會犯一個錯誤―――“錯殺僞壞塊”,因爲在芯片操作過程中可能由於電壓不穩定等偶然因素會造成NAND操作的錯誤。但是,爲了數據的可靠性及軟件設計的簡單化,還是需要遵照這個標準。

      可以用BBTbadblocktable,即壞塊表來進行管理。各家對nand的壞塊管理方法都有差異。比如專門用nand做存儲的,會把bbt放到block0,因爲第0塊一定是好的塊。但是如果nand本身被用來boot,那麼第0塊就要存放程序,不能放bbt了。有的把bbt放到最後一塊,當然,這一塊堅決不能爲壞塊。bbt的大小跟nand大小有關,nand越大,需要的bbt也就越大。
4.
壞塊糾正

     ECCNANDFlash出錯的時候一般不會造成整個Block或是Page不能讀取或是全部出錯,而是整個Page(例如512Bytes)中只有一個或幾個bit出錯。一般使用一種比較專用的校驗——ECCECC能糾正單比特錯誤和檢測雙比特錯誤,而且計算速度很快,但對1比特以上的錯誤無法糾正,對2比特以上的錯誤不保證能檢測。
     ECC
一般每256字節原始數據生成3字節ECC校驗數據,這三字節共24比特分成兩部分:6比特的列校驗和16比特的行校驗,多餘的兩個比特置1。(512生成兩組ECC?) 
     
當往NANDFlashpage中寫入數據的時候,每256字節我們生成一個ECC校驗和,稱之爲原ECC校驗和,保存到PAGEOOBout-of-band)數據區中。其位置就是eccpos[]。校驗的時候,根據上述ECC生成原理不難推斷:將從OOB區中讀出的原ECC校驗和新ECC校驗和按位異或,若結果爲0,則表示不存在錯(或是出現了ECC無法檢測的錯誤);若3個字節異或結果中存在11個比特位爲1,表示存在一個比特錯誤,且可糾正;若3個字節異或結果中只存在1個比特位爲1,表示OOB區出錯;其他情況均表示出現了無法糾正的錯誤。
5.
補充
 (1)需要對前面由於PageProgram錯誤發現的壞塊進行一下特別說明。如果在對一個塊的某個page進行編程的時候發生了錯誤就要把這個塊標記爲壞塊,首先就要把塊裏其他好的面的內容備份到另外一個空的好塊裏面,然後,把這個塊標記爲壞塊。當然,這可能會犯“錯殺”之誤,一個補救的辦法,就是在進行完塊備份之後,再將這個壞塊擦除一遍,如果BlockErase發生錯誤,那就證明這個塊是個真正的壞塊,那就毫不猶豫地將它打個“戳”吧!
 (2)可能有人會問,爲什麼要使用每個塊第一頁的sparearea的第六個byte作爲壞塊標記。這是NANDFlash生產商的默認約定,你可以看到Samsung,Toshiba,STMicroelectronics都是使用這個Byte作爲壞塊標記的。

    3)爲什麼好塊用0xff來標記?因爲NandFlash的擦除即是將相應塊的位全部變爲1,寫操作時只能把芯片每一位(bit)只能從1變爲0,而不能從0變爲10XFF這個值就是標識擦除成功,是好塊。






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章