天天看點

s5pv210 nandflash學習(一)

一、Flash簡介:

Flash全名叫做Flash Memory,屬于非易失性儲存設備(Non-volatile Memory Device),與此相對應的是易失性儲存設備(Volatile Memory Device)。這類裝置,除了Flash,還有其他比較常見的如硬碟,ROM等。

與此相對的,易失性就是斷電了,資料就丢失了,比如大家常用的記憶體,不論是以前的SDRAM,DDR SDRAM,還是現在的DDR2,DDR3等,都是斷電後,資料就沒了。

Flash的内部存儲是MOSFET,裡面有個懸浮門(Floating Gate),是真正存儲資料的單元。

Nandflash存儲器是flash存儲器的一種,其内部采用非線性宏單元模式,為固态大容量記憶體的實作提供了廉價有效的解決方案。

Nandflash存儲器具有容量較大,改寫速度快等優點,适用于大量資料的存儲,因而在業界得到了越來越廣泛的應用,如嵌入式産品中包括數位相機、MP3随身聽記憶卡、體積小巧的U盤、固态硬碟等。

Nandflash根據存儲原理分為三種,SLC(Single Level Cell)、MLC( Multi-Level Cell)、TLC(Tripple Level Cell):

SLC :1個存儲器儲存單元可存放1 bit的資料,隻存在0和1兩個充電值

MLC:1個存儲器儲存單元可存放2 bit的資料,存在00 01 10 11表示的4個值

TLC:1個存儲器儲存單元可存放3 bit的資料,存在000 001 010 011 100 101 110 111表示的8個值

最早出現的是SLC,一個浮栅MOS管(cell)隻存儲1bit資料,這種可靠性好,壽命長。

因為半導體晶片量産成本基本上與所占矽片面積成正比,為了追求存儲密度,降低閃存成本,有人想到了在一個cell裡存儲2bit資料,也就是通過在浮栅裡灌不同數量的電荷來區分4個狀态。相同的半導體制程、相同的矽片面積,存儲資料多了一倍。帶來的缺憾就是差錯率提高、讀寫壽命縮短。

再後來繼續追求低成本,有人造出了TLC,在一個cell裡存3bit,也就是将電荷量分成8個級别,這樣容量提升到3倍。結果是可靠性和壽命急劇下降。當然,普通民用,通過糾錯算法和各種減小磨損的算法,可以将就着用。現在大多數閃存都用了TLC。

再後來,還有人造QLC,在一個cell裡存16個狀态,對應4bit。結果是壽命更短,可靠性更差。大概擦寫壽命幾百次吧。

二、Nandflash工作原理:

根據NAND的實體結構,NAND是通過絕緣層存儲資料的。當你要寫入資料,需要施加電壓并形成一個電場,這樣電子就可以通過絕緣體進入到存儲單元,此時完成寫入資料。如果要删除存儲單元(資料),則要再次施加電壓讓電子穿過絕緣層,進而離開存儲單元。是以,NAND閃存在重新寫入新資料之前必須要删除原來資料。

由于TLC的1個存儲器儲存單元可存放3 bit的資料,為了區分,必須使用不同電壓來實作。除了能夠實作和SLC一樣的000(TLC)=0(SLC)和111(TLC)=1(SLC)外、還有另外六種資料格式必須采用其他不同的電壓來區分,讓不同數量的電子進入到存儲單元,實作不同的資料表達。這樣,才能讓TLC實作機關存儲單元存放比SLC、MLC更多資料的目的。

為什麼TLC的性能在三種媒體中最差?

由于資料寫入到TLC中需要八種不同電壓狀态, 而施加不同的電壓狀态、尤其是相對較高的電壓,需要更長的時間才能得以實作(電壓不斷增高的過程,直到合适的電壓值被發現才算完成)。

是以,在TLC中資料所需通路時間更長,是以傳輸速度更慢。經過實測,同等技術條件下,TLC的SSD性能是比不上MLC SSD的。

為什麼沒有機械結構的SSD還是出現壽命問題?

因為按照工作原理,閃存單元每次寫入或擦除的施加電壓過程都會導緻絕緣體矽氧化物的實體損耗。這東西本來就隻有區區10納米的厚度,每進行一次電子穿越就會變薄一些。也正因為如此,矽氧化物越來越薄,電子可能會滞留在二氧化矽絕緣層,擦寫時間也會是以延長,因為在達到何時的電壓之前需要更長時間、更高的加壓。主要制器是無法改變程式設計和擦寫電壓的。如果原本設計的電壓值工作異常,主要就會嘗試不同的電壓,這自然需要時間,也會給矽氧化物帶來更多壓力,加速了損耗。

