日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

NandFlash详述

發(fā)布時(shí)間:2023/12/10 编程问答 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NandFlash详述 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

1. 硬件特性:

Flash的硬件實(shí)現(xiàn)機(jī)制】

Flash全名叫做Flash Memory,屬于非易失性存儲(chǔ)設(shè)備(Non-volatile Memory Device),與此相對(duì)應(yīng)的是易失性存儲(chǔ)設(shè)備(Volatile Memory Device)。這類設(shè)備,除了Flash,還有其他比較常見的如硬盤,ROM等,

與此相對(duì)的,易失性就是斷電了,數(shù)據(jù)就丟失了,比如大家常用的內(nèi)存,不論是以前的SDRAM,DDR SDRAM,還是現(xiàn)在的DDR2,DDR3等,都是斷電后,數(shù)據(jù)就沒(méi)了。

Flash的內(nèi)部存儲(chǔ)是MOSFET,里面有個(gè)懸浮門(Floating Gate),是真正存儲(chǔ)數(shù)據(jù)的單元。

-------------------------------------------------------------------------------------------------------------------------

金屬-氧化層-半導(dǎo)體-場(chǎng)效晶體管,簡(jiǎn)稱金氧半場(chǎng)效晶體管(Metal-Oxide-Semiconductor Field-Effect Transistor, MOSFET)是一種可以廣泛使用在模擬電路與數(shù)字電路的場(chǎng)效晶體管(field-effect transistor)。MOSFET依照其“通道”的極性不同,可分為n-type與p-type的MOSFET,通常又稱為NMOSFET與PMOSFET,其他簡(jiǎn)稱尚包括NMOS FET、PMOS FET、nMOSFET、pMOSFET等。

-------------------------------------------------------------------------------------------------------------------------

Flash之前,紫外線可擦除(uv-erasable)EPROM,就已經(jīng)采用用Floating Gate存儲(chǔ)數(shù)據(jù)這一技術(shù)了。


1.典型的Flash內(nèi)存單元的物理結(jié)構(gòu)

數(shù)據(jù)在Flash內(nèi)存單元中是的。

存儲(chǔ)電荷的多少,取決于圖中的外部門(external gate)所被施加的電壓,其控制了是向存儲(chǔ)單元中沖入電荷還是使其釋放電荷。

數(shù)據(jù)的表示,以所存儲(chǔ)的電荷的電壓是否超過(guò)一個(gè)特定的閾值Vth來(lái)表示。

SLCMLC的實(shí)現(xiàn)機(jī)制】

Nand Flash按照內(nèi)部存儲(chǔ)數(shù)據(jù)單元的電壓的不同層次,也就是單個(gè)內(nèi)存單元中,是存儲(chǔ)1位數(shù)據(jù),還是多位數(shù)據(jù),可以分為SLCMLC

1. SLCSingle Level Cell:

單個(gè)存儲(chǔ)單元,只存儲(chǔ)一位數(shù)據(jù),表示成10.

就是上面介紹的,對(duì)于數(shù)據(jù)的表示,單個(gè)存儲(chǔ)單元中內(nèi)部所存儲(chǔ)電荷的電壓,和某個(gè)特定的閾值電壓Vth,相比,如果大于此Vth值,就是表示1,反之,小于Vth,就表示0.

對(duì)于nand Flash的數(shù)據(jù)的寫入1,就是控制External Gate去充電,使得存儲(chǔ)的電荷夠多,超過(guò)閾值Vth,就表示1了。而對(duì)于寫入0,就是將其放電,電荷減少到小于Vth,就表示0了。

關(guān)于為何Nand Flash不能從0變成1,我的理解是,物理上來(lái)說(shuō),是可以實(shí)現(xiàn)每一位的,從0變成1的,但是實(shí)際上,對(duì)于實(shí)際的物理實(shí)現(xiàn),出于效率的考慮,如果對(duì)于,每一個(gè)存儲(chǔ)單元都能單獨(dú)控制,即,0變成1就是,對(duì)每一個(gè)存儲(chǔ)單元單獨(dú)去充電,所需要的硬件實(shí)現(xiàn)就很復(fù)雜和昂貴,同時(shí),所進(jìn)行對(duì)塊擦除的操作,也就無(wú)法實(shí)現(xiàn)之前的,一閃而過(guò)的速度了,也就失去了Flash的眾多特性了。

// 也就是放電的思路還是容易些。1->0

2. MLCMulti Level Cell

SLC相對(duì)應(yīng),就是單個(gè)存儲(chǔ)單元,可以存儲(chǔ)多個(gè)位,比如2位,4位等。其實(shí)現(xiàn)機(jī)制,說(shuō)起來(lái)比較簡(jiǎn)單,就是,通過(guò)控制內(nèi)部電荷的多少,分成多個(gè)閾值,通過(guò)控制里面的電荷多少,而達(dá)到我們所需要的存儲(chǔ)成不同的數(shù)據(jù)。比如,假設(shè)輸入電壓是Vin4V(實(shí)際沒(méi)有這樣的電壓,此處只是為了舉例方便),那么,可以設(shè)計(jì)出22次方=4個(gè)閾值,1/4Vin1V2/4Vin2V3/4Vin3VVin4V,分別表示2位數(shù)據(jù)00011011,對(duì)于寫入數(shù)據(jù),就是充電,通過(guò)控制內(nèi)部的電荷的多少,對(duì)應(yīng)表示不同的數(shù)據(jù)。

對(duì)于讀取,則是通過(guò)對(duì)應(yīng)的內(nèi)部的電流(與Vth成反比),然后通過(guò)一系列解碼電路完成讀取,解析出所存儲(chǔ)的數(shù)據(jù)。這些具體的物理實(shí)現(xiàn),都是有足夠精確的設(shè)備和技術(shù),才能實(shí)現(xiàn)精確的數(shù)據(jù)寫入和讀出的。

單個(gè)存儲(chǔ)單元可以存儲(chǔ)2位數(shù)據(jù)的,稱作22次方=4 Level Cell,而不是2 Level Cell;

同理,對(duì)于新出的單個(gè)存儲(chǔ)單元可以存儲(chǔ)4位數(shù)據(jù)的,稱作24次方=16 Level Cell

【關(guān)于如何識(shí)別SLC還是MLC

Nand Flash設(shè)計(jì)中,有個(gè)命令叫做Read ID,讀取ID,意思是讀取芯片的ID,就像大家的身份證一樣,這里讀取的ID中,是:

讀取好幾個(gè)字節(jié),一般最少是4個(gè),新的芯片,支持5個(gè)甚至更多,從這些字節(jié)中,可以解析出很多相關(guān)的信息,比如:

Nand Flash內(nèi)部是幾個(gè)芯片(chip)所組成的,

每個(gè)chip包含了幾片(Plane),

每一片中的頁(yè)大小,塊大小,等等。

在這些信息中,其中有一個(gè),就是識(shí)別此flashSLC還是MLC。下面這個(gè)就是最常見的Nand Flashdatasheet中所規(guī)定的,第3個(gè)字節(jié),3rd byte,所表示的信息,其中就有SLC/MLC的識(shí)別信息:




Description

I/O7

I/O6

I/O5 I/O4

I/O3 I/O2

I/O1 I/O0

Internal

Chip Number

1

2

4

8

0 0

0 1

1 0

1 1

Cell Type

2 Level Cell

4 Level Cell

8 Level Cell

16 Level Cell

0 0

0 1

1 0

1 1

Number of

Simultaneously

Programmed Pages

1

2

4

8

0 0

0 1

1 0

1 1

Interleave Program

Between multiple chips

Not Support

Support

0

1

Cache Program

Not Support

Support

0

1

1.Nand Flash3個(gè)ID的含義

Nand Flash的物理存儲(chǔ)單元的陣列組織結(jié)構(gòu)】

Nand flash的內(nèi)部組織結(jié)構(gòu),此處還是用圖來(lái)解釋,比較容易理解:

2.Nand Flash物理存儲(chǔ)單元的陣列組織結(jié)構(gòu)


上圖是K9K8G08U0Adatasheet中的描述。

簡(jiǎn)單解釋就是:

1.一個(gè)nand flash由很多個(gè)塊(Block)組成,

塊的大小一般是

-> 128KB

-> 256KB

-> 512KB

此處是128KB

2.每個(gè)塊里面又包含了很多頁(yè)(page)。每個(gè)頁(yè)的大小,

老的nand flash,頁(yè)大小是256B512B

這類的nand flash被稱作small block,。地址周期只有4個(gè)。

對(duì)于現(xiàn)在常見的nand flash多數(shù)是2KB

被稱作big block,對(duì)應(yīng)的發(fā)讀寫命令地址,一共5個(gè)周期(cycle)

更新的nand flash4KB

,也是Nand Flash的擦除操作的基本/最小單位。

3.每一個(gè)頁(yè),對(duì)應(yīng)還有一塊區(qū)域,叫做空閑區(qū)域(spare area/冗余區(qū)域(redundant area),而Linux系統(tǒng)中,一般叫做OOBOut Of Band),這個(gè)區(qū)域,是最初基于Nand Flash的硬件特性:數(shù)據(jù)在讀寫時(shí)候相對(duì)容易錯(cuò)誤,所以為了保證數(shù)據(jù)的正確性,必須要有對(duì)應(yīng)的檢測(cè)和糾錯(cuò)機(jī)制,此機(jī)制被叫做EDC(Error Detection Code)/ECCError Code Correction,或者Error Checking and Correcting),所以設(shè)計(jì)了多余的區(qū)域,用于放置數(shù)據(jù)的校驗(yàn)值。

