nandflash詳細操作

2021-06-10 00:46:42 字數 3604 閱讀 6287

下面介紹讀操作,讀操作是以頁為單位進行的。如果在讀取資料的過程中不進行ecc校驗判斷,則讀操作比較簡單,在寫入讀命令的兩個週期之間寫入要讀取的頁位址,然後讀取資料即可。如果為了更準確地讀取資料,則在讀取完資料之後還要進行ecc校驗判斷,以確定所讀取的資料是否正確。

在上文中我們已經介紹過,nandflash

的每一頁有兩區:main區和spare區,main區用於儲存正常的資料,spare區用於儲存其他附加資訊,其中就包括ecc校驗碼。當我們在寫入資料的時候,我們就計算這一頁資料的ecc校驗碼,然後把校驗碼儲存到spare區的特定位置中,在下次讀取這一頁資料的時候,同樣我們也計算ecc校驗碼,然後與spare區中的ecc校驗碼比較,如果一致則說明讀取的資料正確,如果不一致則不正確。ecc的演算法較為複雜,好在s3c2440能夠硬體產生ecc校驗碼,這樣就省去了不少的麻煩事。s3c2440即可以產生main區的ecc校驗碼,也可以產生spare區的ecc校驗碼。因為k9f2g08u0a是8位io口,因此s3c2440共產生4個位元組的main區ecc碼和2個位元組的spare區ecc碼。在這裡我們規定,在每一頁的spare區的第0個位址到第3個位址儲存main區ecc,第4個位址和第5個位址儲存spare區ecc。產生ecc校驗碼的過程為:在讀取或寫入哪個區的資料之前,先解鎖該區的ecc,以便產生該區的ecc。在讀取或寫入完資料之後,再鎖定該區的ecc,這樣系統就會把產生的ecc碼儲存到相應的暫存器中。main區的ecc儲存到nfmecc0/1中(因為k9f2g08u0a是8位io口,因此這裡只用到了nfmecc0),spare區的ecc儲存到nfsecc中。對於讀操作來說,我們還要繼續讀取spare區的相應位址內容,已得到上次寫操作時所儲存的main區和spare區的ecc,並把這些資料分別放入nfmeccd0/1和nfseccd的相應位置中。最後我們就可以通過讀取nfestat0/1(因為k9f2g08u0a是8位io口,因此這裡只用到了nfestat0)中的低4位來判斷讀取的資料是否正確,其中第0位和第1位為main區指示錯誤,第2位和第3位為spare區指示錯誤。

下面就給出一段具體的頁讀操作程式:

u8 rnf_readpage(u32 page_number)

nf_mecc_lock();                     //鎖定main區ecc值

nf_secc_unlock();                  //解鎖spare區ecc

mecc0=nf_rddata();        //讀spare區的前4個位址內容,即第2048~2051位址,這4個位元組為main區的ecc

//把讀取到的main區的ecc校驗碼放入nfmeccd0/1的相應位置內

rnfmeccd0=((mecc0&0xff00)<<8)|(mecc0&0xff);

rnfmeccd1=((mecc0&0xff000000)>>8)|((mecc0&0xff0000)>>16);

nf_secc_lock();               //鎖定spare區的ecc值

secc=nf_rddata();           //繼續讀spare區的4個位址內容,即第2052~2055位址,其中前2個位元組為spare區的ecc值

//把讀取到的spare區的ecc校驗碼放入nfseccd的相應位置內

rnfseccd=((secc&0xff00)<<8)|(secc&0xff);

nf_nfce_h();             //關閉nandflash片選

//判斷所讀取到的資料是否正確

if ((rnfestat0&0xf) == 0x0)

return 0x66;                  //正確

else 

return 0x44;                  //錯誤

}這段程式是把某一頁的內容讀取到全域性變數陣列buffer中。該程式的輸入引數直接就為k9f2g08u0a的第幾頁,例如我們要讀取第128064頁中的內容,可以呼叫該程式為:rnf_readpage(128064);。由於第128064頁是第2001塊中的第0頁(128064=2001×64+0),所以為了更清楚地表示頁與塊之間的關係,也可以寫為:rnf_readpage(2001*64);。