最後,主要控制程式設計和擦寫一個TLC閃存單元所需要的時間也越來越長,最終達到嚴重影響性能、無法接受的地步,閃存區塊也就廢了。

同時,傳統的2D閃存在達到一定密度之後每個電源存儲的電荷量會下降,損耗後的TLC絕緣層,相鄰的存儲單元也會産生電荷幹擾,發展到20nm工藝之後,Cell單元之間的幹擾現象更加嚴重,如果資料長時間不重新整理的話就會出現像之前三星840 Evo那樣的讀取舊檔案會掉速的現象。

人們為什麼會擔心壽命?

由于TLC采用不同的電壓狀态,加上存儲容量多,擊穿絕緣層次數也比其他媒體多,于是加速了絕緣層的損耗過程。是以,TLC SSD的壽命比SLC、MLC短得多。

一開始TLC的P/E壽命隻有不到1000次,但是經過廠商改進算法以及優化主要,提升到1000到2000次。相比之下,MLC有3000到10000次擦寫壽命。如果使用者的PC隻有TLC SSD,那麼在日常使用環境下,如果一個120GB SSD的P/E壽命隻有不到1000次,并且每天寫入60GB的資料,那麼不到五年,SSD就會報廢。在目前性能過剩時代,這壽命是十分吓人的,是以以前人們十分擔心TLC SSD的壽命問題。

TLC SSD為何“倒行逆施”般井噴?

三星 850 EVO、東芝 Q300、英睿達BX200……我們耳熟能詳的SSD廠商都在2015年大規模推出了TLC SSD,氣勢磅礴。既然我們之前說了TLC那麼多的不足,為何廠商依然推廣呢?不是搬石頭砸自己腳嗎?

這一年來,SSD廠商最大的功勞就是解決了TLC的P/E壽命問題,讓TLC SSD的壽命上升到我們使用一台電腦正常周期上。主要算法的好壞會對性能和壽命造成非常大的影響,目前SSD廠商在主要技術上進行了很大的改進,信号處理,更強的ECC算法、擴大備用區域的容量增加預留白間等技術應用,從TLC的500–1000次P/E提升到目前的1000到2000次,一定程度上保證了可靠性與壽命。我們知道TLC的性能比較差,尤其寫入性能上,SSD廠商就通過SLC Cache的運用,隻要制造一個大容量的緩沖區使用者很多時候就不會感覺得到寫入速度慢,而且SLC Cache玩得好還有延長壽命的作用。另外,SSD廠商對于TLC SSD的質保提升到與MLC SSD基本一緻的水準,比如三星 TLC SSD的質保一般為五年,讓消費者在這五年的使用中高枕無憂。加上TLC天生的價格優勢,以及金字招牌,的确有很大的吸引力。越來越多的廠商參與到TLC SSD的競争中,價格不斷走低,讓不少對SSD感興趣的朋友嘗鮮一把,助長了TLC SSD的壯大。

TLC的未來?

TLC的逆襲就是揚長避短的道理。有市場,就有進步,相信廠商會對TLC技術進行更多的研究,保證物美價廉的TLC繼續生存下去。

比如三星3D NAND閃存就是TLC的一個重要方向。3D NAND是不再追求縮小Cell單元,而是通過3D堆疊技術封裝更多Cell單元,是以我們不必要追求更先進的制程,畢竟制程約先進,壽命反而越差。是以,可以使用相對更舊的工藝來生産3D NAND閃存,使用舊工藝的好處就是P/E擦寫次數大幅提升,而且電荷幹擾的情況也因為使用舊工藝而大幅減少。

未來的3D NAND可能都會做成可以MLC與TLC工作模式互相切換,也就是用TLC屏蔽一半容量、來充當MLC,也就是各種所謂的3bit MLC技術創新。類似地,東芝的Q300和OCZ TRION 100用的還是更長壽穩定的企業級eTLC聽起來SLC、MLC、TLC不再是泾渭分明。

三、Nandflash結構

s5pv210 nandflash學習(一)

從上面的圖中可以看到:一塊NandFlash可以劃分為2048個塊,一個塊分為64個頁,一頁分為2k+64位元組的兩個區,2k存放有效資料,64位元組儲存校驗資訊等。

這種劃分的形式在任何NandFlash中都是一樣的。隻是說塊數、頁數、每頁大小可能不一樣。