頁(yè), 是Nand Flash的寫入操作的基本/最小的單位。

Nand Flash數(shù)據(jù)存儲(chǔ)單元的整體架構(gòu)】

簡(jiǎn)單說(shuō)就是,常見的nand flash,內(nèi)部只有一個(gè)chip,每個(gè)chip只有一個(gè)plane

而有些復(fù)雜的,容量更大的nand flash,內(nèi)部有多個(gè)chip,每個(gè)chip有多個(gè)plane。這類的nand flash,往往也有更加高級(jí)的功能,比如下面要介紹的Multi Plane ProgramInterleave Page Program等。

比如,型號(hào)為K9K8G08U0A這個(gè)芯片(chip),

內(nèi)部有:

K9F4G08U0A (256MB) : Plane (1Gb), Plane (1Gb)

K9F4G08U0A (256MB) : Plane (1Gb), Plane (1Gb)

K9WAG08U1A ,內(nèi)部包含了2個(gè)K9K8G08U0A

K9NBG08U5A ,內(nèi)部包含了4個(gè)K9K8G08U0A

Flash名稱的由來(lái)】

Flash的擦除操作是以block塊為單位的,與此相對(duì)應(yīng)的是其他很多存儲(chǔ)設(shè)備,是以bit位為最小讀取/寫入的單位,Flash是一次性地擦除整個(gè)塊:在發(fā)送一個(gè)擦除命令后,一次性地將一個(gè)block,常見的塊的大小是128KB/256KB。。,全部擦除為1,也就是里面的內(nèi)容全部都是0xFF,由于是一下子就擦除了,相對(duì)來(lái)說(shuō),擦除用的時(shí)間很短,可以用一閃而過(guò)來(lái)形容,所以,叫做Flash Memory。中文有的翻譯為(快速)閃存。

Flash相對(duì)于普通設(shè)備的特殊性】

1. 上面提到過(guò)的,Flash最小操作單位,有些特殊。

一般設(shè)備,比如硬盤/內(nèi)存,讀取和寫入都是以bit位為單位,讀取一個(gè)bit的值,將某個(gè)值寫入對(duì)應(yīng)的地址的位,都是可以按位操作的。

但是Flash由于物理特性,使得內(nèi)部存儲(chǔ)的數(shù)據(jù),只能從1變成0,這點(diǎn),可以從前面的內(nèi)部實(shí)現(xiàn)機(jī)制了解到,只是方便統(tǒng)一充電,不方便單獨(dú)的存儲(chǔ)單元去放電,所以才說(shuō),只能從1變成0,也就是釋放電荷。

所以,總結(jié)一下Flash的特殊性如下:

普通設(shè)備(硬盤/內(nèi)存等)

Flash

讀取/寫入的叫法

讀取/寫入

讀取/編程(Program)

讀取/寫入的最小單位

Bit/

Page/頁(yè)

擦除(Erase)操作的最小單位

Bit/

Block/

擦除操作的含義

將數(shù)據(jù)刪除/全部寫入0

將整個(gè)塊都擦除成全是1,也就是里面的數(shù)據(jù)都是0xFF

對(duì)于寫操作

直接寫即可

在寫數(shù)據(jù)之前,要先擦除,然后再寫

2.Flash和普通設(shè)備相比所具有的特殊性

注:

之所以將寫操作叫做編程,是因?yàn)?#xff0c;flash和之前的EPROMEEPROM繼承發(fā)展而來(lái),而之前的EEPROM(Electrically Erasable Programmable Read-Only Memory),往里面寫入數(shù)據(jù),就叫做編程Program,之所以這么稱呼,是因?yàn)槠鋵?duì)數(shù)據(jù)的寫入,是需要用電去擦除/寫入的,就叫做編程。

對(duì)于目前常見的頁(yè)大小是2K/4KNand Flash,其塊的大小有128KB/256KB/512KB等。而對(duì)于Nor Flash,常見的塊大小有64K/32K等。

③在寫數(shù)據(jù)之前,要先擦除,內(nèi)部就都變成0xFF了,然后才能寫入數(shù)據(jù),也就是將對(duì)應(yīng)位由1變成0

Nand Flash引腳(Pin)的說(shuō)明】


3.Nand Flash引腳功能說(shuō)明

上圖是常見的Nand Flash所擁有的引腳(Pin)所對(duì)應(yīng)的功能,簡(jiǎn)單翻譯如下:

1. I/O0 ~ I/O7:用于輸入地址/數(shù)據(jù)/命令,輸出數(shù)據(jù)

2. CLECommand Latch Enable,命令鎖存使能,在輸入命令之前,要先在模式寄存器中,設(shè)置CLE使能

3. ALEAddress Latch Enable,地址鎖存使能,在輸入地址之前,要先在模式寄存器中,設(shè)置ALE使能

4. CE#Chip Enable,芯片使能,在操作Nand Flash之前,要先選中此芯片,才能操作

5. RE#Read Enable,讀使能,在讀取數(shù)據(jù)之前,要先使CE#有效。

6. WE#Write Enable,寫使能,在寫取數(shù)據(jù)之前,要先使WE#有效。

7. WP#Write Protect,寫保護(hù)

8. R/B#:Ready/Busy Output,就緒/,主要用于在發(fā)送完編程/擦除命令后,檢測(cè)這些操作是否完成,,表示編程/擦除操作仍在進(jìn)行中,就緒表示操作完成.

9. VccPower,電源

10. VssGround,接地

11. N.CNon-Connection,未定義,未連接。

[小常識(shí)]

在數(shù)據(jù)手冊(cè)中,你常會(huì)看到,對(duì)于一個(gè)引腳定義,有些字母上面帶一橫杠的,那是說(shuō)明此引腳/信號(hào)是低電平有效,比如你上面看到的RE頭上有個(gè)橫線,就是說(shuō)明,此RE是低電平有效,此外,為了書寫方便,在字母后面加“#”,也是表示低電平有效,比如我上面寫的CE#;如果字母頭上啥都沒(méi)有,就是默認(rèn)的高電平有效,比如上面的CLE,就是高電平有效。

【為何需要ALECLE

突然想明白了,Nand Flash,為何設(shè)計(jì)這么多的命令,把整個(gè)系統(tǒng)搞這么復(fù)雜的原因了:

比如命令鎖存使能(Command Latch Enable,CLE)地址鎖存使能(Address Latch EnableALE),那是因?yàn)?#xff0c;Nand Flash8個(gè)I/O,而且是復(fù)用的,也就是,可以傳數(shù)據(jù),也可以傳地址,也可以傳命令,為了區(qū)分你當(dāng)前傳入的到底是啥,所以,先要用發(fā)一個(gè)CLE(或ALE)命令,告訴nand Flash的控制器一聲,我下面要傳的是命令(或地址),這樣,里面才能根據(jù)傳入的內(nèi)容,進(jìn)行對(duì)應(yīng)的動(dòng)作。否則,nand flash內(nèi)部,怎么知道你傳入的是數(shù)據(jù),還是地址,還是命令啊,也就無(wú)法實(shí)現(xiàn)正確的操作了.

Nand Flash只有8個(gè)I/O引腳的好處】

1. 減少外圍引腳:相對(duì)于并口(Parellel)Nor Flash4852個(gè)引腳來(lái)說(shuō),的確是大大減小了引腳數(shù)目,這樣封裝后的芯片體積,就小很多。現(xiàn)在芯片在向體積更小,功能更強(qiáng),功耗更低發(fā)展,減小芯片體積,就是很大的優(yōu)勢(shì)。同時(shí),減少芯片接口,也意味著使用此芯片的相關(guān)的外圍電路會(huì)更簡(jiǎn)化,避免了繁瑣的硬件連線。

2. 提高系統(tǒng)的可擴(kuò)展性,因?yàn)闆](méi)有像其他設(shè)備一樣用物理大小對(duì)應(yīng)的完全數(shù)目的addr引腳,在芯片內(nèi)部換了芯片的大小等的改動(dòng),對(duì)于用全部的地址addr的引腳,那么就會(huì)引起這些引腳數(shù)目的增加,比如容量擴(kuò)大一倍,地址空間/尋址空間擴(kuò)大一倍,所以,地址線數(shù)目/addr引腳數(shù)目,就要多加一個(gè),而對(duì)于統(tǒng)一用8個(gè)I/O的引腳的Nand Flash,由于對(duì)外提供的都是統(tǒng)一的8個(gè)引腳,內(nèi)部的芯片大小的變化或者其他的變化,對(duì)于外部使用者(比如編寫nand flash驅(qū)動(dòng)的人)來(lái)說(shuō),不需要關(guān)心,只是保證新的芯片,還是遵循同樣的接口,同樣的時(shí)序,同樣的命令,就可以了。這樣就提高了系統(tǒng)的擴(kuò)展性。

【Nand flash的一些典型(typical)特性】

1.頁(yè)擦除時(shí)間是200us,有些慢的有800us。

2.塊擦除時(shí)間是1.5ms.

