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

1、內存詳解

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

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的器件。這就使得一種封裝和接口可以在未來支持較高的密度。安全

clip_image001

clip_image002

clip_image003

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

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

NAND基本操做less

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

clip_image004

每個頁均包含一個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#在整個週期爲低(譯註:根據上下文改寫)。

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

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

全部NAND操做 開始時,都提供一個指令週期(表1)。

clip_image008

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

clip_image009

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

clip_image010

clip_image011

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

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

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

多級單元

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

clip_image013

如上所述,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;一些由工廠標記爲壞的區塊可能在必定的溫度或電壓條件下仍然能工做,可是,未來可能會失效。若是壞塊信息被擦除,就沒法再恢復。

2、NAND FLASH讀寫尋址方式

NAND Flash的尋址方式和NAND Flash的memory組織方式緊密相關。NAND Flash的數據是以bit的方式保存在memory cell,通常來講,一個cell中只能存儲一個bit。這些cell以8個或者16個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device的位寬。
這些Line會再組成Page,一般是528Byte/page或者264Word/page。而後,每32個page造成一個Block,Sizeof(block)=16kByte.
     Block是NAND Flash中最大的操做單元,擦除就是按照block爲單位完成的,而
編程/讀取是按照page爲單位完成的。
因此,按照這樣的組織方式能夠造成所謂的三類地址:
     -Block   Address
     -Page    Address
     -Column Address
首先,必須清楚一點,對於NAND Flash來說,地址和命令只能在I/O[7:0]上傳遞,數據寬度能夠是8位或者16位,可是,對於x16的NAND Device,I/O[15:8]只用於傳遞數據。
清楚了這一點,咱們就能夠開始分析NAND Flash的尋址方式了。
以528Byte/page 總容量512Mbit+512kbyte的NAND器件爲例:
由於,
     1 block=16kbyte,
     512Mbit=64Mbyte,
     Numberof(block)=1024
     1block=32page,
     1page=528byte=512byte(Main Area)+16byte(Spare Area)
用戶數據保存在main area中。
     512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由所謂的pointer operation命令來選擇,也就是選擇了bit8的高低。所以A8就是halfpage pointer,A[7:0]就是所謂的column address。
     32個page須要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512Mb 的NAND,共4096block,所以,須要12個bit來表示,即A[25:14],若是是1Gbit的528byte/page的NAND Flash,共8192個block,則block address用A[26:14]表示。而page address就是blcok address|page address in block
NAND Flash的地址表示爲:
      Block Address|Page Address in block|halfpage pointer|Column Address
地址傳送順序是Column Address,Page Address,Block Address。
因爲地址只能在I/O[7:0]上傳遞,所以,必須採用移位的方式進行。
例如,對於512Mbit x8的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。
以NAND_ADDR爲例:
第1步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上而halfpage pointer即bit8是由操做指令決定的,即指令決定在哪一個halfpage上進行讀寫,而真正的bit8的值是don't care的。
第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-step addressing。
若是NAND Flash的容量是256Mbit如下,那麼,block adress最高位只到bit24,所以尋址只須要3步。


Nand Flash結構與讀寫分析及Nand Flash尋址方式【ZZ】

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

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

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

Nand Flash結構與讀寫分析