Row Address - 行位址可以簡單的認為是頁号。

Column Address - 列位址相當于在一個頁内的偏移位址。

有了頁号和偏移位址便能正确的通路到每個存儲單元。

塊是Nandflash擦除操作的基本/最小機關。

頁是Nandflash寫入操作的基本/最小機關。

每一個頁,對應還有一塊區域,叫做空閑區域(spare area)/備援區域(redundant area),而Linux系統中,一般叫做OOB(Out Of Band),這個區域,是最初基于Nand Flash的硬體特性:資料在讀寫時候相對容易錯誤,是以為了保證資料的正确性,必須要有對應的檢測和糾錯機制,此機制被叫做EDC(Error Detection Code)/ECC(Error Code Correction,或者Error Checking and Correcting),是以設計了多餘的區域,用于放置資料的校驗值。

Flash名稱的由來

Flash的擦除操作是以block塊為機關的,與此相對應的是其他很多儲存設備,是以bit位為最小讀取/寫入的機關,Flash是一次性地擦除整個塊,在發送一個擦除指令後,一次性地将一個block,常見的塊的大小是128KB/256KB等,全部擦除為1,也就是裡面的内容全部都是0xFF了,由于是一下子就擦除了,相對來說,擦除用的時間很短,可以用一閃而過來形容,是以叫做Flash Memory,中文有的翻譯為(快速)閃存。

Nandflash引腳功能說明

s5pv210 nandflash學習(一)

I/O0 ~ I/O7:用于輸入位址/資料/指令,輸出資料

CE:晶片選擇

RE:讀允許

WE:寫允許

WP:在寫或擦除期間,提供寫保護

R/B:讀/忙

ALE:位址鎖存 ALE = 1,data0-data7上傳輸的是位址

CLE:指令鎖存 CLE = 1,data0-data7上傳輸的是指令

ALE、CLE都是0的時候data0-data7上傳輸的是資料

WP:Write Protect,寫保護

在資料手冊中,你常會看到,對于一個引腳定義,有些字母上面帶一橫杠的,那是說明此引腳/信号是低電平有效,比如你上面看到的RE頭上有個橫線,就是說明,此RE是低電平有效,此外,為了書寫友善,在字母下面加’_’,也是表示低電平有效,比如我上面寫的WP,如果字母頭上啥都沒有,就是預設的高電平有效,比如上面的CLE,就是高電平有效。

為何需要ALE和CLE?

那是因為,Nand Flash就8個I/O,而且是複用的,也就是,可以傳資料,也可以傳位址,也可以傳指令,為了區分你目前傳入的到底是啥,是以,先要用發一個CLE(或ALE)指令,告訴nand Flash的控制器一聲,我下面要傳的是指令(或位址),這樣,裡面才能根據傳入的内容,進行對應的動作。否則,nand flash内部,怎麼知道你傳入的是資料,還是位址,還是指令啊,也就無法實作正确的操作了。

Nandflash隻有8個I/O引腳的好處?

1、減少外圍引腳。相對于并口(Parellel)48或52個引腳的Nor Flash來說,的确是大大減小了引腳數目,這樣封裝後的晶片體積就小很多。現在晶片在向體積更小,功能更強,功耗更低發展,減小晶片體積就是很大的優勢。同時,減少晶片接口也意味着使用此晶片的相關的外圍電路會更簡化,避免了繁瑣的硬體連線。

2、提高系統的可擴充性,因為沒有像其他裝置一樣用實體大小對應的完全數目的addr引腳,在晶片内部換了晶片的大小等的改動,對于用全部的位址addr的引腳,那麼就會引起這些引腳數目的增加,比如容量擴大一倍,位址空間/尋址空間擴大一倍,是以,位址線數目/addr引腳數目,就要多加一個,而對于統一用8個I/O的引腳的Nand Flash,由于對外提供的都是統一的8個引腳,内部的晶片大小的變化或者其他的變化,對于外部使用者(比如編寫nand flash驅動的人)來說,不需要關心,隻是保證新的晶片,還是遵循同樣的接口,同樣的時序,同樣的指令就可以了,這樣就提高了系統的擴充性。

Nandflash的一些典型特性

1、頁擦除時間是200us,有些慢的有800us。

2、塊擦除時間是1.5ms.

3、頁資料讀取到資料寄存器的時間一般是20us。

4、串行通路(Serial access)讀取一個資料的時間是25ns,而一些舊的nand flash是30ns,甚至是50ns。

5、輸入輸出端口是位址和資料以及指令一起複用的。