3.頁(yè)數(shù)據(jù)讀取到數(shù)據(jù)寄存器的時(shí)間一般是20us。

4.串行訪問(wèn)(Serial access)讀取一個(gè)數(shù)據(jù)的時(shí)間是25ns,而一些舊的nand flash是30ns,甚至是50ns。

5.輸入輸出端口是地址和數(shù)據(jù)以及命令一起multiplex復(fù)用的。

以前老的Nand Flash,編程/擦除時(shí)間比較短,比如K9G8G08U0M,才5K次,而后來(lái)很多6.nand flash的編程/擦除的壽命,最多允許的次數(shù),以前的nand flash多數(shù)是10K次,也就是1萬(wàn)次,而現(xiàn)在很多新的nand flash,技術(shù)提高了,比如,Micron的MT29F1GxxABB,Numonyx的NAND04G-B2D/NAND08G-BxC,都可以達(dá)到100K,也就是10萬(wàn)次的編程/擦除。和之前常見的Nor Flash達(dá)到同樣的使用壽命了。

7.48引腳的TSOP1封裝或 52引腳的ULGA封裝

【Nand Flash中的特殊硬件結(jié)構(gòu)】

由于nand flash相對(duì)其他常見設(shè)備來(lái)說(shuō),比較特殊,所以,特殊的設(shè)備,也有特殊的設(shè)計(jì),所以,有些特殊的硬件特性,就有比較解釋一下:

1. 頁(yè)寄存器(Page Register):由于Nand Flash讀取和編程操作來(lái)說(shuō),一般最小單位是頁(yè),所以,nand flash在硬件設(shè)計(jì)時(shí)候,就考慮到這一特性,對(duì)于每一片,都有一個(gè)對(duì)應(yīng)的區(qū)域,專門用于存放,將要寫入到物理存儲(chǔ)單元中去的或者剛從存儲(chǔ)單元中讀取出來(lái)的,一頁(yè)的數(shù)據(jù),這個(gè)數(shù)據(jù)緩存區(qū),本質(zhì)上就是一個(gè)buffer,但是只是名字叫法不同,datasheet里面叫做Page Register,此處翻譯為頁(yè)寄存器,實(shí)際理解為頁(yè)緩存,更為恰當(dāng)些。

注意:只有寫到了這個(gè)頁(yè)緩存中,只有等你發(fā)了對(duì)應(yīng)的編程第二階段的確認(rèn)命令0x10之后,實(shí)際的編程動(dòng)作才開始,才開始把頁(yè)緩存中的數(shù)據(jù),一點(diǎn)點(diǎn)寫到物理存儲(chǔ)單元中去。

所以,簡(jiǎn)單總結(jié)一下就是,對(duì)于數(shù)據(jù)的流向,實(shí)際是經(jīng)過(guò)了如下步驟:


圖4 Nand Flash讀寫時(shí)的數(shù)據(jù)流向

【Nand Flash中的壞塊(Bad Block)】

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

壞塊的穩(wěn)定性是無(wú)法保證的,也就是說(shuō),不能保證你寫入的數(shù)據(jù)是對(duì)的,或者寫入對(duì)了,讀出來(lái)也不一定對(duì)的。而正常的塊,肯定是寫入讀出都是正常的。

壞塊有兩種:

(1)一種是出廠的時(shí)候,也就是,你買到的新的,還沒(méi)用過(guò)的Nand Flash,就可以包含了壞塊。此類出廠時(shí)就有的壞塊,被稱作factory (masked)bad block或initial bad/invalid block,在出廠之前,就會(huì)做對(duì)應(yīng)的標(biāo)記,標(biāo)為壞塊。

具體標(biāo)記的地方是,對(duì)于現(xiàn)在常見的頁(yè)大小為2K的Nand Flash,是塊中第一個(gè)頁(yè)的oob起始位置(關(guān)于什么是頁(yè)和oob,下面會(huì)有詳細(xì)解釋)的第1個(gè)字節(jié)(舊的小頁(yè)面,pagesize是512B甚至256B的nand flash,壞塊標(biāo)記是第6個(gè)字節(jié)),如果不是0xFF,就說(shuō)明是壞塊。相對(duì)應(yīng)的是,所有正常的塊,好的塊,里面所有數(shù)據(jù)都是0xFF的。

(2)第二類叫做在使用過(guò)程中產(chǎn)生的,由于使用過(guò)程時(shí)間長(zhǎng)了,在擦塊除的時(shí)候,出錯(cuò)了,說(shuō)明此塊壞了,也要在程序運(yùn)行過(guò)程中,發(fā)現(xiàn),并且標(biāo)記成壞塊的。具體標(biāo)記的位置,和上面一樣。這類塊叫做worn-out bad block。

對(duì)于壞塊的管理,在Linux系統(tǒng)中,叫做壞塊管理(BBM,Bad Block Managment),對(duì)應(yīng)的會(huì)有一個(gè)表去記錄好塊,壞塊的信息,以及壞塊是出廠就有的,還是后來(lái)使用產(chǎn)生的,這個(gè)表叫做 壞塊表(BBT,Bad Block Table)在Linux內(nèi)核MTD架構(gòu)下的Nand Flash驅(qū)動(dòng),和Uboot中Nand Flash驅(qū)動(dòng)中,在加載完驅(qū)動(dòng)之后,如果你沒(méi)有加入?yún)?shù)主動(dòng)要求跳過(guò)壞塊掃描的話,那么都會(huì)去主動(dòng)掃描壞塊,建立必要的BBT的,以備后面壞塊管理所使用。

而關(guān)于好塊和壞塊,Nand Flash在出廠的時(shí)候,會(huì)做出保證:

1.關(guān)于好的,可以使用的塊的數(shù)目達(dá)到一定的數(shù)目,比如三星的K9G8G08U0M,整個(gè)flash一共有4096個(gè)塊,出廠的時(shí)候,保證好的塊至少大于3996個(gè),也就是意思是,你新買到這個(gè)型號(hào)的nand flash,最壞的可能,有3096-3996=100個(gè)壞塊。不過(guò),事實(shí)上,現(xiàn)在出廠時(shí)的壞塊,比較少,絕大多數(shù),都是使用時(shí)間長(zhǎng)了,在使用過(guò)程中出現(xiàn)的。

2.保證第一個(gè)塊是好的,并且一般相對(duì)來(lái)說(shuō)比較耐用。做此保證的主要原因是,很多Nand Flash壞塊管理方法中,就是將第一個(gè)塊,用來(lái)存儲(chǔ)上面提到的BBT,否則,都是出錯(cuò)幾率一樣的塊,那么也就不太好管理了,連放BBT的地方,都不好找了,^_^。

一般來(lái)說(shuō),不同型號(hào)的Nand Flash的數(shù)據(jù)手冊(cè)中,也會(huì)提到,自己的這個(gè)nand flash,最多允許多少個(gè)壞塊。就比如上面提到的,三星的K9G8G08U0M,最多有100個(gè)壞塊。

對(duì)于壞塊的標(biāo)記,本質(zhì)上,也只是對(duì)應(yīng)的flash上的某些字節(jié)的數(shù)據(jù)是非0xFF而已,所以,只要是數(shù)據(jù),就是可以讀取和寫入的。也就意味著,可以寫入其他值,也就把這個(gè)壞塊標(biāo)記信息破壞了。對(duì)于出廠時(shí)的壞塊,一般是不建議將標(biāo)記好的信息擦除掉的。

uboot中有個(gè)命令是“nand scrub”就可以將塊中所有的內(nèi)容都擦除了,包括壞塊標(biāo)記,不論是出廠時(shí)的,還是后來(lái)使用過(guò)程中出現(xiàn)而新標(biāo)記的。一般來(lái)說(shuō),不建議用這個(gè)。不過(guò),我倒是經(jīng)常用,其實(shí)也沒(méi)啥大礙,呵呵。

最好用“nand erase”只擦除好的塊,對(duì)于已經(jīng)標(biāo)記壞塊的塊,不擦除

【nand Flash中頁(yè)的訪問(wèn)順序】

在一個(gè)塊內(nèi),對(duì)每一個(gè)頁(yè)進(jìn)行編程的話,必須是順序的,而不能是隨機(jī)的。比如,一個(gè)塊中有128個(gè)頁(yè),那么你只能先對(duì)page0編程,再對(duì)page1編程,。。。。,而不能隨機(jī)的,比如先對(duì)page3,再page1,page2.,page0,page4,.。。。

【片選無(wú)關(guān)(CE don’t-care)技術(shù)】

很多Nand flash支持一個(gè)叫做CE don’t-care的技術(shù),字面意思就是,不關(guān)心是否片選,