NAND Flash 的數據是以bit 的方式保存在memory cell,通常來講,一個cell 中只能存儲一個bit。這些cell 以8 個或者16 個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device 的位寬。這些Line 會再組成Page,(Nand Flash 有多種結構,我使用的Nand Flash 是K9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32 個page 造成一個Block, Sizeof(block)=16kByte 。1 block=16kbyte,512Mbit=64Mbyte,Numberof(block)=1024 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

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

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

512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的column address。32 個page 須要5bit 來表示,佔用A[13:9],即該page 在塊內的相對地址。Block的地址是由A14 以上的bit 來表示,例如512Mb 的NAND,共4096block,所以,須要12 個bit 來表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,則block address用A[26:14]表示。而page address就是blcok address|page address in block, NAND Flash 的地址表示爲: Block Address|Page Address in block|halfpage pointer|Column Address 地址傳送順序是Column Address,Page Address,Block Address。 因爲地址只能在I/O[7:0]上傳遞,所以,必須採用移位的方式進行。例如,對於512Mbit x8 的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR 爲例: 第1 步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令決定的,即指令決定在哪一個halfpage 上進行讀寫。而真正的bit8 的值是don\'t care 的。 第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-step addressing。 若是NAND Flash 的容量是256Mbit 如下,那麼,block adress 最高位只到bit24,所以尋址 只須要3 步。

下面,就x16 的NAND flash 器件稍微進行一下說明。因爲一個page 的main area 的容量爲256word,仍至關於512byte。可是,這個時候沒有所謂 的1st halfpage 和2nd halfpage 之分了,因此,bit8就變得沒有意義了,也就是這個時候 bit8 徹底不用管,地址傳遞仍然和x8 器件相同。除了,這一點以外,x16 的NAND使用方法和 x8 的使用方法徹底相同。

norflash和nandflash的區別
norflash中能夠運行程序,nandflash不能夠
Nor flash按sector可擦除,按bit可讀寫。Nand Flash按Block可擦除,按Page可讀寫。
最主要是尋址方式不一樣

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

Nand Flash 尋址方式

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

因此,按照這樣的組織方式能夠造成所謂的三類地址:
     -Block   Address
     -Page    Address
     -Column Address

首先,必須清楚一點,對於NAND Flash來說,地址和命令只能在I/O[7:0]上傳遞,數據寬度能夠是8位或者16位,可是,對於x16的NAND Device,I/O[15:8]只用於傳遞數據。

清楚了這一點,咱們就能夠開始分析NAND Flash的尋址方式了。

以528Byte/page 總容量512Mbit+512kbyte的NAND器件爲例:
由於,
     1 block=16kbyte,
     512Mbit=64Mbyte,
     Numberof(block)=1024
     1block=32page,
     1page=528byte=512byte(Main Area)+16byte(Spare Area)
用戶數據保存在main area中。

     512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由所謂的pointer operation命令來選擇,也就是選擇了bit8的高低。所以A8就是halfpage pointer,A[7:0]就是所謂的column address。
     32個page須要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512Mb 的NAND,共4096block,所以,須要12個bit來表示,即A[25:14],若是是1Gbit的528byte/page的NAND Flash,共8192個block,則block address用A[26:14]表示。而page address就是blcok address|page address in block
NAND Flash的地址表示爲:
      Block Address|Page Address in block|halfpage pointer|Column Address
地址傳送順序是Column Address,Page Address,Block Address。
因爲地址只能在I/O[7:0]上傳遞,所以,必須採用移位的方式進行。
例如,對於512Mbit x8的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。

以NAND_ADDR爲例:
第1步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上而halfpage pointer即bit8是由操做指令決定的,即指令決定在哪一個halfpage上進行讀寫,而真正的bit8的值是don't care的。
第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-step addressing。
若是NAND Flash的容量是256Mbit如下,那麼,block adress最高位只到bit24,所以尋址只須要3步。


NAND Flash Architecture

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的時候,在寫第一、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

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


爲何Micron的NAND Flash能達到200MB/s的讀取速度

今天看到新聞Intel, Micron claim world’s fastest NAND flash,就直接到Micron的網站上瀏覽了一下。Micron的新產品分類爲High Speed NAND Flash Products,用「High Speed」與原有NAND產品系列區分(估計ONFI 3.0兼容的產品出來後,還要加上「Ultra」,才能再分出一個類別來)。 riple
      Micron的High Speed系列目前按照容量分爲8Gb、16Gb、32Gb三種,按照接口個數分爲單端口(8Gb)和雙端口(1六、32Gb)兩種。在Micron的網站上還看不到詳細的datasheet,只能看到一個Product BriefFlyerriple
經過Product Brief能夠獲得8Gb芯片的以下信息:採用了50nm而不是72nm工藝生產;是SLC而不是MLC結構;BGA封裝取代了TSOP封 裝;4096Byte/Page,128Page/Block,512Block x 1/Plane,4Planes;I/O分爲異步和同步(DDR)兩種模式;速度最高的同步傳輸模式,讀寫I/O時間都是6ns/Toggle;讀 Array 30us/Page,寫Array 160us/Page,擦Array 3ms/Block。 riple
從上面的信息能夠看出,High Speed特性要歸功於6ns/Toggle的I/O時間,對於8bit的接口來講,至關於166MB/s的傳輸速度。 riple
可是,NAND Flash的訪問速度不只僅取決於I/O速度,還和Array傳輸時間、芯片內部緩衝結構和Plane數量有關。 riple

clip_image014

〇、NAND Flash訪問時間分析 riple

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

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

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

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

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

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

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

      Micron的NAND Flash的一大特色是:每個Plane對應一個Page大小的緩衝(data register)和一個Page大小的緩存(cache register)。數據寫入的順序是:I/O -> cache register -> data register -> Plane,數據讀出的順序恰好相反。緩衝(data register)與緩存(cache register)之間的數據傳輸速度很快,data register能夠把I/O操做和Array操做分隔開,造成I/O操做和Array操做的「兩級流水線」。這種結構與上一代NAND Flash同樣。(其實,4個Plane對應4個data register和1個cache register便可) riple

4、多Plane操做對速度的影響 riple

      4個Plane對應4組緩衝與緩存,每一組能夠分別操做。2個Plane交替操做,能夠實現「乒乓操做」,達到2倍的Array訪問帶寬。4個Plane 交替操做,能夠實現「乒乒乓乓操做」,達到4倍的Array訪問帶寬。在上一代的NAND Flash芯片中,採用2Plane結構是比較常見的。 riple

clip_image001[1]

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

讀I/O時間:1Toggle/Byte x 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/Byte x 6ns/Toggle x 4096Byte/Page = 24.6us/Page,與寫Array時間160us/Page相差不少,單獨採用cache模式不夠,還要採用4Plane的「乒乒乓乓操做」,縮短 寫Array時間,儘可能均衡流水線的兩級操做時間。4Plane模式平均Array寫操做時間爲一次Array寫操做時間的1/4,40us/Page。因此在cache模式配合4Plane模式的寫操做下,流水線的速度等於流水線兩級中最慢的「平均Array寫速度」,能夠近似爲:4096Byte/40us = 102MB/s。 riple

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


nand flash 總結

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

NAND Flash產品能夠分爲三大架構,分別是Single Level Cell;SLC,包括三星電子、Hynix、Micron以及東芝都是此技術使用者,第二種則是Multi Level Cell;MLC,目前有東芝、Renesas使用,不過三星電子將在2005第四季推出相關產品,最後則是Infineon與Saifun Semiconductors合資利用NROM技術所共同開發的Multi Bit Cell;MBC。

MLC是Intel在1997年9月最早開發成功的,其做用是將兩個位的信息存入一個 Floating Gate(NADA Flash存儲單元中存放電荷的部分),而後利用不一樣Level的電荷,透過內存儲存格的電壓控制精準讀寫,假設以4種電壓控制、1個晶體管可存取2 bits 的數據,如果控制8種電壓就能夠存取3 bits 的數據,使Flash 的容量大幅提高,相似Rambus的QRSL技術,經過精確控制浮動柵上的電荷數量,使其呈現出4種不一樣的存儲狀態,每種狀態表明兩個二進制數值(從00 到11)。

固然不光是NOR型NAND Flash在使用,東芝在2003年2月推出第一款MLC型的NAND Flash,並接續2004年4月推出採用MLC技術的4Gbit與8Gbit NAND Flash,顯然這對於原本就以容量見長的NAND Flash更是如虎添翼。根據Semiconductor Insights研究,東芝利用90nm MLC技術所開發出來的4Gb,其die面積爲144 mm2。

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

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

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

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

Nand Flash結構與讀寫分析

NAND Flash 的數據是以bit 的方式保存在memory cell,通常來講,一個cell 中只能存儲一個bit。這些cell 以8 個或者16 個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device 的位寬。這些Line 會再組成Page,(Nand Flash 有多種結構,我使用的Nand Flash 是K9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32 個page 造成一個Block, Sizeof(block)=16kByte 。1 block=16kbyte,512Mbit=64Mbyte,Numberof(block)=1024 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)

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

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

512byte須要9bit來表示,對於528byte系列的NAND,這512byte被 分紅1st half和2nd half,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的column address。32 個page 須要5bit 來表示,佔用A[13:9],即該page 在塊內的相對地址。Block的地址是由A14 以上的bit 來表示,例如512Mb 的NAND,共4096block,所以,須要12 個bit 來表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,則block address用A[26:14]表示。而page address就是blcok address|page address in block, NAND Flash 的地址表示爲: Block Address|Page Address in block|halfpage pointer|Column Address 地址傳送順序是Column Address,Page Address,Block Address。 因爲地址只能在I/O[7:0]上傳遞,所以,必須採用移位的方式進行。例如,對於512Mbit x8 的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR 爲例: 第1 步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令決定的,即指令決定在哪一個halfpage 上進行讀寫。而真正的bit8 的值是don\'t care 的。 第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-step addressing。 若是NAND Flash 的容量是256Mbit 如下,那麼,block adress 最高位只到bit24,所以尋址 只須要3 步。

下面,就x16 的NAND flash 器件稍微進行一下說明。 因爲一個page 的main area 的容量爲256word,仍至關於512byte。可是,這個時候沒有所謂 的1st halfpage 和2nd halfpage 之分了,因此,bit8就變得沒有意義了,也就是這個時候 bit8 徹底不用管,地址傳遞仍然和x8 器件相同。除了,這一點以外,x16 的NAND使用方法和 x8 的使用方法徹底相同。

norflash和nandflash的區別

norflash中能夠運行程序,nandflash不能夠

Nor flash按sector可擦除,按bit可讀寫。Nand Flash按Block可擦除,按Page可讀寫。

最主要是尋址方式不一樣

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

Nand Flash 尋址方式

NAND Flash的尋址方式和NAND Flash的memory組織方式緊密相關。NAND Flash的數據是以bit的方式保存在memory cell,通常來講,一個cell中只能存儲一個bit。這些cell以8個或者16個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device的位寬。

這些Line會再組成Page,一般是528Byte/page或者264Word/page。而後,每32個page造成一個Block,Sizeof(block)=16kByte.

     Block是NAND Flash中最大的操做單元,擦除就是按照block爲單位完成的,而

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

因此,按照這樣的組織方式能夠造成所謂的三類地址:

     -Block   Address

     -Page    Address

     -Column Address

首先,必須清楚一點,對於NAND Flash來說,地址和命令只能在I/O[7:0]上傳遞,數據寬度能夠是8位或者16位,可是,對於x16的NAND Device,I/O[15:8]只用於傳遞數據。

清楚了這一點,咱們就能夠開始分析NAND Flash的尋址方式了。

以528Byte/page 總容量512Mbit+512kbyte的NAND器件爲例:

由於,

     1 block=16kbyte,

     512Mbit=64Mbyte,

     Numberof(block)=1024

     1block=32page,

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

用戶數據保存在main area中。

     512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由所謂的pointer operation命令來選擇,也就是選擇了bit8的高低。所以A8就是halfpage pointer,A[7:0]就是所謂的column address。

     32個page須要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。Block的地址是由A14以上的bit來表示,例如512Mb 的NAND,共4096block,所以,須要12個bit來表示,即A[25:14],若是是1Gbit的528byte/page的NAND Flash,共8192個block,則block address用A[26:14]表示。而page address就是blcok address|page address in block

NAND Flash的地址表示爲:

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

地址傳送順序是Column Address,Page Address,Block Address。

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

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

以NAND_ADDR爲例:

第1步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上而halfpage pointer即bit8是由操做指令決定的,即指令決定在哪一個halfpage上進行讀寫,而真正的bit8的值是don't care的。

第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-step addressing。

若是NAND Flash的容量是256Mbit如下,那麼,block adress最高位只到bit24,所以尋址只須要3步。

NAND Flash 的數據是以bit 的方式保存在memory cell,通常來講,一個cell 中只能存儲一個bit。這些cell 以8 個或者16 個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device 的位寬。這些Line 會再組成Page.

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

1 block="16kbyte",

512Mbit=64Mbyte,

Numberof(block)=4096 1block=32page,

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

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

按照這樣的組織方式能夠造成所謂的三類地址:

--Block Address

-- Page Address

--Column Address

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

512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的column address。

32 個page 須要5bit 來表示,佔用A[13:9],即該page 在塊內的相對地址。Block的地址是由A14 以上的bit 來表示,例如512Mb 的NAND,共4096block,所以,須要12 個bit 來表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,則block address用A[26:24]表示。而page address就是blcok address|page address in block

NAND Flash 的地址表示爲:

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

地址傳送順序是Column Address,Page Address,Block Address。

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

以NAND_ADDR 爲例:

第1 步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令決定的,即指令決定在哪一個halfpage 上進行讀寫。而真正的bit8 的值是don't care 的。

第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-step addressing。 若是NAND Flash 的容量是256Mbit 如下,那麼,block adress 最高位只到bit24,所以尋址 只須要3 步。 下面,就x16 的NAND flash 器件稍微進行一下說明。 因爲一個page 的main area 的容量爲256word,仍至關於512byte。可是,這個時候沒有所謂 的1st halfpage 和2nd halfpage 之分了,因此,bit8就變得沒有意義了,也就是這個時候 bit8 徹底不用管,地址傳遞仍然和x8 器件相同。除了,這一點以外,x16 的NAND使用方法和 x8 的使用方法徹底相同。

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

1block = 32page

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

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

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

讀 命令有兩個,分別是 Read1,Read2其中Read1用於讀取Data Field的數據,而Read2則是用於讀取Spare Field的數據。對於Nand Flash來講,讀操做的最小操做單位爲Page,也就是說當咱們給定了讀取的起始位置後,讀操做將從該位置開始,連續讀取到本Page的最後一個 Byte爲止(能夠包括Spare Field)

Nand Flash的尋址

    Nand Flash的地址寄存器把一個完整的Nand Flash地址分解成Column Address與Page Address.進行尋址。

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

Paage Address:頁地址。因爲頁地址老是以512Bytes對齊的,因此它的低9位老是0。肯定讀寫操做是在Flash上的哪一個頁進行的。

Read1命令

當咱們獲得一個Nand Flash地址src_addr時咱們能夠這樣分解出Column Address和Page Address

column_addr=src_addr%512;                      // column address

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

也能夠這麼認爲,一個Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8並無出現,也就是A8被忽略,在下面你將瞭解到這是什麼緣由)