Nandflash中的特殊硬體結構

1、頁寄存器(Page Register)

由于Nand Flash讀取和程式設計操作來說,一般最小機關是頁,是以nand flash在硬體設計時候就考慮到這一特性,對于每一片都有一個對應的區域,專門用于存放将要寫入到實體存儲單元中去的或者剛從存儲單元中讀取出來的一頁資料,這個資料緩存區本質上就是一個buffer,隻是名字叫法不同,datasheet裡面叫做Page Register,此處翻譯為頁寄存器,實際了解為頁緩存更為恰當些。

注意:隻有寫到了這個頁緩存中,隻有等你發了對應的程式設計第二階段的确認指令0x10之後,實際的程式設計動作才開始,才開始把頁緩存中的資料,一點點寫到實體存儲單元中去。

2、Nand Flash中的壞塊(Bad Block)

Nand Flash中,一個塊中含有1個或多個位是壞的,就成為其為壞塊。

壞塊的穩定性是無法保證的,也就是說,不能保證你寫入的資料是對的,或者寫入對了,讀出來也不一定對的。而正常的塊,肯定是寫入讀出都是正常的。

壞塊有兩種:

(1)一種是出廠的時候,也就是你買到的新的還沒用過的Nand Flash,就可能包含了壞塊。此類出廠時就有的壞塊,被稱作factory (masked)bad block或initial bad/invalid block,在出廠之前,就會做對應的标記,标為壞塊。

具體标記的地方是,對于現在常見的頁大小為2K的Nand Flash,是塊中第一個頁的oob起始位置(關于什麼是頁和oob,下面會有詳細解釋)的第1個位元組(舊的小頁面,pagesize是512B甚至256B的nand flash,壞塊标記是第6個位元組),如果不是0xFF,就說明是壞塊。相對應的是,所有正常的塊,好的塊,裡面所有資料都是0xFF的。

(2)第二類叫做在使用過程中産生的,由于使用過程時間長了,在擦塊除的時候,出錯了,說明此塊壞了,也要在程式運作過程中發現并且标記成壞塊的。具體标記的位置,和上面一樣。這類塊叫做worn-out bad block。

對于壞塊的管理,在Linux系統中,叫做壞塊管理(BBM,Bad Block Managment),對應的會有一個表去記錄好塊,壞塊的資訊,以及壞塊是出廠就有的,還是後來使用産生的,這個表叫做 壞塊表(BBT,Bad Block Table)。在Linux核心MTD架構下的Nand Flash驅動,和Uboot中Nand Flash驅動中,在加載完驅動之後,如果你沒有加入參數主動要求跳過壞塊掃描的話,那麼都會去主動掃描壞塊,建立必要的BBT的,以備後面壞塊管理所使用。

而關于好塊和壞塊,Nand Flash在出廠的時候,會做出保證:

1、關于好的,可以使用的塊的數目達到一定的數目,比如三星的K9G8G08U0M,整個flash一共有4096個塊,出廠的時候,保證好的塊至少大于3996個,也就是意思是,你新買到這個型号的nand flash,最壞的可能,有3096-3996=100個壞塊。不過,事實上,現在出廠時的壞塊,比較少,絕大多數,都是使用時間長了,在使用過程中出現的。

2、保證第一個塊是好的,并且一般相對來說比較耐用。做此保證的主要原因是,很多Nand Flash壞塊管理方法中,就是将第一個塊,用來存儲上面提到的BBT,否則都是出錯幾率一樣的塊,那麼也就不太好管理了,連放BBT的地方都不好找了。

一般來說,不同型号的Nand Flash的資料手冊中,也會提到,自己的這個nand flash,最多允許多少個壞塊。就比如上面提到的,三星的K9G8G08U0M,最多有100個壞塊。

對于壞塊的标記,本質上,也隻是對應的flash上的某些位元組的資料是非0xFF而已,是以隻要是資料,就是可以讀取和寫入的。也就意味着,可以寫入其他值,也就把這個壞塊标記資訊破壞了。對于出廠時的壞塊,一般是不建議将标記好的資訊擦除掉的。壞塊的産生,在程式設計的時候、在擦出的時候、在讀取的時候

Nandflash中頁的通路順序

在一個塊内,對每一個頁進行程式設計的話,必須是順序的,而不能是随機的。比如,一個塊中有128個頁,那麼你隻能先對page0程式設計,再對page1程式設計,。。。。,而不能随機的,比如先對page3,再page1,page2.,page0,page4,.。