那有人會(huì)問(wèn)了,如果不片選,那還能對(duì)其操作嗎?答案就是,這個(gè)技術(shù),主要用在當(dāng)時(shí)是不需要選中芯片卻還可以繼續(xù)操作的這些情況:在某些應(yīng)用,比如錄音,音頻播放等應(yīng)用,中,外部使用的微秒(us)級(jí)的時(shí)鐘周期,此處假設(shè)是比較少的2us,在進(jìn)行讀取一頁(yè)或者對(duì)頁(yè)編程時(shí),是對(duì)Nand Flash操作,這樣的串行(Serial Access)訪問(wèn)的周期都是20/30/50ns,都是納秒(ns)級(jí)的,此處假設(shè)是50ns,當(dāng)你已經(jīng)發(fā)了對(duì)應(yīng)的讀或?qū)懙拿钪?#xff0c;接下來(lái)只是需要Nand Flash內(nèi)部去自己操作,將數(shù)據(jù)讀取除了或?qū)懭脒M(jìn)去到內(nèi)部的數(shù)據(jù)寄存器中而已,此處,如果可以把片選取消,CE#是低電平有效,取消片選就是拉高電平,這樣會(huì)在下一個(gè)外部命令發(fā)送過(guò)來(lái)之前,即微秒量級(jí)的時(shí)間里面,即2us-50ns≈2us,這段時(shí)間的取消片選,可以降低很少的系統(tǒng)功耗,但是多次的操作,就可以在很大程度上降低整體的功耗了。

總結(jié)起來(lái)簡(jiǎn)單解釋就是:由于某些外部應(yīng)用的頻率比較低,而Nand Flash內(nèi)部操作速度比較快,所以具體讀寫操作的大部分時(shí)間里面,都是在等待外部命令的輸入,同時(shí)卻選中芯片,產(chǎn)生了多余的功耗,此“不關(guān)心片選”技術(shù),就是在Nand Flash的內(nèi)部的相對(duì)快速的操作(讀或?qū)?#xff09;完成之后,就取消片選,以節(jié)省系統(tǒng)功耗。待下次外部命令/數(shù)據(jù)/地址輸入來(lái)的時(shí)候,再選中芯片,即可正常繼續(xù)操作了。這樣,整體上,就可以大大降低系統(tǒng)功耗了。

注:Nand Flash的片選與否,功耗差別會(huì)有很大。如果數(shù)據(jù)沒(méi)有記錯(cuò)的話,我之前遇到我們系統(tǒng)里面的nand flash的片選,大概有5個(gè)mA的電流輸出呢,要知道,整個(gè)系統(tǒng)優(yōu)化之后的待機(jī)功耗,也才10個(gè)mA左右的。

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

Copy-Back功能,簡(jiǎn)單的說(shuō)就是,將一個(gè)頁(yè)的數(shù)據(jù),拷貝到另一個(gè)頁(yè)。

如果沒(méi)有Copy-Back功能,那么正常的做法就是,先要將那個(gè)頁(yè)的數(shù)據(jù)拷貝出來(lái)放到內(nèi)存的數(shù)據(jù)buffer中,讀出來(lái)之后,再用寫命令將這頁(yè)的數(shù)據(jù),寫到新的頁(yè)里面。

Copy-Back功能的好處在于,不需要用到外部的存儲(chǔ)空間,不需要讀出來(lái)放到外部的buffer里面,而是可以直接讀取數(shù)據(jù)到內(nèi)部的頁(yè)寄存器(page register)然后寫到新的頁(yè)里面去。而且,為了保證數(shù)據(jù)的正確,要硬件支持EDC(Error Detection Code)的,否則,在數(shù)據(jù)的拷貝過(guò)程中,可能會(huì)出現(xiàn)錯(cuò)誤,并且拷貝次數(shù)多了,可能會(huì)累積更多錯(cuò)誤。

而對(duì)于錯(cuò)誤檢測(cè)來(lái)說(shuō),硬件一般支持的是512字節(jié)數(shù)據(jù),對(duì)應(yīng)有16字節(jié)用來(lái)存放校驗(yàn)產(chǎn)生的ECC數(shù)值,而這512字節(jié)一般叫做一個(gè)扇區(qū)。對(duì)于2K+64字節(jié)大小的頁(yè)來(lái)說(shuō),按照512字節(jié)分,分別叫做A,B,C,D區(qū),而后面的64字節(jié)的oob區(qū)域,按照16字節(jié)一個(gè)區(qū),分別叫做E,F,G,H區(qū),對(duì)應(yīng)存放A,B,C,D數(shù)據(jù)區(qū)的ECC的值。

總結(jié):

512+16

2K +64 : A B C D - E F G H區(qū)

Copy-Back編程的主要作用在于,去掉了數(shù)據(jù)串行讀取出來(lái),再串行寫入進(jìn)去的時(shí)間,所以,這部分操作,是比較耗時(shí)的,所以此技術(shù)可以提高編程效率,提高系統(tǒng)整體性能。

【多片同時(shí)編程(Simultaneously Program Multi Plane)】

對(duì)于有些新出的Nand Flash,支持同時(shí)對(duì)多個(gè)片進(jìn)行編程,比如上面提到的三星的K9K8G08U0A,內(nèi)部包含4片(Plane),分別叫做Plane0,Plane1,Plane2,Plane3。.由于硬件上,對(duì)于每一個(gè)Plane,都有對(duì)應(yīng)的大小是2048+64=2112字節(jié)的頁(yè)寄存器(Page Register),使得同時(shí)支持多個(gè)Plane編程成為可能。K9K8G08U0A支持同時(shí)對(duì)2個(gè)Plane進(jìn)行編程。不過(guò)要注意的是,只能對(duì)Plane0和Plane1或者Plane2和Plane3,同時(shí)編程,而不支持Plane0和Plane2同時(shí)編程。

【交錯(cuò)頁(yè)編程(Interleave Page Program)】

多片同時(shí)編程,是針對(duì)一個(gè)chip里面的多個(gè)Plane來(lái)說(shuō)的,

而此處的交錯(cuò)頁(yè)編程,是指對(duì)多個(gè)chip而言的。

可以先對(duì)一個(gè)chip,假設(shè)叫chip1,里面的一頁(yè)進(jìn)行編程,然后此時(shí),chip1內(nèi)部就開始將數(shù)據(jù)一點(diǎn)點(diǎn)寫到頁(yè)里面,就出于忙的狀態(tài)了,而此時(shí)可以利用這個(gè)時(shí)間,對(duì)出于就緒狀態(tài)的chip2,也進(jìn)行頁(yè)編程,發(fā)送對(duì)應(yīng)的命令后,chip2內(nèi)部也就開始慢慢的寫數(shù)據(jù)到存儲(chǔ)單元里面去了,也出于忙的狀態(tài)了。此時(shí),再去檢查chip1,如果編程完成了,就可以開始下一頁(yè)的編程了,然后發(fā)完命令后,就讓其內(nèi)部慢慢的編程吧,再去檢查chip2,如果也是編程完了,也就可以進(jìn)行接下來(lái)的其他頁(yè)的編程了。如此,交互操作chip1和chip2,就可以有效地利用時(shí)間,使得整體編程效率提高近2倍,大大提高nand flash的編程/擦寫速度了。

【隨機(jī)輸出頁(yè)內(nèi)數(shù)據(jù)(Random Data Output In a Page)】

在介紹此特性之前,先要說(shuō)說(shuō),與Random Data Output In a Page相對(duì)應(yīng)的是,普通的,正常的,sequential data output in a page。

正常情況下,我們讀取數(shù)據(jù),都是先發(fā)讀命令,然后等待數(shù)據(jù)從存儲(chǔ)單元到內(nèi)部的頁(yè)數(shù)據(jù)寄存器中后,我們通過(guò)不斷地將RE#(Read Enale,低電平有效)置低,然后從我們開始傳入的列的起始地址,一點(diǎn)點(diǎn)讀出我們要的數(shù)據(jù),直到頁(yè)的末尾,當(dāng)然有可能還沒(méi)到頁(yè)地址的末尾,就不再讀了。所謂的順序(sequential)讀取也就是,根據(jù)你之前發(fā)送的列地址的起始地址開始,每讀一個(gè)字節(jié)的數(shù)據(jù)出來(lái),內(nèi)部的數(shù)據(jù)指針就加1,移到下個(gè)字節(jié)的地址,然后你再讀下一個(gè)字節(jié)數(shù)據(jù),就可以讀出來(lái)你要的數(shù)據(jù)了,直到讀取全部的數(shù)據(jù)出來(lái)為止。

而此處的隨機(jī)(random)讀取,就是在你正常的順序讀取的過(guò)程中,

先發(fā)一個(gè)隨機(jī)讀取的開始命令0x05命令,

再傳入你要將內(nèi)部那個(gè)數(shù)據(jù)指針定位到具體什么地址,也就是2個(gè)cycle的列地址,

然后再發(fā)隨機(jī)讀取結(jié)束命令0xE0,

然后,內(nèi)部那個(gè)數(shù)據(jù)地址指針,就會(huì)移動(dòng)到你所制定的位置了,

你接下來(lái)再讀取的數(shù)據(jù),就是從那個(gè)制定地址開始的數(shù)據(jù)了。

而nand flash數(shù)據(jù)手冊(cè)里面也說(shuō)了,這樣的隨機(jī)讀取,你可以多次操作,沒(méi)限制的。

請(qǐng)注意,上面你所傳入的地址,都是列地址,也就是頁(yè)內(nèi)地址,也就是說(shuō),對(duì)于頁(yè)大小為2K的nand flash來(lái)說(shuō),所傳入的地址,應(yīng)該是小于2048+64=2112的。

不過(guò),實(shí)際在nand flash的使用中,好像這種用法很少的。絕大多數(shù),都是順序讀取數(shù)據(jù)。

【頁(yè)編程(寫操作)】

Nand flash的寫操作叫做編程Program,編程,一般情況下,是以頁(yè)為單位的。