頁寫操作的大致流程為:在兩個寫命令週期之間分別寫入頁位址和資料,當然如果為了保證下次讀取該資料時的正確性,還需要把main區的ecc值和spare區的ecc值寫入到該頁的spare區內。然後我們還需要讀取狀態暫存器,以判斷這次寫操作是否正確。下面就給出一段具體的頁寫操作程式,其中輸入引數也是要寫入資料到第幾頁:

u8 rnf_writepage(u32 page_number)

nf_mecc_lock();                     //鎖定main區的ecc值

mecc0=rnfmecc0;                    //讀取main區的ecc校驗碼

//把ecc校驗碼由字型轉換為位元組型,並儲存到全域性變數陣列eccbuf中

eccbuf[0]=(u8)(mecc0&0xff);

eccbuf[1]=(u8)((mecc0>>8) & 0xff);

eccbuf[2]=(u8)((mecc0>>16) & 0xff);

eccbuf[3]=(u8)((mecc0>>24) & 0xff);

nf_secc_unlock();                  //解鎖spare區的ecc

//把main區的ecc值寫入到spare區的前4個位元組位址內,即第2048~2051位址

for(i=0;i<4;i++) 

nf_secc_lock();                      //鎖定spare區的ecc值

secc=rnfsecc;                   //讀取spare區的ecc校驗碼

//把ecc校驗碼儲存到全域性變數陣列eccbuf中

eccbuf[4]=(u8)(secc&0xff);

eccbuf[5]=(u8)((secc>>8) & 0xff);

//把spare區的ecc值繼續寫入到spare區的第2052~2053位址內

for(i=4;i<6;i++)

nf_cmd(cmd_write2);                //頁寫命令週期2

delay(1000);          //延時一段時間,以等待寫操作完成

nf_cmd(cmd_status);                 //讀狀態命令

//判斷狀態值的第6位是否為1,即是否在忙,該語句的作用與nf_detect_rb();相同

dowhile(!(stat&0x40));

nf_nfce_h();                    //關閉nandflash片選

//判斷狀態值的第0位是否為0,為0則寫操作正確,否則錯誤

if (stat & 0x1)

else 

return 0x66;                  //寫操作成功

}該段程式先判斷該頁所在的壞是否為壞塊,如果是則退出。在最後寫操作失敗後,還要標註該頁所在的塊為壞塊,其中所用到的函式rnf_isbadblock和rnf_markbadblock,我們在後面介紹。我們再總結一下該程式所返回數值的含義,0x42:表示該頁所在的塊為壞塊;0x43:表示寫操作失敗,並且在標註該頁所在的塊為壞塊時也失敗;0x44:表示寫操作失敗,但是標註壞塊成功;0x66:寫操作成功。

nand flash 讀寫操作

1 頁讀 如下所示,先輸入讀命令 0x00 然後輸入5個位址,分為2個列位址 頁內位址 和3個行位址 頁和block位址 再輸入讀確認位址0x30,nand硬體會自動從指定的頁的主儲存區讀資料到頁快取 頁暫存器 此時r b 為低電平,當內部讀完成後,r b 恢復為高電平,此時便可以通過nfc的資料暫...

nand flash操作原理

1.nand flash原理圖 訊號線只有ldata 0 7 既傳送命令,傳送位址,還能讀寫資料。nand flash引腳定義 rnb 狀態訊號 nfce 片選訊號 cle 為高表示當前 ldata上的資料是命令 nfwe 寫 nfre 讀 2.辨別nand flash 每個nand flash裡面...

nandflash操作詳解

1.nandflash就是嵌入式系統的硬碟 2.分類 1 mlc 儲存單元格儲存兩位,慢,偏移,壽命短,容量大 2 slc 儲存一位。快,壽命長,容量小,昂貴 3訪問 1 獨立編址,有專用的控制器,控制器裡有相應的暫存器,先送位址,然後命令,最後資料 2 位址組成 行位址 頁編號 列位址 在頁中的偏...