Nandflash行位址和列位址的計算

如上圖所示,Nandflash有2048Blocks,每個Block有64頁,每一頁含有2K的使用者可以使用的資料和64B的OOB。對于使用者來說這64B的資料時不用操作的,讀寫的時候也會忽略這部分。也就是說使用者在讀這一頁資料的時候隻會發出11位位址,不會發出12位位址(12位位址包含了讀寫OOB)。 如果讀取0x60000位址處的資料,那麼:

column_address = 0x60000 % 2048;

row_address = 0x60000 / 2048;

由于位址和資料都是通過8位引腳發送的,是以:

第一個周期發送的位址是: 0x60000 & 0xff 或column_address & 0xff;

第二個周期發送的位址為:(0x60000 >> 8) & 0x07或(column_address >> 8) & 0x07;

第三個周期發送的位址為:(0x60000 >> 11) & 0xff,這裡是右移11位,不是12位,或row_address & 0xff;

第四個周期發送的位址為:(0x60000 >> 19) & 0xff,或(row_address >> 8) & 0xff;

最後一個周期發送的位址為:(0x60000 >> 27) & 0x01,或(row_address >> 16) & 0x01。

片選無關(CE don’t-care)技術

很多Nand flash支援一個叫做CE don’t-care的技術,字面意思就是,不關心是否片選,那有人會問了,如果不片選,那還能對其操作嗎?答案就是,這個技術,主要用在當時是不需要選中晶片卻還可以繼續操作的這些情況:在某些應用,比如錄音,音頻播放等應用中,外部使用的微秒(us)級的時鐘周期,此處假設是比較少的2us,在進行讀取一頁或者對頁程式設計時,是對Nand Flash操作,這樣的串行(Serial Access)通路的周期都是20/30/50ns,都是納秒(ns)級的,此處假設是50ns,當你已經發了對應的讀或寫的指令之後,接下來隻是需要Nand Flash内部去自己操作,将資料讀取除了或寫入進去到内部的資料寄存器中而已,此處,如果可以把片選取消,CE是低電平有效,取消片選就是拉高電平,這樣會在下一個外部指令發送過來之前,即微秒量級的時間裡面,即2us-50ns≈2us,這段時間的取消片選,可以降低很少的系統功耗,但是多次的操作,就可以在很大程度上降低整體的功耗了。

總結起來簡單解釋就是:由于某些外部應用的頻率比較低,而Nand Flash内部操作速度比較快,是以具體讀寫操作的大部分時間裡面,都是在等待外部指令的輸入,同時卻選中晶片,産生了多餘的功耗,此“不關心片選”技術,就是在Nand Flash的内部的相對快速的操作(讀或寫)完成之後,就取消片選,以節省系統功耗。待下次外部指令/資料/位址輸入來的時候,再選中晶片,即可正常繼續操作了。這樣,整體上,就可以大大降低系統功耗了。

注:Nand Flash的片選與否,功耗差别會有很大。如果資料沒有記錯的話,我之前遇到我們系統裡面的nand flash的片選,大概有5個mA的電流輸出呢,要知道,整個系統優化之後的待機功耗,也才10個mA左右的。

帶EDC的拷回操作以及Sector的定義(Copy-Back Operation with EDC & Sector Definition for EDC)

Copy-Back功能,簡單的說就是,将一個頁的資料,拷貝到另一個頁。

如果沒有Copy-Back功能,那麼正常的做法就是,先要将那個頁的資料拷貝出來放到記憶體的資料buffer中,讀出來之後,再用寫指令将這頁的資料,寫到新的頁裡面。

而Copy-Back功能的好處在于,不需要用到外部的存儲空間,不需要讀出來放到外部的buffer裡面,而是可以直接讀取資料到内部的頁寄存器(page register)然後寫到新的頁裡面去。而且為了保證資料的正确,要硬體支援EDC(Error Detection Code),否則在資料的拷貝過程中,可能會出現錯誤,并且拷貝次數多了,可能會累積更多錯誤。而對于錯誤檢測來說,硬體一般支援的是512位元組資料,對應有16位元組用來存放校驗産生的ECC數值,而這512位元組一般叫做一個扇區。對于2K+64位元組大小的頁來說,按照512位元組分,分别叫做A,B,C,D區,而後面的64位元組的oob區域,按照16位元組一個區,分别叫做E,F,G,H區,對應存放A,B,C,D資料區的ECC的值。

總結:

512+16

2K +64 : A B C D - E F G H區