有的Nand Flash,比如K9K8G08U0A,支持部分頁(yè)編程,但是有一些限制:在同一個(gè)頁(yè)內(nèi)的,連續(xù)的部分頁(yè)的編程,不能超過(guò)4次。一般情況下,很少使用到部分頁(yè)編程,都是以頁(yè)為單位進(jìn)行編程操作的。

一個(gè)操作,用兩個(gè)命令去實(shí)現(xiàn),看起來(lái)是多余,效率不高,但是實(shí)際上,有其特殊考慮,

至少對(duì)于塊擦除來(lái)說(shuō),開始的命令0x60是擦除設(shè)置命令(erase setup comman),然后傳入要擦除的塊地址,然后再傳入擦除確認(rèn)命令(erase confirm command)0xD0,以開始擦除的操作。

這種,分兩步:開始設(shè)置,最后確認(rèn)的命令方式,是為了避免由于外部由于無(wú)意的/未預(yù)料而產(chǎn)生的噪音,比如,,此時(shí),即使被nand flash誤認(rèn)為是擦除操作,但是沒(méi)有之后的確認(rèn)操作0xD0,nand flash就不會(huì)去擦除數(shù)據(jù),這樣使得數(shù)據(jù)更安全,不會(huì)由于噪音而誤操作。

分類: Flash驅(qū)動(dòng)

【讀(read)操作過(guò)程詳解】

以最簡(jiǎn)單的read操作為例,解釋如何理解時(shí)序圖,以及將時(shí)序圖中的要求,轉(zhuǎn)化為代碼。

解釋時(shí)序圖之前,讓我們先要搞清楚,我們要做的事情:那就是,要從nand flash的某個(gè)頁(yè)里面,讀取我們要的數(shù)據(jù)。

要實(shí)現(xiàn)此功能,會(huì)涉及到幾部分的知識(shí),至少很容易想到的就是:需要用到哪些命令,怎么發(fā)這些命令,怎么計(jì)算所需要的地址,怎么讀取我們要的數(shù)據(jù)等等。

下面,就一步步的解釋,需要做什么,以及如何去做:

1.需要使用何種命令

首先,是要了解,對(duì)于讀取數(shù)據(jù),要用什么命令。

下面是datasheet中的命令集合:


圖5.Nand Flash K9K8G08U0A的命令集合

很容易看出,我們要讀取數(shù)據(jù),要用到Read命令,該命令需要2個(gè)周期,第一個(gè)周期發(fā)0x00,第二個(gè)周期發(fā)0x30。

2.發(fā)送命令前的準(zhǔn)備工作以及時(shí)序圖各個(gè)信號(hào)的具體含義

知道了用何命令后,再去了解如何發(fā)送這些命令。

[小常識(shí)]

在開始解釋前,多羅嗦一下”使能”這個(gè)詞,以便有些讀者和我以前一樣,在聽這類雖然對(duì)于某些專業(yè)人士說(shuō)是屬于最基本的詞匯了,但是對(duì)于初次接觸,或者接觸不多的人來(lái)說(shuō),聽多了,容易被搞得一頭霧水:使能(Enable),是指使其(某個(gè)信號(hào))有效,使其生效的意思,“使其”“能夠”怎么怎么樣。。。。比如,上面圖中的CLE線號(hào),是高電平有效,如果此時(shí)將其設(shè)為高電平,我們就叫做,將CLE使能,也就是使其生效的意思。


圖6.Nand Flash數(shù)據(jù)讀取操作的時(shí)序圖

注:此圖來(lái)自三星的型號(hào)K9K8G08U0A的nand flash的數(shù)據(jù)手冊(cè)(datasheet)。

我們來(lái)一起看看,我在圖6中的特意標(biāo)注的①邊上的黃色豎線。

黃色豎線所處的時(shí)刻,是在發(fā)送讀操作的第一個(gè)周期的命令0x00之前的那一刻。

讓我們看看,在那一刻,其所穿過(guò)好幾行都對(duì)應(yīng)什么值,以及進(jìn)一步理解,為何要那個(gè)值。

(1)黃色豎線穿過(guò)的第一行,是CLE。還記得前面介紹命令所存使能(CLE)那個(gè)引腳吧?CLE,將CLE置1,就說(shuō)明你將要通過(guò)I/O復(fù)用端口發(fā)送進(jìn)入Nand Flash的,是命令,而不是地址或者其他類型的數(shù)據(jù)。只有這樣將CLE置1,使其有效,才能去通知了內(nèi)部硬件邏輯,你接下來(lái)將收到的是命令,內(nèi)部硬件邏輯,才會(huì)將受到的命令,放到命令寄存器中,才能實(shí)現(xiàn)后面正確的操作,否則,不去將CLE置1使其有效,硬件會(huì)無(wú)所適從,不知道你傳入的到底是數(shù)據(jù)還是命令了。

(2)而第二行,是CE#,那一刻的值是0。這個(gè)道理很簡(jiǎn)單,你既然要向Nand Flash發(fā)命令,那么先要選中它,所以,要保證CE#為低電平,使其有效,也就是片選有效。

(3)第三行是WE#,意思是寫使能。因?yàn)榻酉聛?lái)是往nand Flash里面寫命令,所以,要使得WE#有效,所以設(shè)為低電平。

(4)第四行,是ALE是低電平,而ALE是高電平有效,此時(shí)意思就是使其無(wú)效。而對(duì)應(yīng)地,前面介紹的,使CLE有效,因?yàn)閷⒁獢?shù)據(jù)的是命令,而不是地址。如果在其他某些場(chǎng)合,比如接下來(lái)的要輸入地址的時(shí)候,就要使其有效,而使CLE無(wú)效了。

(5)第五行,RE#,此時(shí)是高電平,無(wú)效。可以看到,知道后面低6階段,才變成低電平,才有效,因?yàn)槟菚r(shí)候,要發(fā)生讀取命令,去讀取數(shù)據(jù)。

(6)第六行,就是我們重點(diǎn)要介紹的,復(fù)用的輸入輸出I/O端口了,此刻,還沒(méi)有輸入數(shù)據(jù),接下來(lái),在不同的階段,會(huì)輸入或輸出不同的數(shù)據(jù)/地址。

(7)第七行,R/B#,高電平,表示R(Ready)/就緒,因?yàn)榈搅撕竺娴牡?階段,硬件內(nèi)部,在第四階段,接受了外界的讀取命令后,把該頁(yè)的數(shù)據(jù)一點(diǎn)點(diǎn)送到頁(yè)寄存器中,這段時(shí)間,屬于系統(tǒng)在忙著干活,屬于忙的階段,所以,R/B#才變成低,表示Busy忙的狀態(tài)的。

介紹了時(shí)刻①的各個(gè)信號(hào)的值,以及為何是這個(gè)值之后,相信,后面的各個(gè)時(shí)刻,對(duì)應(yīng)的不同信號(hào)的各個(gè)值,大家就會(huì)自己慢慢分析了,也就容易理解具體的操作順序和原理了。

3.如何計(jì)算出,我們要傳入的地址

在介紹具體讀取數(shù)據(jù)的詳細(xì)流程之前,還要做一件事,那就是,先要搞懂我們要訪問(wèn)的地址,以及這些地址,如何分解后,一點(diǎn)點(diǎn)傳入進(jìn)去,使得硬件能識(shí)別才行。

此處還是以K9K8G08U0A為例,此nand flash,一共有8192個(gè)塊,每個(gè)塊內(nèi)有64頁(yè),每個(gè)頁(yè)是2K+64 Bytes,假設(shè),我們要訪問(wèn)其中的第7000個(gè)塊中的第25頁(yè)中的1208字節(jié)處的地址,此時(shí),我們就要先把具體的地址算出來(lái):

物理地址=塊大小×塊號(hào)+頁(yè)大小×頁(yè)號(hào)+頁(yè)內(nèi)地址=7000×128K+64×2K+1208=0x36B204B8,接下來(lái),我們就看看,怎么才能把這個(gè)實(shí)際的物理地址,轉(zhuǎn)化為nand Flash所要求的格式。

在解釋地址組成之前,先要來(lái)看看其datasheet中關(guān)于地址周期的介紹:


圖7 Nand Flash的地址周期組成

結(jié)合圖7和圖5中的2,3階段,我們可以看出,此nand flash地址周期共有5個(gè),2個(gè)列(Column)周期,3個(gè)行(Row)周期。

而對(duì)于對(duì)應(yīng)地,我們可以看出,實(shí)際上,

列地址A0~A10,就是頁(yè)內(nèi)地址,地址范圍是從0到2047,而對(duì)出的A11,理論上可以表示2048~4095,但是實(shí)際上,我們最多也只用到了2048~2112,用于表示頁(yè)內(nèi)的oob區(qū)域,其大小是64字節(jié)。

A12~A30,稱作頁(yè)號(hào),頁(yè)的號(hào)碼,可以定位到具體是哪一個(gè)頁(yè)。

而其中,A18~A30,表示對(duì)應(yīng)的塊號(hào),即屬于哪個(gè)塊。

// 可見:地址的傳輸順序是是 頁(yè)內(nèi)地址,頁(yè)號(hào),塊號(hào)。 從小到大。

簡(jiǎn)單解釋完了地址組成,那么就很容易分析上面例子中的地址了:

0x36B204B8 = 0011 0110 1011 0010 0000 0100 1011 1000,分別分配到5個(gè)地址周期就是:

1st 周期,A7~A0 :1011 1000 = 0x B8

2nd周期,A11~A8 :0000 0100 = 0x04

3rd周期,A19~A12 :0010 0000 = 0x20

4th周期,A27~A20 :0110 1011 = 0x6B

5th周期,A30~A28 :0000 0011 = 0x03

注意,與圖7中對(duì)應(yīng)的,*L,意思是低電平,由于未用到那些位,datasheet中強(qiáng)制要求設(shè)為0,所以,才有上面的2nd周期中的高4位是0000.其他的A30之后的位也是類似原理,都是0。

因此,接下來(lái)要介紹的,我們要訪問(wèn)第7000個(gè)塊中的第25頁(yè)中的1208字節(jié)處的話,所要傳入的地址就是分5個(gè)周期,分別傳入兩個(gè)列地址的:0xB8,0x04,然后再傳3個(gè)行地址的:0x20,0x6B,0x03,這樣硬件才能識(shí)別。

4.讀操作過(guò)程的解釋

準(zhǔn)備工作終于完了,下面就可以開始解釋說(shuō)明,對(duì)于讀操作的,上面圖中標(biāo)出來(lái)的,1-6個(gè)階段,具體是什么含義。

(1) 操作準(zhǔn)備階段:此處是讀(Read)操作,所以,先發(fā)一個(gè)圖5中讀命令的第一個(gè)階段的0x00,表示,讓硬件先準(zhǔn)備一下,接下來(lái)的操作是讀。

(2) 發(fā)送兩個(gè)周期的列地址。也就是頁(yè)內(nèi)地址,表示,我要從一個(gè)頁(yè)的什么位置開始讀取數(shù)據(jù)。

(3) 接下來(lái)再傳入三個(gè)行地址。對(duì)應(yīng)的也就是頁(yè)號(hào)。

(4) 然后再發(fā)一個(gè)讀操作的第二個(gè)周期的命令0x30。接下來(lái),就是硬件內(nèi)部自己的事情了。

(5) Nand Flash內(nèi)部硬件邏輯,負(fù)責(zé)去按照你的要求,根據(jù)傳入的地址,找到哪個(gè)塊中的哪個(gè)頁(yè),然后把整個(gè)這一頁(yè)的數(shù)據(jù),都一點(diǎn)點(diǎn)搬運(yùn)到頁(yè)緩存中去。而在此期間,你所能做的事,也就只需要去讀取狀態(tài)寄存器,看看對(duì)應(yīng)的位的值,也就是R/B#那一位,是1還是0,0的話,就表示,系統(tǒng)是busy,仍在”忙“(著讀取數(shù)據(jù)),如果是1,就說(shuō)系統(tǒng)活干完了,忙清了,已經(jīng)把整個(gè)頁(yè)的數(shù)據(jù)都搬運(yùn)到頁(yè)緩存里去了,你可以接下來(lái)讀取你要的數(shù)據(jù)了。

對(duì)于這里。估計(jì)有人會(huì)問(wèn)了,這一個(gè)頁(yè)一共2048+64字節(jié),如果我傳入的頁(yè)內(nèi)地址,就像上面給的1028一類的值,只是想讀取1028到2011這部分?jǐn)?shù)據(jù),而不是頁(yè)開始的0地址整個(gè)頁(yè)的數(shù)據(jù),那么內(nèi)部硬件卻讀取整個(gè)頁(yè)的數(shù)據(jù)出來(lái),豈不是很浪費(fèi)嗎?答案是,的確很浪費(fèi),效率看起來(lái)不高,但是實(shí)際就是這么做的,而且本身讀取整個(gè)頁(yè)的數(shù)據(jù),相對(duì)時(shí)間并不長(zhǎng),而且讀出來(lái)之后,內(nèi)部數(shù)據(jù)指針會(huì)定位到你剛才所制定的1208的那個(gè)位置。

(6) 接下來(lái),就是你“竊取“系統(tǒng)忙了半天之后的勞動(dòng)成果的時(shí)候了,呵呵。通過(guò)先去Nand Flash的控制器中的數(shù)據(jù)寄存器中寫入你要讀取多少個(gè)字節(jié)(byte)/字(word),然后就可以去Nand Flash的控制器的FIFO中,一點(diǎn)點(diǎn)讀取你要的數(shù)據(jù)了。

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

對(duì)于其他操作,可以根據(jù)我上面的分析,一點(diǎn)點(diǎn)自己去看datasheet,根據(jù)里面的時(shí)序圖去分析具體的操作過(guò)程,然后對(duì)照代碼,會(huì)更加清楚具體是如何實(shí)現(xiàn)的。

【Flash的類型】

Flash的類型主要分兩種,nand flash和nor flash。

除了網(wǎng)上最流行的這個(gè)解釋之外:

NAND和NOR的比較

再多說(shuō)幾句:

1.nor的成本相對(duì)高,具體讀寫數(shù)據(jù)時(shí)候,不容易出錯(cuò)。總體上,比較適合應(yīng)用于存儲(chǔ)少量的代碼。

2.Nand flash相對(duì)成本低。使用中數(shù)據(jù)讀寫容易出錯(cuò),所以一般都需要有對(duì)應(yīng)的軟件或者硬件的數(shù)據(jù)校驗(yàn)算法,統(tǒng)稱為ECC。由于相對(duì)來(lái)說(shuō),容量大,價(jià)格便宜,因此適合用來(lái)存儲(chǔ)大量的數(shù)據(jù)。其在嵌入式系統(tǒng)中的作用,相當(dāng)于PC上的硬盤,用于存儲(chǔ)大量數(shù)據(jù)。

所以,一個(gè)常見的應(yīng)用組合就是,用小容量的Nor Flash存儲(chǔ)啟動(dòng)代碼,比如uboot,系統(tǒng)啟動(dòng)后,初始化對(duì)應(yīng)的硬件,包括SDRAM等,然后將Nand Flash上的Linux 內(nèi)核讀取到內(nèi)存中,做好該做的事情后,就跳轉(zhuǎn)到SDRAM中去執(zhí)行內(nèi)核了,然后內(nèi)核解壓(如果是壓縮內(nèi)核的話,否則就直接運(yùn)行了)后,開始運(yùn)行,在Linux內(nèi)核啟動(dòng)最后,去Nand Flash上,掛載根文件,比如jffs2,yaffs2等,掛載完成,運(yùn)行初始化腳本,啟動(dòng)consle交互,才運(yùn)行你通過(guò)console和內(nèi)核交互。至此完成整個(gè)系統(tǒng)啟動(dòng)過(guò)程

而Nor Flash存放的是Uboot,Nand Flash存放的是Linux的內(nèi)核鏡像和根文件系統(tǒng),以及余下的空間分成一個(gè)數(shù)據(jù)區(qū)。

Nor flash,有類似于dram之類的地址總線,因此可以直接和CPU相連,CPU可以直接通過(guò)地址總線對(duì)nor flash進(jìn)行訪問(wèn),而nand flash沒(méi)有這類的總線,只有IO接口,只能通過(guò)IO接口發(fā)送命令和地址,對(duì)nand flash內(nèi)部數(shù)據(jù)進(jìn)行訪問(wèn)。相比之下,nor flash就像是并行訪問(wèn),nand flash就是串行訪問(wèn),所以相對(duì)來(lái)說(shuō),前者的速度更快些。

但是由于物理制程/制造方面的原因,導(dǎo)致nor 和nand在一些具體操作方面的特性不同:



表3 Nand Flash 和 Nor Flash的區(qū)別

1. 理論上是可以的,而且也是有人驗(yàn)證過(guò)可以的,只不過(guò)由于nand flash的物理特性,不能完全保證所讀取的數(shù)據(jù)/代碼是正確的,實(shí)際上,很少這么用而已。因?yàn)?#xff0c;如果真是要用到nand flash做XIP,那么除了讀出速度慢之外,還要保證有數(shù)據(jù)的校驗(yàn),以保證讀出來(lái)的,將要執(zhí)行的代碼/數(shù)據(jù),是正確的。否則,系統(tǒng)很容易就跑飛了。。。

2. 芯片內(nèi)執(zhí)行(XIP, eXecute In Place):

http://hi.baidu.com/serial_story/blog/item/adb20a2a3f8ffe3c5243c1df.html

【Nand Flash的種類】

具體再分,又可以分為

1)Bare NAND chips:裸片,單獨(dú)的nand 芯片

2)SmartMediaCards: =裸片+一層薄塑料,常用于數(shù)碼相機(jī)和MP3播放器中。之所以稱smart,是由于其軟件smart,而不是硬件本身有啥smart之處。^_^

3)DiskOnChip:裸片+glue logic,glue logic=硬件ECC產(chǎn)生器+用于靜態(tài)的nand 芯片控制的寄存器+直接訪問(wèn)一小片地址窗口,那塊地址中包含了引導(dǎo)代碼的stub樁,其可以從nand flash中拷貝真正的引導(dǎo)代碼。

【spare area/oob】

Nand由于最初硬件設(shè)計(jì)時(shí)候考慮到,額外的錯(cuò)誤校驗(yàn)等需要空間,專門對(duì)應(yīng)每個(gè)頁(yè),額外設(shè)計(jì)了叫做spare area空區(qū)域,在其他地方,比如jffs2文件系統(tǒng)中,也叫做oob(out of band)數(shù)據(jù)。