Read1 命令的操做分爲4個Cycle,發送完讀命令00h或01h(00h與01h的區別請見下文描述)以後將分4個Cycle發送參數,1st.Cycle是發送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle則是指定Page Address(每次向地址寄存器發送的數據只能是8位,因此17位的Page Address必須分紅3次進行發送

Read1的 命令裏面出現了兩個命令選項,分別是00h和01h。這裏出現了兩個讀命是否令你意識到什麼呢?是的,00h是用於讀寫1st half的命令,而01h是用於讀取2nd half的命令。如今我能夠結合上圖給你說明爲何K9F1208U0B的DataField被分爲2個half了。

如上文我所說起的,Read1的1st.Cycle是發送Column Address,假設我如今指定的Column Address是0,那麼讀操做將今後頁的第0號Byte開始一直讀取到此頁的最後一個Byte(包括Spare Field),若是我指定的Column Address是127,狀況也與前面同樣,但不知道你發現沒有,用於傳遞Column Address的數據線有8條(I/O0~I/O7,對應A0~A7,這也是A8爲何不出如今咱們傳遞的地址位中),也就是說咱們可以指定的 Column Address範圍爲0~255,但不要忘了,1個Page的DataField是由512個Byte組成的,假設如今我要指定讀命令從第256個字節處 開始讀取此頁,那將會發生什麼情景?我必須把Column Address設置爲256,但Column Address最大隻能是255,這就形成數據溢出。。。正是由於這個緣由咱們才把Data Field分爲兩個半區,當要讀取的起始地址(Column Address)在0~255內時咱們用00h命令,當讀取的起始地址是在256~511時,則使用01h命令.假設如今我要指定從第256個byte開 始讀取此頁,那麼我將這樣發送命令串

column_addr=256;

NF_CMD=0x01; ?                                     從2nd half開始讀取

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_CMD和NF_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,這樣讀操做將今後頁的第256號byte(2nd half的第0號byte)開始讀取數據。 nand_flash.c中包含3個函數

void nf_reset(void);

void nf_init(void);

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

nf_reset()將被nf_init()調用。nf_init()是nand_flash的初始化函數,在對nand flash進行任何操做以前,nf_init()必須被調用。

nf_read(unsigned int src_addr,unsigned   char *desc_addr,int size);爲讀函數,src_addr是nand flash上的地址,desc_addr是內存地址,size是讀取文件的長度。

在nf_reset和nf_read函數中存在兩個宏

NF_nFCE_L();

NF_nFCE_H();

你能夠看到當每次對Nand Flash進行操做以前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的控制寄存器進行初始化配置,rNFCONF是Nand Flash的配置寄存器,各個位的具體功能請參閱s3c2410數據手冊。

如今舉一個例子,假設我要從Nand Flash中的第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;                                        從2nd half開始讀取

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以後,數據指針會落在下一個Page的0號Column(0號Byte).

下面是源代碼:

/*

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

    author: caiyuqing   

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

*/

#include "s3c2410.h"

#include "nand_flash.h"

static unsigned char seBuf[16]={0xff};

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

unsigned short nf_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;    // Maker code(K9S1208V:0xec)

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

    NF_nFCE_H();        //chip enable

    return id;

}

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

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     r xxx,      r xxx       

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

    nf_reset();

}

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

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