Copy-Back程式設計的主要作用在于,去掉了資料串行讀取出來再串行寫入進去的時間,這部分操作是比較耗時的,是以此技術可以提高程式設計效率,提高系統整體性能。

多片同時程式設計(Simultaneously Program Multi Plane)

對于有些新出的Nand Flash,支援同時對多個片進行程式設計,比如上面提到的三星的K9K8G08U0A,内部包含4片(Plane),分别叫做Plane0,Plane1,Plane2,Plane3。.由于硬體上,對于每一個Plane,都有對應的大小是2048+64=2112位元組的頁寄存器(Page Register),使得同時支援多個Plane程式設計成為可能。K9K8G08U0A支援同時對2個Plane進行程式設計。不過要注意的是,隻能對Plane0和Plane1或者Plane2和Plane3,同時程式設計,而不支援Plane0和Plane2同時程式設計。

交錯頁程式設計(Interleave Page Program)

多片同時程式設計,是針對一個chip裡面的多個Plane來說的,而此處的交錯頁程式設計,是指對多個chip而言的。

可以先對一個chip,假設叫chip1,裡面的一頁進行程式設計,然後此時,chip1内部就開始将資料一點點寫到頁裡面,就出于忙的狀态了,而此時可以利用這個時間,對出于就緒狀态的chip2,也進行頁程式設計,發送對應的指令後,chip2内部也就開始慢慢的寫資料到存儲單元裡面去了,也出于忙的狀态了。此時,再去檢查chip1,如果程式設計完成了,就可以開始下一頁的程式設計了,然後發完指令後,就讓其内部慢慢的程式設計吧,再去檢查chip2,如果也是程式設計完了,也就可以進行接下來的其他頁的程式設計了。如此,互動操作chip1和chip2,就可以有效地利用時間,使得整體程式設計效率提高近2倍,大大提高nand flash的程式設計/擦寫速度了。

随機輸出頁内資料(Random Data Output In a Page)

在介紹此特性之前,先要說說,與Random Data Output In a Page相對應的是,普通的,正常的輸出頁資料(sequential data output in a page)。

正常情況下,我們讀取資料,都是先發讀指令,然後等待資料從存儲單元到内部的頁資料寄存器中後,我們通過将RE(Read Enale,低電平有效)置低,然後從開始傳入的列起始位址,一點點讀出我們要的資料,直到頁的末尾,當然有可能還沒到頁位址的末尾就不再讀了。所謂的順序(sequential)讀取也就是,根據你之前發送的列位址的起始位址開始,每讀一個位元組的資料出來,内部的資料指針就加1,移到下個位元組的位址,然後你再讀下一個位元組資料,這樣就可以讀出你要的全部資料。

而此處的随機(random)讀取,就是在你正常的順序讀取的過程中,先發一個随機讀取的開始指令0x05指令,再傳入你要将内部那個資料指針定位到具體什麼位址,也就是2個cycle的列位址,然後再發随機讀取結束指令0xE0,然後内部那個資料位址指針,就會移動到你所指定的位置了,你接下來再讀取的資料,就是從那個制定位址開始的資料了。

而nand flash資料手冊裡面也說了,這樣的随機讀取,你可以多次操作,沒限制的。

請注意,上面你所傳入的位址都是列位址,也就是頁内位址,也就是說,對于頁大小為2K的nand flash來說,所傳入的位址應該是小于2048+64=2112的。不過,實際在nand flash的使用中,好像這種用法很少的。絕大多數,都是順序讀取資料。

頁程式設計(寫操作)

Nand flash的寫操作叫做程式設計Program,程式設計,一般情況下,是以頁為機關的。

有的Nand Flash,比如K9K8G08U0A,支援部分頁程式設計,但是有一些限制:在同一個頁内的,連續的部分頁的程式設計,不能超過4次。一般情況下,很少使用到部分頁程式設計,都是以頁為機關進行程式設計操作的。

一個操作,用兩個指令去實作,看起來是多餘,效率不高,但是實際上,有其特殊考慮,

至少對于塊擦除來說,開始的指令0x60是擦除設定指令(erase setup comman),然後傳入要擦除的塊位址,然後再傳入擦除确認指令(erase confirm command)0xD0,以開始擦除的操作。

這種分兩步:開始設定,最後确認的指令方式,是為了避免由于外部由于無意的/未預料而産生的噪音,假設此時即使被nand flash誤認為是擦除操作,但是沒有之後的确認操作0xD0,nand flash就不會去擦除資料,這樣使得資料更安全,不會由于噪音而誤操作。

