<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 對S3C2440讀取NAND Flash的總結(jié)

          對S3C2440讀取NAND Flash的總結(jié)

          作者: 時(shí)間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
          在網(wǎng)上找了一些資料,又結(jié)合自己的經(jīng)歷談一下我對NAND Flash 的了解。

          S3C2440 板的Nand Flash 支持由兩部分組成:Nand Flash 控制器(集成在S3C2440 CPU)和Nand Flash 存儲芯片(K9F1208U0B)兩大部分組成。當(dāng)要訪問Nand Flash中的數(shù)據(jù)時(shí),必須通過Nand Flash控制器發(fā)送命令才能完成。所以, Nand Flash相當(dāng)于S3C2440的一個(gè)外設(shè),而不位于它的內(nèi)存地址區(qū).

          本文引用地址:http://www.ex-cimer.com/article/201611/317616.htm

          NAND Flash 的數(shù)據(jù)是以bit 的方式保存在memory cell,一般來說,一個(gè)cell 中只能存儲一個(gè)bit。這些cell 以8 個(gè)或者16 個(gè)為單位,連成bit line,形成所謂的byte(x8)/word(x16),這就是NAND Device 的位寬。這些Line 會再組成Page.

          NandFlash有多種結(jié)構(gòu),我使用的NandFlash是K9F1208,下面內(nèi)容針對三星的K9F1208U0M,數(shù)據(jù)存儲容量為64MB,采用塊頁式存儲管理。一共有4096個(gè)block(塊),每個(gè)block有32個(gè)page(頁),每個(gè)page有528Byte。

          1block=32page,1page=528byte=512byte(MainArea)+16byte(SpareArea)

          Nandflash以頁為單位讀寫數(shù)據(jù),而以塊為單位擦除數(shù)據(jù)。

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

          --BlockAddress--PageAddress--ColumnAddress

          對于NANDFlash來講,8個(gè)I/O引腳充當(dāng)數(shù)據(jù)、地址、命令的復(fù)用端口。地址和命令只能在I/O[7:0]上傳遞,數(shù)據(jù)寬度是8位。

          512byte需要9bit來表示,對于528byte系列的NAND,這512byte被分成1sthalf2ndhalf,最后16個(gè)字節(jié)(又稱OOB)用于NandFlash命令執(zhí)行完后設(shè)置狀態(tài)用,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的columnaddress。

          32個(gè)page需要5bit來表示,占用A[13:9],即該page在塊內(nèi)的相對地址。Block的地址是由A14以上的bit來表示,例如512Mb的NAND,共4096block,因此,需要12個(gè)bit來表示,即A[25:14],如果是1Gbit的528byte/page的NANDFlash,則blockaddress用A[26:14]表示。

          NANDFlash的地址表示為:

          BlockAddress|PageAddressinblock|halfpagepointer|ColumnAddress

          地址傳送順序是ColumnAddress,PageAddress,BlockAddress。

          由于地址只能在I/O[7:0]上傳遞,因此,必須傳遞多次。例如,對于512Mbitx8的NANDflash,地址范圍是0-0x3FFFFFF,只要是這個(gè)范圍內(nèi)的數(shù)值表示的地址都是有效的。以NAND_ADDR為例:第1步是傳遞columnaddress,就是NAND_ADDR[7:0]給相應(yīng)的寄存器,即可傳遞到I/O[7:0]上,而halfpagepointer即bit8是由操作指令決定的,即指令決定在哪個(gè)halfpage上進(jìn)行讀寫。而真正的bit8的值是dontcare的。第2步就是將NAND_ADDR[16:9]傳到I/O[7:0]上。第3步將NAND_ADDR[24:17]放到I/O上。第4步需要將NAND_ADDR[25]放到I/O因此,整個(gè)地址傳遞過程需要4步才能完成,即4-stepaddressing。如果NANDFlash的容量是256Mbit以下,那么,blockadress最高位只到bit24,因此尋址只需要3步。下面,就x16(16位)的NANDflash器件稍微進(jìn)行一下說明。由于一個(gè)page的mainarea的容量為256word,仍相當(dāng)于512byte。但是,這個(gè)時(shí)候沒有所謂的1sthalfpage和2ndhalfpage之分了,所以,bit8就變得沒有意義了,也就是這個(gè)時(shí)候bit8完全不用管,地址傳遞仍然和x8器件相同。除了,這一點(diǎn)之外,x16的NAND使用方法和x8的使用方法完全相同。

          正如硬盤的盤片被分為磁道,每個(gè)磁道又分為若干扇區(qū),一塊nandflash也分為若干block,每個(gè)block分為如干page。一般而言,block、page之間的關(guān)系隨著芯片的不同而不同,典型的分配是這樣的:
          1block=32page
          1page=512bytes(datafield)+16bytes(oob)

          需要注意的是,對于flash的讀寫都是以一個(gè)page開始的,但是在讀寫之前必須進(jìn)行flash的擦寫,而擦寫則是以一個(gè)block為單位的。同時(shí)必須提醒的是,512bytes理論上被分為1sthalf和2sdhalf,每個(gè)half各占256個(gè)字節(jié)。

          我們討論的K9F1208U0B總共有4096個(gè)Blocks,故我們可以知道這塊flash的容量為4096*(32*528)=69206016Bytes=66MB。但事實(shí)上每個(gè)Page上的最后16Bytes是用于存貯檢驗(yàn)碼和其他信息用的,并不能存放實(shí)際的數(shù)據(jù),所以實(shí)際上我們可以操作的芯片容量為4096*(32*512)=67108864Bytes=64MB。

          由上圖所示,1個(gè)Page總共由528Bytes組成,這528個(gè)字節(jié)按順序由上而下以列為單位進(jìn)行排列(1列代表一個(gè)Byte。第0行為第0Byte,第1行為第1Byte,以此類推,每個(gè)行又由8個(gè)位組成,每個(gè)位表示1個(gè)Byte里面的1bit)。這528Bytes按功能分為兩大部分,分別是DataField和SpareField,其中SpareField占528Bytes里的16Bytes,這16Bytes是用于在讀寫操作的時(shí)候存放校驗(yàn)碼用的,一般不用做普通數(shù)據(jù)的存儲區(qū),除去這16Bytes,剩下的512Bytes便是我們用于存放數(shù)據(jù)用的DataField,所以一個(gè)Page上雖然有528個(gè)Bytes,但我們只按512Bytes進(jìn)行容量的計(jì)算。

          讀命令有兩個(gè),分別是Read1,Read2其中Read1用于讀取DataField的數(shù)據(jù),而Read2則是用于讀取SpareField的數(shù)據(jù)。對于NandFlash來說,讀操作的最小操作單位為Page,也就是說當(dāng)我們給定了讀取的起始位置后,讀操作將從該位置開始,連續(xù)讀取到本Page的最后一個(gè)Byte為止(可以包括SpareField)

          NandFlash的尋址
          NandFlash的地址寄存器把一個(gè)完整的NandFlash地址分解成ColumnAddress與PageAddress.進(jìn)行尋址。

          ColumnAddress:列地址。ColumnAddress其實(shí)就是指定Page上的某個(gè)Byte,指定這個(gè)Byte其實(shí)也就是指定此頁的讀寫起始地址。

          PaageAddress:頁地址。由于頁地址總是以512Bytes對齊的,所以它的低9位總是0。確定讀寫操作是在Flash上的哪個(gè)頁進(jìn)行的。

          Read1命令

          當(dāng)我們得到一個(gè)NandFlash地址addr時(shí)我們可以這樣分解出ColumnAddress和PageAddress
          column_addr=src_addrQ2;//columnaddress
          page_address=(src_addr>>9);//pageaddress

          也可以這么認(rèn)為,一個(gè)NandFlash地址的src_addr[7,0]是它的column_addr,addr[25,9]是它的PageAddress。(注意地址位src_addr[8]并沒有出現(xiàn),也就是addr[8]被忽略,在下面你將了解到這是什么原因)

          Read1命令的操作發(fā)送完讀命令00h或01h(00h與01h的區(qū)別請見下文描述)之后將分4個(gè)Cycle發(fā)送參數(shù),1st.Cycle是發(fā)送ColumnAddress。2nd.Cycle,3rd.Cycle和4th.Cycle則是指定PageAddress(每次向地址寄存器發(fā)送的數(shù)據(jù)只能是8位,所以17位的PageAddress必須分成3次進(jìn)行發(fā)送。

          Read1的命令里面出現(xiàn)了兩個(gè)命令選項(xiàng),分別是00h和01h。這里出現(xiàn)了兩個(gè)讀命是否令你意識到什么呢?是的,00h是用于讀寫1sthalf的命令,而01h是用于讀取2ndhalf的命令?,F(xiàn)在我可以結(jié)合上圖給你說明為什么K9F1208U0B的DataField被分為2個(gè)half了。

          如上文我所提及的,Read1的1st.Cycle是發(fā)送ColumnAddress,假設(shè)我現(xiàn)在指定的ColumnAddress是0,那么讀操作將從此頁的第0號Byte開始一直讀取到此頁的最后一個(gè)Byte(包括SpareField),如果我指定的ColumnAddress是127,情況也與前面一樣,但不知道你發(fā)現(xiàn)沒有,用于傳遞ColumnAddress的數(shù)據(jù)線有8條(I/O0-I/O7,對應(yīng)addr[7,0],這也是addr[8]為什么不出現(xiàn)在我們傳遞的地址位中),也就是說我們能夠指定的ColumnAddress范圍為0-255,但不要忘了,1個(gè)Page的DataField是由512個(gè)Byte組成的,假設(shè)現(xiàn)在我要指定讀命令從第256個(gè)字節(jié)處開始讀取此頁,那將會發(fā)生什么情景?我必須把ColumnAddress設(shè)置為256,但ColumnAddress最大只能是255,這就造成數(shù)據(jù)溢出。正是因?yàn)檫@個(gè)原因我們才把DataField分為兩個(gè)半?yún)^(qū),當(dāng)要讀取的起始地址(ColumnAddress)在0-255內(nèi)時(shí)我們用00h命令,當(dāng)讀取的起始地址是在256-511時(shí),則使用01h命令.假設(shè)現(xiàn)在我要指定從第256個(gè)byte開始讀取此頁,那么我將這樣發(fā)送命令串。
          column_addr=256;
          NF_CMD=0x01;從2ndhalf開始讀取
          NF_ADDR=column_addr&0xff;1stCycle
          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=0x30;

          事實(shí)上,當(dāng)NF_CMD=0x01時(shí),NANDFlash地址寄存器中的第8位(A8)將被設(shè)置為1(如上文分析,A8位不在我們傳遞的地址中,這個(gè)位其實(shí)就是硬件電路根據(jù)01h或是00h這兩個(gè)命令來置高位或是置低位),這樣我們傳遞column_addr的值256隨然由于數(shù)據(jù)溢出變?yōu)?,但A8位已經(jīng)由于NF_CMD=0x01的關(guān)系被置為1了。這8個(gè)位所表示的正好是256,這樣讀操作將從此頁的第256號byte(2ndhalf的第0號byte)開始讀取數(shù)據(jù)。

          在對NANDFlash進(jìn)行任何操作之前,NANDFlash必須被初始化。向NandFlash的命令寄存器和地址寄存器發(fā)送完以上命令和參數(shù)之后,我們就可以從rNFDATA寄存器(NandFlash數(shù)據(jù)寄存器)讀取數(shù)據(jù)了.
          我用下面的代碼進(jìn)行數(shù)據(jù)的讀取.
          for(i=column_addr;i<512;i++)
          {
          *buf++=NF_RDDATA();
          }

          每當(dāng)讀取完一個(gè)Page之后,數(shù)據(jù)指針會落在下一個(gè)Page的0號Column(0號Byte).

          存儲操作特點(diǎn):
          1.擦除操作的最小單位是塊。
          2.NandFlash芯片每一位(bit)只能從1變?yōu)?,而不能從0變?yōu)?wbr />1,所以在對其進(jìn)行寫入操作之前要一定將相應(yīng)塊擦除(擦除即是將相應(yīng)塊得位全部變?yōu)?wbr />1).
          3.OOB部分的第六字節(jié)(即517字節(jié))標(biāo)志是否是壞塊,如果不是壞塊該值為FF,否則為壞塊。
          4.除OOB第六字節(jié)外,通常至少把OOB的前3個(gè)字節(jié)存放NandFlash硬件ECC碼(關(guān)于硬件ECC碼請參看Nandflash控制器一節(jié)).

          重要芯片引腳功能
          I/O0-I/O7:復(fù)用引腳。可以通過它向nandflash芯片輸入數(shù)據(jù)、地址、nandflash命令以及輸出數(shù)據(jù)和操作狀態(tài)信息。
          CLE(CommandLatchEnable):命令鎖存允許
          ALE(AddressLactchEnable):地址鎖存允許
          -CE:芯片選擇
          -RE:讀允許
          -WE:寫允許
          -WP:在寫或擦除期間,提供寫保護(hù)
          R/-B:讀/忙輸出


          NandFlash控制器中的硬件ECC介紹

          ECC產(chǎn)生方法

          ECC是用于對存儲器之間傳送數(shù)據(jù)正確進(jìn)行校驗(yàn)的一種算法,分硬件ECC和軟件ECC算法兩種,在S3C2440的NandFlash控制器中實(shí)現(xiàn)了由硬件電路(ECC生成器)實(shí)現(xiàn)的硬件ECC。

          ECC生成器工作過程
          當(dāng)寫入數(shù)據(jù)到Nandflash存儲空間時(shí),ECC生成器會在寫入數(shù)據(jù)完畢后自動生成ECC碼,將其放入到ECC0-ECC2。當(dāng)讀出數(shù)據(jù)時(shí)NandFlash同樣會在讀數(shù)據(jù)完畢后,自動生成ECC碼將其放到ECC0-ECC2當(dāng)中。

          ECC的運(yùn)用

          當(dāng)寫入數(shù)據(jù)時(shí),可以在每頁寫完數(shù)據(jù)后將產(chǎn)生的ECC碼放入到OOB指定的位置(Byte6)去,這樣就完成了ECC碼的存儲。這樣當(dāng)讀出該頁數(shù)據(jù)時(shí),將所需數(shù)據(jù)以及整個(gè)OOB讀出,然后將指定位置的ECC碼與讀出數(shù)據(jù)后在ECC0-ECC1的實(shí)際產(chǎn)生的ECC碼進(jìn)行對比,如果相等則讀出正確,若不相等則讀取錯(cuò)誤需要進(jìn)行重讀。

            操作命令字介紹

          操作NAND FLASH時(shí),先傳輸命令,接著輸出地址,最后讀/寫數(shù)據(jù),期間還要檢查FLASH的狀態(tài)。具體的命令字見下表。


            1、Read命令字為00h,30h。

            如上圖,當(dāng)發(fā)出00h命令后,接著4個(gè)字節(jié)的地址序列,然后再發(fā)出30h命令,接著,就可以讀出數(shù)據(jù)了,當(dāng)發(fā)送完30h后,可以檢測R/B引腳看是否準(zhǔn)備好了,如果準(zhǔn)備好,就可以讀出數(shù)據(jù)。

            2、Reset

            命令字:FFh

            當(dāng)向芯片發(fā)送FFh命令時(shí),可以復(fù)位芯片,如果芯片正在處于讀、寫、擦除狀態(tài),復(fù)位命令會終止這些命令。

          3、Page Program

            命令字:80h,10h.

            NAND FLASH的寫操作一般是以頁為單位進(jìn)行的,因此才會叫Page Program,但是也支持一個(gè)字以上的(包括一個(gè)字)連續(xù)寫操作。開始發(fā)出80h命令,接著發(fā)送5個(gè)字節(jié)的地址序列,然后向FLASH發(fā)送數(shù)據(jù),最大為一頁大小,最后發(fā)送10h命令啟動燒寫,此時(shí)FLASH內(nèi)部會自動完成寫、校驗(yàn)操作。發(fā)送10h后,可以通過讀狀態(tài)命令70h(見下文)獲知寫操作是否完成,是否成功。

          4、Copy-Back Program

            命令字:00h、8Ah、10h.

            此命令用于將一頁復(fù)制到同一層的另外一頁,它省去了讀出數(shù)據(jù)、將數(shù)據(jù)重新載入FLASH的過程,使得效率大大提高。

            關(guān)于層:NAND FLASH有層的概念,K9F2G08分為兩層,每層包括了1024個(gè)塊,如下圖,因此上面的命令表中才會有two-plane的命令,這些命令可以使得在兩個(gè)層間完成操作,這樣程序員就很方便的使用一個(gè)命令完成更多的操作,其命令格式和單層操作的類似,詳見手冊。但K9F2G08R0A不支持兩層命令。




            上圖清晰的告訴我們,開始發(fā)送00h和源地址,當(dāng)發(fā)送35h之后,芯片將一頁大小的數(shù)據(jù)讀入到內(nèi)部寄存器,接著,我們發(fā)送85h和目的地址序列,最后發(fā)送10h啟動。最后,我們可以使用70h/7Bh檢測是否完成,是否成功。

            5、Block Erase

            命令字:60h、D0h

            擦除操作是以塊為單位的,也就是128K。開始發(fā)出60h,然后發(fā)出3個(gè)地址序列僅行地址,最好發(fā)出D0h。具體操作,如下圖。


            6、Read Status

             命令字:70h

             讀狀態(tài)命令可以讀出芯片的狀態(tài)寄存器,查看是否讀、寫操作是否完成、是否成功。具體的狀態(tài)見下圖。


            S3C2440的NAND FLASH控制器介紹

            看了上面的命令時(shí)序圖,大家肯定認(rèn)為對NAND FLASH的操作比較復(fù)雜,因此S3C2440為了簡化操作,為我們提供了幾個(gè)寄存器,比如NFCMD寄存器,就是NAND FLASH命令寄存器,如果我們需要讀命令,直接向此寄存器寫00h、30h即可。

            基本操作步驟:

            1.設(shè)置NFCONF和NFCONT寄存器,配置NAND FLASH;

            2.向NFCMD寄存器寫入命令;

            3.向NFADDR寄存器寫入地址;

            4.讀/寫數(shù)據(jù),通過NFSTAT檢測NAND FLASH的狀態(tài),讀R/nB信號以確定是否完成操作,是否成功。

            主要寄存器:

            (NFCONF)

            配置寄存器,設(shè)置NAND FLASH的時(shí)序參考TACLS、TWRPH0、TWRPH1,這三個(gè)參數(shù)見下面時(shí)序圖;設(shè)置位寬度;還包括一些只讀位,用來批示是否支持其它大小的頁。

            TACLS:表示CLT/ALE的建立時(shí)間(setup time)。

            TWRPH0:表示CLE/ALE的持續(xù)時(shí)間。

            TWRPH1:表示CLE/ALE的維持時(shí)間(hold time)。




          NFCONT

            用來使能/禁止NAND FLASH控制器、使能/禁止控制引腳信號nFCE、初始化ECC。

            NFCMD

            命令寄存器,用來向其寫入命令。

            NFADDR

            地址寄存器,用來向其寫入地址。

            NFDATA

            數(shù)據(jù)寄存器,用來讀、寫數(shù)據(jù)使用,只用到8位。

            NFSTAT

            狀態(tài)寄存器,只用到一位,0:busy;1:ready。

             NFECC

            校驗(yàn)寄存器,ECC 校驗(yàn)寄存器

            NAND FLASH的操作(以讀為例)

            

            1、設(shè)置NFCONF和NFCONT

            NFCONF主要是設(shè)置TACLS、TWRPH0、TWRPH1三個(gè)時(shí)間參數(shù)。根據(jù)手冊的參數(shù)表,見下圖:


            三個(gè)參數(shù)只有最小值 MIN,沒有最大值,因此,只要參數(shù)大于表格中的數(shù)即可,這里涉及時(shí)鐘的一些概念,這里直接將參數(shù)告訴大家:

            TACLS=1;TWRPH0=4;TWRPH1=0。

            NFCONT設(shè)置為:NFCONT=(1<<4)|(1<<1)|(1<<0) 表示使能NAND FLASH控制器、禁止控制引腳信號nFCE、初始化ECC。



          關(guān)鍵詞: S3C2440NANDFLAS

          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();