其具體用途,總結(jié)起來(lái)有:

1. 標(biāo)記是否是壞快

2. 存儲(chǔ)ECC數(shù)據(jù)

3. 存儲(chǔ)一些和文件系統(tǒng)相關(guān)的數(shù)據(jù),如jffs2就會(huì)用到這些空間存儲(chǔ)一些特定信息,yaffs2文件系統(tǒng),會(huì)在oob中,存放很多和自己文件系統(tǒng)相關(guān)的信息。

【內(nèi)存技術(shù)設(shè)備,MTD(Memory Technology Device)】

MTD,是Linux的存儲(chǔ)設(shè)備中的一個(gè)子系統(tǒng)。其設(shè)計(jì)此系統(tǒng)的目的是,對(duì)于內(nèi)存類的設(shè)備,提供一個(gè)抽象層,一個(gè)接口,使得對(duì)于硬件驅(qū)動(dòng)設(shè)計(jì)者來(lái)說(shuō),可以盡量少的去關(guān)心存儲(chǔ)格式,比如FTL,FFS2等,而只需要去提供最簡(jiǎn)單的底層硬件設(shè)備的讀/寫/擦除函數(shù)就可以了。而對(duì)于數(shù)據(jù)對(duì)于上層使用者來(lái)說(shuō)是如何表示的,硬件驅(qū)動(dòng)設(shè)計(jì)者可以不關(guān)心,而MTD存儲(chǔ)設(shè)備子系統(tǒng)都幫你做好了。

對(duì)于MTD字系統(tǒng)的好處,簡(jiǎn)單解釋就是,他幫助你實(shí)現(xiàn)了,很多對(duì)于以前或者其他系統(tǒng)來(lái)說(shuō),本來(lái)也是你驅(qū)動(dòng)設(shè)計(jì)者要去實(shí)現(xiàn)的很多功能。換句話說(shuō),有了MTD,使得你設(shè)計(jì)Nand Flash的驅(qū)動(dòng),所要做的事情,要少很多很多,因?yàn)榇蟛糠止ぷ?#xff0c;都由MTD幫你做好了。

當(dāng)然,這個(gè)好處的一個(gè)“副作用”就是,使得我們不了解的人去理解整個(gè)Linux驅(qū)動(dòng)架構(gòu),以及MTD,變得更加復(fù)雜。但是,總的說(shuō),覺得是利遠(yuǎn)遠(yuǎn)大于弊,否則,就不僅需要你理解,而且還是做更多的工作,實(shí)現(xiàn)更多的功能了。


此外,還有一個(gè)重要的原因,那就是,前面提到的nand flash和普通硬盤等設(shè)備的特殊性:

有限的通過(guò)出復(fù)用來(lái)實(shí)現(xiàn)輸入輸出命令和地址/數(shù)據(jù)等的IO接口,最小單位是頁(yè)而不是常見的bit,寫前需擦除等,導(dǎo)致了這類設(shè)備,不能像平常對(duì)待硬盤等操作一樣去操作,只能采取一些特殊方法,這就誕生了MTD設(shè)備的統(tǒng)一抽象層。

MTD,將nand flash,nor flash和其他類型的flash等設(shè)備,統(tǒng)一抽象成MTD設(shè)備來(lái)管理,根據(jù)這些設(shè)備的特點(diǎn),上層實(shí)現(xiàn)了常見的操作函數(shù)封裝,底層具體的內(nèi)部實(shí)現(xiàn),就需要驅(qū)動(dòng)設(shè)計(jì)者自己來(lái)實(shí)現(xiàn)了。具體的內(nèi)部硬件設(shè)備的讀/寫/擦除函數(shù),那就是你必須實(shí)現(xiàn)的了。

表4.MTD設(shè)備和硬盤設(shè)備之間的區(qū)別


==========
多說(shuō)一句,關(guān)于MTD更多的內(nèi)容,感興趣的,去附錄中的MTD的主頁(yè)去看。

關(guān)于mtd設(shè)備驅(qū)動(dòng),感興趣的可以去參考

MTD原始設(shè)備與FLASH硬件驅(qū)動(dòng)的對(duì)話

MTD原始設(shè)備與FLASH硬件驅(qū)動(dòng)的對(duì)話-續(xù)

那里,算是比較詳細(xì)地介紹了整個(gè)流程,方便大家理解整個(gè)mtd框架和nand flash驅(qū)動(dòng)。

【Nand flash驅(qū)動(dòng)工作原理】

在介紹具體如何寫Nand Flash驅(qū)動(dòng)之前,我們先要了解,大概的,整個(gè)系統(tǒng),和Nand Flash相關(guān)的部分的驅(qū)動(dòng)工作流程,這樣,對(duì)于后面的驅(qū)動(dòng)實(shí)現(xiàn),才能更加清楚機(jī)制,才更容易實(shí)現(xiàn),否則就是,即使寫完了代碼,也還是沒(méi)搞懂系統(tǒng)是如何工作的了。

讓我們以最常見的,Linux內(nèi)核中已經(jīng)有的三星的Nand Flash驅(qū)動(dòng),來(lái)解釋Nand Flash驅(qū)動(dòng)具體流程和原理。

此處是參考2.6.29版本的Linux源碼中的\drivers\mtd\nand\s3c2410.c,以2410為例。

1. 在nand flash驅(qū)動(dòng)加載后,第一步,調(diào)用對(duì)應(yīng)的init函數(shù) ---- s3c2410_nand_init: 去將nand flash驅(qū)動(dòng)注冊(cè)到Linux驅(qū)動(dòng)框架中。

2. 驅(qū)動(dòng)本身真正的開始,是從probe函數(shù): s3c2410_nand_probe->s3c24xx_nand_probe,
在probe過(guò)程中:
clk_enable //打開nand flash控制器的clock時(shí)鐘,
request_mem_region //去申請(qǐng)驅(qū)動(dòng)所需要的一些內(nèi)存等相關(guān)資源。
s3c2410_nand_inithw //去初始化硬件相關(guān)的部分,主要是關(guān)于時(shí)鐘頻率的計(jì)算,以及啟用nand flash控制器,使得硬件初始化好了,后面才能正常工作。

3. 需要多解釋一下的,是這部分代碼:

for (setno = 0; setno < nr_sets; setno++, nmtd++) {
pr_debug("initialising set %d (%p, info %p)\n", setno, nmtd, info);

/*調(diào)用init chip去掛載你的nand驅(qū)動(dòng)的底層函數(shù)到"nand flash的結(jié)構(gòu)體"中,以及設(shè)置對(duì)應(yīng)的"ecc mode",掛載ecc相關(guān)的函數(shù) */
s3c2410_nand_init_chip(info, nmtd, sets);

/* scan_ident,掃描nand 設(shè)備,設(shè)置nand flash的默認(rèn)函數(shù),獲得物理設(shè)備的具體型號(hào)以及對(duì)應(yīng)各個(gè)特性參數(shù),這部分算出來(lái)的一些值,對(duì)于nand flash來(lái)說(shuō),是最主要的參數(shù),比如nand flash的芯片的大小,塊大小,頁(yè)大小等。 */
nmtd->scan_res = nand_scan_ident(&nmtd->mtd, (sets) ? sets->nr_chips : 1);

if (nmtd->scan_res == 0) {
s3c2410_nand_update_chip(info, nmtd);

/*掃描的后一階段,經(jīng)過(guò)前面的scan_ident,我們已經(jīng)獲得對(duì)應(yīng)nand flash的硬件的各個(gè)參數(shù)
*然后就可以在scan tail中,根據(jù)這些參數(shù),去設(shè)置其他一些重要參數(shù),尤其是ecc的layout,即ecc是如何在oob中擺放的,
*最后,再去進(jìn)行一些初始化操作,主要是根據(jù)你的驅(qū)動(dòng),如果沒(méi)有實(shí)現(xiàn)一些函數(shù)的話,那么就用系統(tǒng)默認(rèn)的。 */
nand_scan_tail(&nmtd->mtd);

/*add partion,根據(jù)你的nand flash的分區(qū)設(shè)置,去分區(qū) */
s3c2410_nand_add_partition(info, nmtd, sets);
}
if (sets != NULL)
sets++;
}

4. 等所有的參數(shù)都計(jì)算好了,函數(shù)都掛載完畢,系統(tǒng)就可以正常工作了。

上層訪問(wèn)你的nand falsh中的數(shù)據(jù)的時(shí)候,通過(guò)MTD層,一層層調(diào)用,最后調(diào)用到你所實(shí)現(xiàn)的那些底層訪問(wèn)硬件數(shù)據(jù)/緩存的函數(shù)中。


【Linux下nand flash驅(qū)動(dòng)編寫步驟簡(jiǎn)介】

關(guān)于上面提到的,在nand_scan_tail的時(shí)候,系統(tǒng)會(huì)根據(jù)你的驅(qū)動(dòng),如果沒(méi)有實(shí)現(xiàn)一些函數(shù)的話,那么就用系統(tǒng)默認(rèn)的。如果實(shí)現(xiàn)了自己的函數(shù),就用你的。
"那么到底我要實(shí)現(xiàn)哪些函數(shù)呢,而又有哪些是可以不實(shí)現(xiàn),用系統(tǒng)默認(rèn)的就可以了呢。"
此問(wèn)題的,就是我們下面要介紹的,也就是,你要實(shí)現(xiàn)的,你的驅(qū)動(dòng)最少要做哪些工作,才能使整個(gè)nand flash工作起來(lái)。