讀操作過程

(1) 操作準備階段:此處是讀(Read)操作,是以先發一個讀指令的第一個階段指令0x00,,表示讓硬體先準備一下,接下來的操作是讀。

(2) 發送兩個周期的列位址,也就是頁内位址,表示我要從一個頁的什麼位置開始讀取資料。

(3) 接下來再傳入三個行位址,對應的也就是頁号。

(4) 然後再發一個讀操作的第二個周期指令0x30,接下來就是硬體内部自己的事情了。

(5) Nand Flash内部硬體邏輯,負責去按照你的要求,根據傳入的位址,找到哪個塊中的哪個頁,然後把整個這一頁的資料,都一點點搬運到頁緩存中去。而在此期間,你所能做的事,也就隻需要去讀取狀态寄存器,看看對應的位的值,也就是R/B那一位,是1還是0,0的話就表示系統是busy,仍在”忙“(着讀取資料),如果是1,就說系統活幹完了,忙清了,已經把整個頁的資料都搬運到頁緩存裡去了,你可以接下來讀取你要的資料了。

對于這裡估計有人會問了,這一個頁一共2048+64位元組,如果我傳入的頁内位址,就像上面給的1028一類的值,隻是想讀取1028到2011這部分資料,而不是頁開始的0位址整個頁的資料,那麼内部硬體卻讀取整個頁的資料出來,豈不是很浪費嗎?答案是,的确很浪費,效率看起來不高,但是實際就是這麼做的,而且本身讀取整個頁的資料,相對時間并不長,而且讀出來之後,内部資料指針會定位到你剛才所制定的1208的那個位置。

(6) 接下來,就是你“竊取“系統忙了半天之後的勞動成果的時候了。通過先去Nand Flash的控制器中的資料寄存器中寫入你要讀取多少個位元組(byte)/字(word),然後就可以去Nand Flash控制器的FIFO中,一點點讀取你要的資料了。

至此,整個Nand Flash的讀操作就完成了。

spare area/oob

Nand由于最初硬體設計時候考慮到,額外的錯誤校驗等需要空間,專門對應每個頁,額外設計了叫做spare area空區域,在其他地方,比如jffs2檔案系統中,也叫做oob(out of band)資料。

其具體用途,總結起來有:

  1. 标記是否是壞快
  2. 存儲ECC資料
  3. 存儲一些和檔案系統相關的資料,如jffs2就會用到這些空間存儲一些特定資訊,yaffs2檔案系統,會在oob中,存放很多和自己檔案系統相關的資訊。

記憶體技術裝置MTD(Memory Technology Device)

MTD,是Linux的儲存設備中的一個子系統。其設計此系統的目的是,對于記憶體類的裝置,提供一個抽象層,一個接口,使得對于硬體驅動設計者來說,可以盡量少的去關心存儲格式,比如FTL,FFS2等,而隻需要去提供最簡單的底層硬體裝置的讀/寫/擦除函數就可以了。而對于資料對于上層使用者來說是如何表示的,硬體驅動設計者可以不關心,而MTD儲存設備子系統都幫你做好了。

對于MTD字系統的好處,簡單解釋就是,他幫助你實作了很多對于以前或者其他系統來說,本來也是你驅動設計者要去實作的很多功能。換句話說,有了MTD,使得你設計Nand Flash的驅動,所要做的事情要少很多很多,因為大部分工作,都由MTD幫你做好了。

當然,這個好處的一個“副作用”就是,使得我們不了解的人去了解整個Linux驅動架構,以及MTD,變得更加複雜。但是,總的說,覺得是利遠遠大于弊,否則,就不僅需要你了解,而且還是做更多的工作,實作更多的功能了。

此外,還有一個重要的原因,那就是,前面提到的nand flash和普通硬碟等裝置的特殊性:

有限的通過出複用來實作輸入輸出指令和位址/資料等的IO接口,最小機關是頁而不是常見的bit,寫前需擦除等,導緻了這類裝置,不能像平常對待硬碟等操作一樣去操作,隻能采取一些特殊方法,這就誕生了MTD裝置的統一抽象層。MTD,将nand flash,nor flash和其他類型的flash等裝置,統一抽象成MTD裝置來管理,根據這些裝置的特點,上層實作了常見的操作函數封裝,底層具體的内部實作,就需要驅動設計者自己來實作了。具體的内部硬體裝置的讀/寫/擦除函數,那就是你必須實作的了。

錯誤校驗碼