{

    int i;

    unsigned int column_addr = src_addr % 512;            // column address

    unsigned int page_address = (src_addr >> 9);        // page addrress

    unsigned char *buf = desc_addr;

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

    {

        NF_nFCE_L();                    // enable chip

        /*NF_ADDR和NF_CMD爲nand_flash的地址和命令寄存器的解引用*/

        if(column_addr > 255)                // 2end halft   

            NF_CMD(0x01);                // Read2 command.   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 ;

}

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

NAND Flash 的數據是以bit 的方式保存在memory cell,通常來講,一個cell 中只能存儲一個bit。這些cell 以8 個或者16 個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device 的位寬。這些Line 會再組成Page.

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

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

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

按照這樣的組織方式能夠造成所謂的三類地址:

--Block Address -- Page Address --Column Address

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

512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的column address。

32 個page 須要5bit 來表示,佔用A[13:9],即該page 在塊內的相對地址。Block的地址是由A14 以上的bit 來表示,例如512Mb 的NAND,共4096block,所以,須要12 個bit 來表示,即A[25:14],若是是1Gbit 的528byte/page的NAND Flash,則block address用A[26:24]表示。而page address就是blcok address|page address in block

NAND Flash 的地址表示爲:

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

地址傳送順序是Column Address,Page Address,Block Address。

因爲地址只能在I/O[7:0]上傳遞,所以,必須採用移位的方式進行。例如,對於512Mbit x8 的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR 爲例: 第1 步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上,而halfpage pointer 即bit8 是由操做指令決定的,即指令決定在哪一個halfpage 上進行讀寫。而真正的bit8 的值是don't care 的。 第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-step addressing。 若是NAND Flash 的容量是256Mbit 如下,那麼,block adress 最高位只到bit24,所以尋址 只須要3 步。 下面,就x16 的NAND flash 器件稍微進行一下說明。 因爲一個page 的main area 的容量爲256word,仍至關於512byte。可是,這個時候沒有所謂 的1st halfpage 和2nd halfpage 之分了,因此,bit8就變得沒有意義了,也就是這個時候 bit8 徹底不用管,地址傳遞仍然和x8 器件相同。除了,這一點以外,x16 的NAND使用方法和 x8 的使用方法徹底相同。

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

1block = 32page

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

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

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

讀 命令有兩個,分別是 Read1,Read2其中Read1用於讀取Data Field的數據,而Read2則是用於讀取Spare Field的數據。對於Nand Flash來講,讀操做的最小操做單位爲Page,也就是說當咱們給定了讀取的起始位置後,讀操做將從該位置開始,連續讀取到本Page的最後一個 Byte爲止(能夠包括Spare Field)

Nand Flash的尋址

    Nand Flash的地址寄存器把一個完整的Nand Flash地址分解成Column Address與Page Address.進行尋址。

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

Paage Address:頁地址。因爲頁地址老是以512Bytes對齊的,因此它的低9位老是0。肯定讀寫操做是在Flash上的哪一個頁進行的。

Read1命令

當咱們獲得一個Nand Flash地址src_addr時咱們能夠這樣分解出Column Address和Page Address

column_addr=src_addr%512;                      // column address

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

也能夠這麼認爲,一個Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8並無出現,也就是A8被忽略,在下面你將瞭解到這是什麼緣由)