1. 對(duì)于驅(qū)動(dòng)框架部分

其實(shí),要了解,關(guān)于驅(qū)動(dòng)框架部分,你所要做的事情的話,只要看看三星的整個(gè)nand flash驅(qū)動(dòng)中的這個(gè)結(jié)構(gòu)體,就差不多了:

static struct platform_driver s3c2410_nand_driver = {
.probe = s3c2410_nand_probe,
.remove = s3c2410_nand_remove,
.suspend = s3c24xx_nand_suspend,
.resume = s3c24xx_nand_resume,
.driver = {
.name = "s3c2410-nand",
.owner = THIS_MODULE,
},
};

對(duì)于上面這個(gè)結(jié)構(gòu)體,沒(méi)多少要解釋的。從名字,就能看出來(lái):
(1)probe就是系統(tǒng)“探測(cè)”,就是前面解釋的整個(gè)過(guò)程,這個(gè)過(guò)程中的多數(shù)步驟,都是和你自己的nand flash相關(guān)的,尤其是那些硬件初始化部分,是你必須要自己實(shí)現(xiàn)的。
(2)remove,就是和probe對(duì)應(yīng)的,“反初始化”相關(guān)的動(dòng)作。主要是釋放系統(tǒng)相關(guān)資源和關(guān)閉硬件的時(shí)鐘等常見操作了。
(3)suspend和resume,對(duì)于很多沒(méi)用到電源管理的情況下,至少對(duì)于我們剛開始寫基本的驅(qū)動(dòng)的時(shí)候,可以不用關(guān)心,放個(gè)空函數(shù)即可。


2. 對(duì)于nand flash底層操作實(shí)現(xiàn)部分

而對(duì)于底層硬件操作的有些函數(shù),總體上說(shuō),都可以在上面提到的s3c2410_nand_init_chip中找到:

static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info,
struct s3c2410_nand_mtd *nmtd, //主要是完善該結(jié)構(gòu)體
struct s3c2410_nand_set *set)
{

struct nand_chip *chip = &nmtd->chip;
void __iomem *regs = info->regs;

chip->write_buf = s3c2410_nand_write_buf;
chip->read_buf = s3c2410_nand_read_buf;
chip->select_chip = s3c2410_nand_select_chip;
chip->chip_delay = 50;
chip->priv = nmtd;
chip->options = 0;
chip->controller = &info->controller;

switch (info->cpu_type) {
case TYPE_S3C2410:

/* nand flash控制器中,一般都有對(duì)應(yīng)的數(shù)據(jù)寄存器,用于給你往里面寫數(shù)據(jù),表示將要讀取或?qū)懭攵嗌賯€(gè)字節(jié)(byte,u8)/字(word,u32) ,所以,此處,你要給出地址,以便后面的操作所使用 */

chip->IO_ADDR_W = regs + S3C2410_NFDATA;
info->sel_reg = regs + S3C2410_NFCONF;
info->sel_bit = S3C2410_NFCONF_nFCE;
chip->cmd_ctrl = s3c2410_nand_hwcontrol;
chip->dev_ready = s3c2410_nand_devready;

break;

。。。。。。

}

chip->IO_ADDR_R = chip->IO_ADDR_W;

nmtd->info = info;
nmtd->mtd.priv = chip;
nmtd->mtd.owner = THIS_MODULE;
nmtd->set = set;

if (hardware_ecc) {
chip->ecc.calculate = s3c2410_nand_calculate_ecc;
chip->ecc.correct = s3c2410_nand_correct_data;

/* 此處,多數(shù)情況下,你所用的Nand Flash的控制器,都是支持硬件ECC的,所以,此處設(shè)置硬件ECC(HW_ECC) ,也是充分利用硬件的特性,
* 而如果此處不用硬件去做ECC話,那么下面也會(huì)去設(shè)置成NAND_ECC_SOFT,系統(tǒng)會(huì)用默認(rèn)的軟件去做ECC校驗(yàn),相比之下,比硬件ECC的效率就低很多,而你的nand flash的讀寫,也會(huì)相應(yīng)地要慢不少
*/

chip->ecc.mode = NAND_ECC_HW; //設(shè)置成了硬件方式校驗(yàn)ecc

switch (info->cpu_type) {

case TYPE_S3C2410:

chip->ecc.hwctl = s3c2410_nand_enable_hwecc;
chip->ecc.calculate = s3c2410_nand_calculate_ecc;

break;
。。。。。
}

} else {
chip->ecc.mode = NAND_ECC_SOFT; //也就是說(shuō),怎么搞也得校驗(yàn)了
}

if (set->ecc_layout != NULL)
chip->ecc.layout = set->ecc_layout;

if (set->disable_ecc)
chip->ecc.mode = NAND_ECC_NONE;
}

而我們要實(shí)現(xiàn)的底層函數(shù),也就是上面藍(lán)色標(biāo)出來(lái)的一些函數(shù)而已:

(1)s3c2410_nand_write_bufs3c2410_nand_read_buf:這是兩個(gè)最基本的操作函數(shù),其功能,就是往你的nand flash的控制器中的FIFO讀寫數(shù)據(jù)。一般情況下,是MTD上層的操作,比如要讀取一頁(yè)的數(shù)據(jù),那么在發(fā)送完相關(guān)的讀命令和等待時(shí)間之后,就會(huì)調(diào)用到你底層的read_buf,去nand Flash的FIFO中,一點(diǎn)點(diǎn)把我們要的數(shù)據(jù),讀取出來(lái),放到我們制定的內(nèi)存的緩存中去。寫操作也是類似,將我們內(nèi)存中的數(shù)據(jù),寫到Nand Flash的FIFO中去。
(2)s3c2410_nand_select_chip : 實(shí)現(xiàn)Nand Flash的片選。
(3)s3c2410_nand_hwcontrol: 給底層發(fā)送命令或地址,或者設(shè)置具體操作的模式,都是通過(guò)此函數(shù)。
(4)s3c2410_nand_devready: Nand Flash的一些操作,比如讀一頁(yè)數(shù)據(jù),寫入(編程)一頁(yè)數(shù)據(jù),擦除一個(gè)塊,都是需要一定時(shí)間的,在命令發(fā)送完成后,就是硬件開始忙著工作的時(shí)候了,而硬件什么時(shí)候完成這些操作,什么時(shí)候不忙了,變就緒了,就是通過(guò)這個(gè)函數(shù)去檢查狀態(tài)的。一般具體實(shí)現(xiàn)都是去讀硬件的一個(gè)狀態(tài)寄存器,其中某一位是否是1,對(duì)應(yīng)著是出于“就緒/不忙”還是“忙”的狀態(tài)。這個(gè)寄存器,也就是我們前面分析時(shí)序圖中的R/B#。
(5)s3c2410_nand_calculate_ecc:如果是上面提到的硬件ECC的話,就不用我們用軟件去實(shí)現(xiàn)校驗(yàn)算法了,而是直接去讀取硬件產(chǎn)生的ECC數(shù)值就可以了。
(6)s3c2410_nand_correct_data: 當(dāng)實(shí)際操作過(guò)程中,讀取出來(lái)的數(shù)據(jù)所對(duì)應(yīng)的硬件或軟件計(jì)算出來(lái)的ECC,和從oob中讀出來(lái)的ECC不一樣的時(shí)候,就是說(shuō)明數(shù)據(jù)有誤了,就需要調(diào)用此函數(shù)去糾正錯(cuò)誤。對(duì)于現(xiàn)在SLC常見的ECC算法來(lái)說(shuō),可以發(fā)現(xiàn)2位,糾正1位。如果錯(cuò)誤大于1位,那么就無(wú)法糾正回來(lái)了。一般情況下,出錯(cuò)超過(guò)1位的,好像幾率不大。至少我看到的不是很大。更復(fù)雜的情況和更加注重?cái)?shù)據(jù)安全的情況下,一般是需要另外實(shí)現(xiàn)更高效和檢錯(cuò)和糾錯(cuò)能力更強(qiáng)的ECC算法的。
(7)s3c2410_nand_enable_hwecc: 在硬件支持的前提下,前面設(shè)置了硬件ECC的話,要實(shí)現(xiàn)這個(gè)函數(shù),用于每次在讀寫操作前,通過(guò)設(shè)置對(duì)應(yīng)的硬件寄存器的某些位,使得啟用硬件ECC,這樣在讀寫操作完成后,就可以去讀取硬件校驗(yàn)產(chǎn)生出來(lái)的ECC數(shù)值了。

當(dāng)然,除了這些你必須實(shí)現(xiàn)的函數(shù)之外,在你更加熟悉整個(gè)框架之后,你可以根據(jù)你自己的nand flash的特點(diǎn),去實(shí)現(xiàn)其他一些原先用系統(tǒng)默認(rèn)但是效率不高的函數(shù),而用自己的更高效率的函數(shù)替代他們,以提升你的nand flash的整體性能和效率。

總結(jié)

以上是生活随笔為你收集整理的NandFlash详述的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。