Nand Flash實體特性上使得其資料讀寫過程中會發生一定幾率的錯誤,是以要有個對應的錯誤檢測和糾正的機制,于是才有此ECC,用于資料錯誤的檢測與糾正。Nand Flash的ECC,常見的算法有海明碼和BCH,這類算法的實作,可以是軟體也可以是硬體。不同系統,根據自己的需求,采用對應的軟體或者是硬體。

相對來說,硬體實作這類ECC算法,肯定要比軟體速度要快,但是多加了對應的硬體部分,是以成本相對要高些。如果系統對于性能要求不是很高,那麼可以采用軟體實作這類ECC算法,但是由于增加了資料讀取和寫入前後要做的資料錯誤檢測和糾錯,是以性能相對要降低一些,即Nand Flash的讀取和寫入速度相對會有所影響。其中,Linux中的軟體實作ECC算法,即NAND_ECC_SOFT模式,就是用的對應的海明碼。而對于目前常見的MLC的Nand Flash來說,由于容量比較大,動辄2GB,4GB,8GB等,常用BCH算法。BCH算法,相對來說,算法比較複雜。筆者由于水準有限,目前仍未完全搞懂BCH算法的原理。

BCH算法,通常是由對應的Nand Flash的Controller中,包含對應的硬體BCH ECC子產品,實作了BCH算法,而作為軟體方面,需要在讀取資料後,寫入資料之前,分别操作對應BCH相關的寄存器,設定成BCH模式,然後讀取對應的BCH狀态寄存器,得知是否有錯誤,和生成的BCH校驗碼,用于寫入。其具體代碼是如何操作這些寄存器的,由于是和具體的硬體,具體的nand flash的controller不同而不同,無法用同一的代碼。如果你是nand flash驅動開發者,自然會得到對應的起nand flash的controller部分的datasheet,按照手冊說明,去操作即可。

不過,額外說明一下的是,關于BCH算法,往往是要從專門的做軟體算法的廠家購買的,但是Micron之前在網上放出一個免費版本的BCH算法。

位反轉

Nand Flash的位反轉現象,主要是由以下一些原因/效應所導緻:

  1. 漂移效應(Drifting Effects):漂移效應指的是,Nand Flash中cell的電壓值,慢慢地變了,變的和原始值不一樣了
  2. 程式設計幹擾所産生的錯誤(Program-Disturb Errors):此現象有時候也叫做,過度程式設計效應(over-program effect),對于某個頁面的程式設計操作,即寫操作,引起非相關的其他的頁面的某個位跳變了。
  3. 讀操作幹擾産生的錯誤(Read-Disturb Errors):此效應是,對一個頁進行資料讀取操作,卻使得對應的某個位的資料,産生了永久性的變化,即Nand Flash上的該位的值變了。

Nand Flash位反轉類型和解決辦法:

一種是nand flash實體上的資料存儲的單元上的資料,是正确的,隻是在讀取此資料出來的資料中的某位,發生變化,出現了位反轉,即讀取出來的資料中,某位錯了,本來是0變成1,或者本來是1變成0了。此處可以成為軟體上位反轉。此資料位的錯誤,當然可以

通過一定的校驗算法檢測并糾正。

另外一種,就是nand flash中的實體存儲單元中,對應的某個位,實體上發生了變化,原來是1的,變成了0,或原來是0的,變成了1,發生了實體上的位的資料變化。此處可以成為硬體上的位反轉。此錯誤,由于是實體上發生的,雖然讀取出來的資料的錯誤,可以通過軟體或硬體去檢測并糾正過來,但是實體上真正發生的位的變化,則沒辦法改變了。不過個人了解,好像也是可以通過擦除Erase整個資料塊Block的方式去擦除此錯誤,不過在之後的Nand Flash的使用過程中,估計此位還是很可能繼續發生同樣的硬體的位反轉的錯誤。

以上兩種類型的位反轉,其實對于從Nand Flash讀取出來的資料來說,解決其中的錯誤的位的方法,都是一樣的,即通過一定的校驗算法,常稱為ECC,去檢測出來,或檢測并糾正錯誤。

如果隻是單獨檢測錯誤,那麼如果發現資料有誤,那麼再重新讀取一次即可。實際中更多的做法是,ECC校驗發現有錯誤,會有對應的算法去找出哪位錯誤并且糾正過來。其中對錯誤的檢測和糾正,具體的實作方式,有軟體算法,也有硬體實作,即硬體Nand Flash的控制器controller本身包含對應的硬體子產品以實作資料的校驗和糾錯的。