Read1 命令的操做分爲4個Cycle,發送完讀命令00h或01h(00h與01h的區別請見下文描述)以後將分4個Cycle發送參數,1st.Cycle是發送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle則是指定Page Address(每次向地址寄存器發送的數據只能是8位,因此17位的Page Address必須分紅3次進行發送

Read1的 命令裏面出現了兩個命令選項,分別是00h和01h。這裏出現了兩個讀命是否令你意識到什麼呢?是的,00h是用於讀寫1st half的命令,而01h是用於讀取2nd half的命令。如今我能夠結合上圖給你說明爲何K9F1208U0B的DataField被分爲2個half了。

如上文我所說起的,Read1的1st.Cycle是發送Column Address,假設我如今指定的Column Address是0,那麼讀操做將今後頁的第0號Byte開始一直讀取到此頁的最後一個Byte(包括Spare Field),若是我指定的Column Address是127,狀況也與前面同樣,但不知道你發現沒有,用於傳遞Column Address的數據線有8條(I/O0~I/O7,對應A0~A7,這也是A8爲何不出如今咱們傳遞的地址位中),也就是說咱們可以指定的 Column Address範圍爲0~255,但不要忘了,1個Page的DataField是由512個Byte組成的,假設如今我要指定讀命令從第256個字節處 開始讀取此頁,那將會發生什麼情景?我必須把Column Address設置爲256,但Column Address最大隻能是255,這就形成數據溢出。。。正是由於這個緣由咱們才把Data Field分爲兩個半區,當要讀取的起始地址(Column Address)在0~255內時咱們用00h命令,當讀取的起始地址是在256~511時,則使用01h命令.假設如今我要指定從第256個byte開 始讀取此頁,那麼我將這樣發送命令串

column_addr=256;

NF_CMD=0x01; ?                                     從2nd half開始讀取

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_CMD和NF_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,這樣讀操做將今後頁的第256號byte(2nd half的第0號byte)開始讀取數據。 nand_flash.c中包含3個函數

void nf_reset(void);

void nf_init(void);

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

nf_reset()將被nf_init()調用。nf_init()是nand_flash的初始化函數,在對nand flash進行任何操做以前,nf_init()必須被調用。

nf_read(unsigned int src_addr,unsigned   char *desc_addr,int size);爲讀函數,src_addr是nand flash上的地址,desc_addr是內存地址,size是讀取文件的長度。

在nf_reset和nf_read函數中存在兩個宏

NF_nFCE_L();

NF_nFCE_H();

你能夠看到當每次對Nand Flash進行操做以前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的控制寄存器進行初始化配置,rNFCONF是Nand Flash的配置寄存器,各個位的具體功能請參閱s3c2410數據手冊。

如今舉一個例子,假設我要從Nand Flash中的第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;                                        從2nd half開始讀取

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以後,數據指針會落在下一個Page的0號Column(0號Byte).

下面是源代碼:

/*

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

    author: caiyuqing   

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

*/

#include "s3c2410.h"

#include "nand_flash.h"

static unsigned char seBuf[16]={0xff};

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

unsigned short nf_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;    // Maker code(K9S1208V:0xec)

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

    NF_nFCE_H();        //chip enable

    return id;

}

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

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     r xxx,      r xxx       

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

    nf_reset();

}

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

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

