NAND Flash結構與驅動分析
一、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位。
二、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 的使用方法完全相同。
三、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
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
……
#ifdef CONFIG_MTD_NAND_ECC
u_char ecc_code_buf[6];
u_char reserved[2];
#endif
#endif
};
縱觀對NAND flash的各種操作(read、write、erase),無外乎如下幾種操作:
1.選擇flash nand_select()
2.發送指令 nand_command()
3.進行相應操作 read,write……
4.反選NAND flash nand_deselect()
下面是以上四步的實作代碼:
1、選擇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個反應時間。
2、發送指令
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 複位操作
按照程式的注釋,可以将該函數的實作分為如下幾步:
1、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)發送指令的。
2、 Write out the command to the device
這部分對于不同的指令來說,操作的步驟也不太相同,如果為寫操作,那麼還有根據flash不同的容量決定操作步驟,具體可以參看代碼。如果為其他指令,那麼就是簡單的一行:
this->write_cmd (command);
将指令直接想到指令寄存器(NFCMD[7:0])中。
3、 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中。
4、 Latch in address
實作代碼:
this->hwcontrol(NAND_CTL_CLRALE);
this->hwcontrol(NAND_CTL_DAT_IN);
位址發送完畢,清楚ALE。
5、 Pause for 15us
我使用的VIVI中,使用udelay (15)延時15us,但這個時間會因NAND Flash的不同而不同。
三、Operation
根據函數的不同,操作部分會不一樣,但是主要的是對NAND FLASH DATA (NFDATA) REGISTER的操作,或寫(程式設計)或者讀。通過讀或寫函數的參數來傳回或傳遞讀出的值或寫入的值。寫得操作通常比較麻煩,他要将寫到flash的内容重新讀出後進行ECC校驗,如果資料正确則在重新真正的寫(程式設計),如果錯誤,則将資料寫入flash的另一個塊。讀和寫都是以頁為機關進行操作。而擦除則以塊為機關,三個周期發送完位址。擦除完畢後同樣需要進行檢察以确定是否擦除成功。
四、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;),有興趣的可以讀讀代碼,看看這是怎麼實作的,我的感覺就是關于寄存器的清置讀起來都比較暈。
http://blog.chinaunix.net/uid-26739173-id-3158739.html