{

    int i;

    unsigned int column_addr = src_addr % 512;            // column address

    unsigned int page_address = (src_addr >> 9);        // page addrress

    unsigned char *buf = desc_addr;

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

    {

        NF_nFCE_L();                    // enable chip

        /*NF_ADDR和NF_CMD爲nand_flash的地址和命令寄存器的解引用*/

        if(column_addr > 255)                // 2end halft   

            NF_CMD(0x01);                // Read2 command.   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結構與讀寫分析

今天在利用ARM7上的nandflash控制器驅動,ID已讀取成功,擦寫,讀取等還沒有完成,晚上就在網上查查相關的知識,以爲有一個不錯,轉貼以下:
NAND Flash 的數據是以bit 的方式保存在memory cell,通常來講,一個cell 中只能存儲一個bit。這些cell 以8 個或者16 個爲單位,連成bit line,造成所謂的byte(x8)/word(x16),這就是NAND Device 的位寬。這些Line 會再組成Page.
(Nand Flash 有多種結構,我使用的Nand Flash 是K9F1208,下面內容針對三星的K9F1208U0M),每頁528Byte,每32 個page 造成一個Block, Sizeof(block)=16kByte 。
1 block="16kbyte",512Mbit=64Mbyte,Numberof(block)=4096 1block=32page, 1page=528byte=512byte(Main Area)+16byte(Spare Area)
Nand flash 以頁爲單位讀寫數據,而以塊爲單位擦除數據。
按照這樣的組織方式能夠造成所謂的三類地址:
--Block Address -- Page Address --Column Address
對於NAND Flash 來說,地址和命令只能在I/O【7:0】上傳遞,數據寬度是8 位。
512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half和2nd half,各自的訪問由地址指針命令來選擇,A【7:0】就是所謂的column address。
32 個page 須要5bit 來表示,佔用A【13:9】,即該page 在塊內的相對地址。Block的地址是由A14 以上的bit 來表示,例如512Mb 的NAND,共4096block,所以,須要12 個bit 來表示,即A【25:14】,若是是1Gbit 的528byte/page的NAND Flash,則block address用A【26:24】表示。而page address就是blcok address|page address in block
NAND Flash 的地址表示爲:
Block Address|Page Address in block|halfpage pointer|Column Address
地址傳送順序是Column Address,Page Address,Block Address。
因爲地址只能在I/O【7:0】上傳遞,所以,必須採用移位的方式進行。例如,對於512Mbit x8 的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。以NAND_ADDR 爲例: 第1 步是傳遞column address,就是NAND_ADDR【7:0】,不需移位便可傳遞到I/O【7:0】上,而halfpage pointer 即bit8 是由操做指令決定的,即指令決定在哪一個halfpage 上進行讀寫。而真正的bit8 的值是don‘t care 的。 第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-step addressing。 若是NAND Flash 的容量是256Mbit 如下,那麼,block adress 最高位只到bit24,所以尋址只須要3 步。 下面,就x16 的NAND flash 器件稍微進行一下說明。 因爲一個page 的main area 的容量爲256word,仍至關於512byte。可是,這個時候沒有所謂 的1st halfpage 和2nd halfpage 之分了,因此,bit8就變得沒有意義了,也就是這個時候 bit8 徹底不用管,地址傳遞仍然和x8 器件相同。除了,這一點以外,x16 的NAND使用方法和 x8 的使用方法徹底相同。
正如硬盤的盤片被分爲磁道,每一個磁道又分爲若干扇區,一塊nand flash也分爲若干block,每一個block分爲如干page。通常而言,block、page之間的關係隨着芯片的不一樣而不一樣,典型的分配是這樣的:
1block = 32page
1page = 512bytes(datafield) + 16bytes(oob)

clip_image015

須要注意的是,對於flash的讀寫都是以一個page開始的,可是在讀寫以前必須進行flash的擦寫,而擦寫則是以一個block爲單位的。同時必須提醒的是,512bytes理論上被分爲1st half 和2sd half,每一個half各佔256個字節。
咱們討論的K9F1208U0B總共有4096 個Blocks,故咱們能夠知道這塊flash的容量爲4096 *(32 *528)= 69206016 Bytes = 66 MB 但事實上每一個Page上的最後16Bytes是用於存貯檢驗碼和其餘信息用的,並不能存放實際的數據,因此實際上咱們能夠操做的芯片容量爲4096 *(32 *512) = 67108864 Bytes = 64 MB由 上圖所示,1個Page總共由528 Bytes組成,這528個字節按順序由上而下以列爲單位進行排列(1列表明一個Byte。第0行爲第0 Byte ,第1行爲第1 Byte,以此類推,每一個行又由8個位組成,每一個位表示1個Byte裏面的1bit)。這528Bytes按功能分爲兩大部分,分別是Data Field和Spare Field,其中Spare Field佔528Bytes裏的16Bytes,這16Bytes是用於在讀寫操做的時候存放校驗碼用的,通常不用作普通數據的存儲區,除去這 16Bytes,剩下的512Bytes即是咱們用於存放數據用的Data Field,因此一個Page上雖然有528個Bytes,但咱們只按512Bytes進行容量的計算。
讀 命令有兩個,分別是 Read1,Read2其中Read1用於讀取Data Field的數據,而Read2則是用於讀取Spare Field的數據。對於Nand Flash來講,讀操做的最小操做單位爲Page,也就是說當咱們給定了讀取的起始位置後,讀操做將從該位置開始,連續讀取到本Page的最後一個 Byte爲止(能夠包括Spare Field)
Nand Flash的尋址
Nand Flash的地址寄存器把一個完整的Nand Flash地址分解成Column Address與Page Address.進行尋址。
Column Address: 列地址。Column Address其實就是指定Page上的某個Byte,指定這個Byte其實也就是指定此頁的讀寫起始地址。
Paage Address:頁地址。因爲頁地址老是以512Bytes對齊的,因此它的低9位老是0。肯定讀寫操做是在Flash上的哪一個頁進行的。
Read1命令
當咱們獲得一個Nand Flash地址src_addr時咱們能夠這樣分解出Column Address和Page Address
column_addr=src_addr%512; // column address
page_address=(src_addr>>9); // page address
也能夠這麼認爲,一個Nand Flash地址的A0~A7是它的column_addr,A9~A25是它的Page Address。(注意地址位A8並無出現,也就是A8被忽略,在下面你將瞭解到這是什麼緣由)
Read1 命令的操做分爲4個Cycle,發送完讀命令00h或01h(00h與01h的區別請見下文描述)以後將分4個Cycle發送參數,1st.Cycle是 發送Column Address。2nd.Cycle ,3rd.Cycle和4th.Cycle則是指定Page Address(每次向地址寄存器發送的數據只能是8位,因此17位的Page Address必須分紅3次進行發送
Read1的 命令裏面出現了兩個命令選項,分別是00h和01h。這裏出現了兩個讀命是否令你意識到什麼呢?是的,00h是用於讀寫1st half的命令,而01h是用於讀取2nd half的命令。如今我能夠結合上圖給你說明爲何K9F1208U0B的DataField被分爲2個half了。
如上文我所說起的,Read1的1st.Cycle是發送Column Address,假設我如今指定的Column Address是0,那麼讀操做將今後頁的第0號Byte開始一直讀取到此頁的最後一個Byte(包括Spare Field),若是我指定的Column Address是127,狀況也與前面同樣,但不知道你發現沒有,用於傳遞Column Address的數據線有8條(I/O0~I/O7,對應A0~A7,這也是A8爲何不出如今咱們傳遞的地址位中),也就是說咱們可以指定的 Column Address範圍爲0~255,但不要忘了,1個Page的DataField是由512個Byte組成的,假設如今我要指定讀命令從第256個字節處 開始讀取此頁,那將會發生什麼情景?我必須把Column Address設置爲256,但Column Address最大隻能是255,這就形成數據溢出。。。正是由於這個緣由咱們才把Data Field分爲兩個半區,當要讀取的起始地址(Column Address)在0~255內時咱們用00h命令,當讀取的起始地址是在256~511時,則使用01h命令.假設如今我要指定從第256個byte開 始讀取此頁,那麼我將這樣發送命令串
column_addr=256;
NF_CMD=0x01; ? 從2nd half開始讀取
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_CMD和NF_ADDR分別是NandFlash的命令寄存器和地址寄存器的地址解引用,我通常這樣定義它們,
#define rNFCMD (*(volatile unsigned ch ar *)0x4e000004) //NADD Flash command
#define rNFADDR (*(volatile unsigned ch ar *)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,這樣讀操做將今後頁的第256號byte(2nd half的第0號byte)開始讀取數據。 nand_flash.c中包含3個函數
void nf_reset(void);
void nf_init(void);
void nf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size);
nf_reset()將被nf_init()調用。nf_init()是nand_flash的初始化函數,在對nand flash進行任何操做以前,nf_init()必須被調用。
nf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size);爲讀函數,src_addr是nand flash上的地址,desc_addr是內存地址,size是讀取文件的長度。
在nf_reset和nf_read函數中存在兩個宏
NF_nFCE_L();
NF_nFCE_H();
你能夠看到當每次對Nand Flash進行操做以前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的控制寄存器進行初始化配置,rNFCONF是Nand Flash的配置寄存器,各個位的具體功能請參閱s3c2410數據手冊。
如今舉一個例子,假設我要從Nand Flash中的第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; 從2nd half開始讀取
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以後,數據指針會落在下一個Page的0號Column(0號Byte).
下面是源代碼:
/*
www.another-prj.com
author: caiyuqing
本代碼只屬於交流學習,不得用於商業開發
*/
#include "s3c2410.h"
#include "nand_flash.h"
static unsigned ch ar seBuf【16】={0xff};
//--------------------------------------------------------------------------------------
unsigned short nf_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; // Maker code(K9S1208V:0xec)
id|=NF_RDDATA(); // Devide code(K9S1208V:0x76)
NF_nFCE_H(); //chip enable
return id;
}
//--------------------------------------------------------------------------------------
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 r xxx, r xxx
// En r r ECCR nFCE="H" tACLS tWRPH0 tWRPH1
nf_reset();
}
//--------------------------------------------------------------------------------------
void nf_read(unsigned int src_addr,unsigned ch ar *desc_addr,int size)
{
int i;
unsigned int column_addr = src_addr % 512; // column address
unsigned int page_address = (src_addr >> 9); // page addrress
unsigned ch ar *buf = desc_addr;
while((unsigned int)buf < (unsigned int)(desc_addr) + size)
{
NF_nFCE_L(); // enable chip
/*NF_ADDR和NF_CMD爲nand_flash的地址和命令寄存器的解引用*/
if(column_addr > 255) // 2end halft
NF_CMD(0x01); // Read2 command. 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結構與驅動分析

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

2、NAND Flash地址的表示
512byte須要9bit來表示,對於528byte系列的NAND,這512byte被分紅1st half Page Register和2nd half Page Register,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的column address(列地址),在進行擦除操做時不須要它,why?由於以塊爲單位擦除。32個page須要5bit來表示,佔用A[13:9],即該page在塊內的相對地址。A8這一位地址被用來設置512byte的1st half page仍是2nd half page,0表示1st,1表示2nd。Block的地址是由A14以上的bit來表示。
例 如64MB(512Mb)的NAND flash(實際中因爲存在spare area,故都大於這個值),共4096block,所以,須要12個bit來表示,即A[25:14],若是是128MB(1Gbit) 的528byte/page的NAND Flash,則block address用A[26:14]表示。而page address就是blcok address|page address in block NAND Flash 的地址表示爲: Block Address|Page Address in block|halfpage pointer|Column Address 地址傳送順序是Column Address,Page Address,Block Address。
因爲地址只能在I/O[7:0]上傳遞,所以,必須採用移位的方式進行。 例如,對於512Mbit x8的NAND flash,地址範圍是0~0x3FF_FFFF,只要是這個範圍內的數值表示的地址都是有效的。 以NAND_ADDR 爲例:
第1 步是傳遞column address,就是NAND_ADDR[7:0],不需移位便可傳遞到I/O[7:0]上,而halfpage pointer即A8 是由操做指令決定的,即指令決定在哪一個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-step addressing。 若是NAND Flash 的容量是32MB(256Mbit)如下,那麼,block adress最高位只到bit24,所以尋址只須要3步。
下面,就x16 的NAND flash 器件稍微進行一下說明。 因爲一個page 的main area 的容量爲256word,仍至關於512byte。可是,這個時候沒有所謂的1st halfpage 和2nd halfpage 之分了,因此,bit8就變得沒有意義了,也就是這個時候 A8 徹底不用管,地址傳遞仍然和x8 器件相同。除了,這一點以外,x16 的NAND使用方法和 x8 的使用方法徹底相同。

3、NAND flash驅動解讀
之前因爲作移植多一些,那些工做 很簡單(如今看來),歷來都不用去關心驅動裏面到底怎麼實現的,這幾回面試才發現真的是學的太淺了,彷佛我還在學習仰泳而那些牛人基本都屬於潛水級的了, 潛的不知有多深。我對照着開發板所帶的NAND flash驅動和k9f1208的芯片資料把這些代碼通讀了一遍,終於明白了NAND flash的讀寫過程是如何實現的了。我所參考的驅動是mizi公司爲三星芯片所寫的,我看看了,大概和官方2.4.18內核的nand.c差很少。
在 s3c2410處理器中有專門的NAND flash控制器,他們位於SFR區,具體能夠參看s3c2410用戶手冊。如下的這些代碼都可以在vivi或者kernel裏面找到,文中會標明程序出 自何處。在vivi中,有關NAND flash的驅動都在driver/mtd/nand/下,該目錄中包含的源文件:smc_core.c是NAND flash的主要驅動。
NAND flash 芯片定義了一個很長的結構,這個結構中包含了操做NAND flash的函數和一些必要的變量(include/mtd/nand.h)。
struct nand_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_char val);
    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 */
    ……
#ifdef CONFIG_MTD_NAND_ECC
    u_char ecc_code_buf[6];
    u_char reserved[2];
#endif
#endif    /* CONFIG_MTD_NANDY */
};
縱觀對NAND flash的各類操做(read、write、erase),無外乎以下幾種操做:
1.選擇flash    nand_select()
2.發送命令     nand_command()
3.進行相應操做 read,write……
4.反選NAND flash   nand_deselect()

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

命令 命令值 描述
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            讀Flash ID號
NAND_CMD_ERASE2                 0xd0            擦寫操做
NAND_CMD_RESET                    oxff                復位操做

按照程序的註釋,能夠將該函數的實現分爲以下幾步:
一、Begin command latch cycle
實現代碼:
this->hwcontrol(NAND_CTL_SETCLE);
this->hwcontrol(NAND_CTL_DAT_OUT);
找到第二條語句的定義,發現什麼都麼作,不解!!但願達人解答。我猜測多是一個數據讀出的使能操做,容許數據讀出。
Command Latch Enable(CLE) and Address Latch Enable(ALE) are used to multiplex command and address respectively, via the I/O pins. The CLE input controls the path activation for commands sent to the command register. When active high, commands are latched into the command register through the I/O ports on the rising edge of the nWE signal. 看了這段英文相信對第一條語句的做用已經十分清楚了,他就是用來控制向命令寄存(COMMAND SET (NFCMD) REGISTER)發送命令的。
二、 Write out the command to the device
這部分對於不一樣的命令來講,操做的步驟也不太相同,若是爲寫操做,那麼還有根據flash不一樣的容量決定操做步驟,具體能夠參看代碼。若是爲其餘命令,那麼就是簡單的一行:
this->write_cmd (command);
將命令直接想到命令寄存器(NFCMD[7:0])中。
三、 Set ALE and clear CLE to start address cycle & Serially input address
1中已經提到了ALE和CLE的做用,如今開始發送地址。
實現代碼:
this->hwcontrol(NAND_CTL_CLRCLE); // clear the command latch enable
this->hwcontrol(NAND_CTL_SETALE); // set the address latch enable
而後按位操做,是用函數write_addr()將地址寫到NAND FLASH ADDRESS SET (NFADDR) REGISTER中。
四、 Latch in address
實現代碼:
this->hwcontrol(NAND_CTL_CLRALE);
this->hwcontrol(NAND_CTL_DAT_IN);
地址發送完畢,清楚ALE。
五、 Pause for 15us
我使用的VIVI中,使用udelay (15)延時15us,但這個時間會因NAND Flash的不一樣而不一樣。
3、Operation
根 據函數的不一樣,操做部分會不同,可是主要的是對NAND FLASH DATA (NFDATA) REGISTER的操做,或寫(編程)或者讀。經過讀或寫函數的參數來返回或傳遞讀出的值或寫入的值。寫得操做一般比較麻煩,他要將寫到flash的內容 從新讀出後進行ECC校驗,若是數據正確則在從新真正的寫(編程),若是錯誤,則將數據寫入flash的另外一個塊。讀和寫都是以頁爲單位進行操做。而擦除 則以塊爲單位,三個週期發送完地址。擦除完畢後一樣須要進行檢察以肯定是否擦除成功。
4、De-select the NAND device
實現代碼:
#define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE);
反 選flash吧,不知這樣叫正確與否,跟select the 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字節地址,在頁內隨機存取數據的操做僅僅用到第一和第二字節。塊擦除操做僅僅須要三個最高字節(第3、第四和第五字節)來選擇區塊。 圖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;一些由工廠標記爲壞的區塊可能在必定的溫度或電壓條件下仍然能工做,可是,未來可能會失效。若是壞塊信息被擦除,就沒法再恢復。


nand flash壞塊管理OOB,BBT,ECC

0.NAND的操做管理方式

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

1.爲何會出現壞塊
因爲NAND Flash的工藝不能保證NAND的Memory Array在其生命週期中保持性能的可靠,所以,在NAND的生產中及使用過程當中會產生壞塊。壞塊的特性是:當編程/擦除這個塊時,會形成Page Program和Block Erase操做時的錯誤,相應地反映到Status Register的相應位。

2.壞塊的分類
整體上,壞塊能夠分爲兩大類:(1)固有壞塊:這是生產過程當中產生的壞塊,通常芯片原廠都會在出廠時都會將每一個壞塊第一個page的spare area的第6個byte標記爲不等於0xff的值。(2)使用壞塊:這是在NAND Flash使用過程當中,若是Block Erase或者Page Program錯誤,就能夠簡單地將這個塊做爲壞塊來處理,這個時候須要把壞塊標記起來。爲了和固有壞塊信息保持一致,將新發現的壞塊的第一個page的 spare area的第6個Byte標記爲非0xff的值。

3.壞塊管理
根據上面的這些敘述,能夠了解NAND Flash出廠時在spare area中已經反映出了壞塊信息,所以,若是在擦除一個塊以前,必定要先check一下第一頁的spare area的第6個byte是不是0xff,若是是就證實這是一個好塊,能夠擦除;若是是非0xff,那麼就不能擦除,以避免將壞塊標記擦掉。固然,這樣處理可能會犯一個錯誤―――「錯殺僞壞塊」,由於在芯片操做過程當中可能因爲電壓不穩定等偶然因素會形成NAND操做的錯誤。可是,爲了數據的可靠性及軟件設計的簡單化,仍是須要遵守這個標準。

能夠用BBT:bad block table,即壞塊表來進行管理。各家對nand的壞塊管理方法都有差別。好比專門用nand作存儲的,會把bbt放到block0,由於第0塊必定是好 的塊。可是若是nand自己被用來boot,那麼第0塊就要存放程序,不能放bbt了。有的把bbt放到最後一塊,固然,這一塊堅定不能爲壞塊。bbt的大小跟nand大小有關,nand越大,須要的bbt也就越大。
4.壞塊糾正

     ECC:NAND Flash出錯的時候通常不會形成整個Block或是Page不能讀取或是所有出錯,而是整個Page(例如512Bytes)中只有一個或幾個bit出 錯。通常使用一種比較專用的校驗——ECC。ECC能糾正單比特錯誤和檢測雙比特錯誤,並且計算速度很快,但對1比特以上的錯誤沒法糾正,對2比特以上的 錯誤不保證能檢測。
      ECC通常每256字節原始數據生成3字節ECC校驗數據,這三字節共24比特分紅兩部分:6比特的列校驗和16比特的行校驗,多餘的兩個比特置1。(512生成兩組ECC?)
當往NAND Flash的page中寫入數據的時候,每256字節咱們生成一個ECC校驗和,稱之爲原ECC校驗和,保存到PAGE的OOB(out- of-band)數據區中。其位置就是eccpos[]。校驗的時候,根據上述ECC生成原理不難推斷:將從OOB區中讀出的原ECC校驗和新ECC校驗和按位異或,若結果爲0,則表示不存在錯(或是出現了ECC沒法檢測的錯誤);若3個字節異或結果中存在11個比特位爲1,表示存在一個比特錯誤,且可糾正;若3個字節異或結果中只存在1個比特位爲1,表示OOB區出錯;其餘狀況均表示出現了沒法糾正的錯誤。
5.補充

(1)須要對前面因爲Page Program錯誤發現的壞塊進行一下特別說明。若是在對一個塊的某個page進行編程的時候發生了錯誤就要把這個塊標記爲壞塊,首先就要把塊裏其餘好的 面的內容備份到另一個空的好塊裏面,而後,把這個塊標記爲壞塊。固然,這可能會犯「錯殺」之誤,一個補救的辦法,就是在進行完塊備份以後,再將這個壞塊 擦除一遍,若是Block Erase發生錯誤,那就證實這個塊是個真正的壞塊,那就絕不猶豫地將它打個「戳」吧!
(2)可能有人會問,爲何要使用每一個塊第一頁的spare area的第六個byte做爲壞塊標記。這是NAND Flash生產商的默認約定,你能夠看到Samsung,Toshiba,STMicroelectronics都是使用這個Byte做爲壞塊標記的。

(3)爲何好塊用0xff來標記?由於Nand Flash的擦除便是將相應塊的位所有變爲1,寫操做時只能把芯片每一位(bit)只能從1變爲0,而不能從0變爲1。0XFF這個值就是標識擦除成功,是好塊。

相關文章
相關標籤/搜索