一、NAND flash的物理組成 NAND Flash 的數(shù)據(jù)是以bit的方式保存在memory cell,一般來說,一個cell 中只能存儲一個bit。這些cell 以8個或者16個為單位,連成bit line,形成所謂的byte(x8)/word(x16),這就是NAND Device的位寬。這些Line會再組成Page,(NAND Flash 有多種結(jié)構(gòu),我使用的NAND Flash 是K9F1208,下面內(nèi)容針對三星的K9F1208U0M),每頁528Bytes(512byte(Main Area)+16byte(Spare Area)),每32個page形成一個Block(32*528B)。具體一片flash上有多少個Block視需要所定。我所使用的三星 k9f1208U0M具有4096個block,故總?cè)萘繛?096*(32*528B)=66MB,但是其中的2MB是用來保存ECC校驗碼等額外數(shù)據(jù)的,故實際中可使用的為64MB。 NAND flash以頁為單位讀寫數(shù)據(jù),而以塊為單位擦除數(shù)據(jù)。按照這樣的組織方式可以形成所謂的三類地址: Column Address:Starting Address of the Register. 翻成中文為列地址,地址的低8位 Page Address :頁地址 Block Address :塊地址 對于NAND Flash來講,地址和命令只能在I/O[7:0]上傳遞,數(shù)據(jù)寬度是8位。
二、NAND Flash地址的表示 512byte需要9bit來表示,對于528byte系列的NAND,這512byte被分成1st half Page Register和2nd half Page Register,各自的訪問由地址指針命令來選擇,A[7:0]就是所謂的column address(列地址),在進(jìn)行擦除操作時不需要它,why?因為以塊為單位擦除。32個page需要5bit來表示,占用A[13:9],即該page在塊內(nèi)的相對地址。A8這一位地址被用來設(shè)置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]上傳遞,因此,必須采用移位的方式進(jìn)行。 例如,對于512Mbit x8的NAND flash,地址范圍是0~0x3FF_FFFF,只要是這個范圍內(nèi)的數(shù)值表示的地址都是有效的。 以NAND_ADDR 為例: 第1 步是傳遞column address,就是NAND_ADDR[7:0],不需移位即可傳遞到I/O[7:0]上,而halfpage pointer即A8 是由操作指令決定的,即指令決定在哪個halfpage 上進(jìn)行讀 寫,而真正的A8 的值是不需程序員關(guān)心的。 第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 器件稍微進(jìn)行一下說明。 由于一個page 的main area 的容量為256word,仍相當(dāng)于512byte。但是,這個時候沒有所謂的1st halfpage 和2nd halfpage 之分了,所以,bit8就變得沒有意義了,也就是這個時候 A8 完全不用管,地址傳遞仍然和x8 器件相同。除了,這一點之外,x16 的NAND使用方法和 x8 的使用方法完全相同。
三、NAND flash驅(qū)動解讀 以前由于做移植多一些,那些工作很簡單(現(xiàn)在看來),從來都不用去關(guān)心驅(qū)動里面到底怎么實現(xiàn)的,這幾次面試才發(fā)現(xiàn)真的是學(xué)的太淺了,似乎我還在學(xué)習(xí)仰泳而那些牛人基本都屬于潛水級的了,潛的不知有多深。我對照著開發(fā)板所帶的NAND flash驅(qū)動和k9f1208的芯片資料把這些代碼通讀了一遍,終于明白了NAND flash的讀寫過程是如何實現(xiàn)的了。我所參考的驅(qū)動是mizi公司為三星芯片所寫的,我看看了,大概和官方2.4.18內(nèi)核的nand.c差不多。 在 s3c2410處理器中有專門的NAND flash控制器,他們位于SFR區(qū),具體可以參看s3c2410用戶手冊。以下的這些代碼均可以在vivi或者kernel里面找到,文中會標(biāo)明程序出自何處。在vivi中,有關(guān)NAND flash的驅(qū)動都在driver/mtd/nand/下,該目錄中包含的源文件:smc_core.c是NAND flash的主要驅(qū)動。 NAND flash 芯片定義了一個很長的結(jié)構(gòu),這個結(jié)構(gòu)中包含了操作NAND flash的函數(shù)和一些必要的變量(include/mtd/nand.h)。 struct nand_chip { #ifdef CONFIG_MTD_NANDY /* =y */ 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 /* CONFIG_MTD_NANDY */ …… #ifdef CONFIG_MTD_NAND_ECC u_char ecc_code_buf[6]; u_char reserved[2]; #endif #endif /* CONFIG_MTD_NANDY */ }; 縱觀對NAND flash的各種操作(read、write、erase),無外乎如下幾種操作: 1.選擇flash nand_select() 2.發(fā)送命令 nand_command() 3.進(jìn)行相應(yīng)操作 read,write…… 4.反選NAND flash nand_deselect()
下面是以上四步的實現(xiàn)代碼: 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) 的作用是設(shè)置2410的NAND FLASH CONFIGURATION (NFCONF) REGISTER的NAND Flash Memory chip enable位為0,這位寄存器在自動重啟后就被系統(tǒng)自動清零。如果要訪問NAND flash的內(nèi)存,這位必須置1。 nand_command(mtd, NAND_CMD_RESET, -1, -1);向flash發(fā)送命令,此命令為reset,即為重置NAND flash。 然后是10us的延遲,給flash個反應(yīng)時間。 2、發(fā)送命令 Nand_command()同樣在smc_core.c中實現(xiàn)。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 讀取狀態(tài) NAND_CMD_STATUS_MULTI 0x71 讀取狀態(tài) NAND_CMD_SEQIN 0x80 寫操作 NAND_CMD_READID 0x90 讀Flash ID號 NAND_CMD_ERASE2 0xd0 擦寫操作 NAND_CMD_RESET oxff 復(fù)位操作
按照程序的注釋,可以將該函數(shù)的實現(xiàn)分為如下幾步: 1、Begin command latch cycle 實現(xiàn)代碼: this->hwcontrol(NAND_CTL_SETCLE); this->hwcontrol(NAND_CTL_DAT_OUT); 找到第二條語句的定義,發(fā)現(xiàn)什么都么做,不解!!希望達(dá)人解答。我猜想可能是一個數(shù)據(jù)讀出的使能操作,允許數(shù)據(jù)讀出。 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. 看了這段英文相信對第一條語句的作用已經(jīng)十分清楚了,他就是用來控制向命令寄存(COMMAND SET (NFCMD) REGISTER)發(fā)送命令的。 2、 Write out the command to the device 這部分對于不同的命令來說,操作的步驟也不太相同,如果為寫操作,那么還有根據(jù)flash不同的容量決定操作步驟,具體可以參看代碼。如果為其他命令,那么就是簡單的一行: this->write_cmd (command); 將命令直接想到命令寄存器(NFCMD[7:0])中。 3、 Set ALE and clear CLE to start address cycle & Serially input address 1中已經(jīng)提到了ALE和CLE的作用,現(xiàn)在開始發(fā)送地址。 實現(xiàn)代碼: this->hwcontrol(NAND_CTL_CLRCLE); // clear the command latch enable this->hwcontrol(NAND_CTL_SETALE); // set the address latch enable 然后按位操作,是用函數(shù)write_addr()將地址寫到NAND FLASH ADDRESS SET (NFADDR) REGISTER中。 4、 Latch in address 實現(xiàn)代碼: this->hwcontrol(NAND_CTL_CLRALE); this->hwcontrol(NAND_CTL_DAT_IN); 地址發(fā)送完畢,清楚ALE。 5、 Pause for 15us 我使用的VIVI中,使用udelay (15)延時15us,但這個時間會因NAND Flash的不同而不同。 三、Operation 根據(jù)函數(shù)的不同,操作部分會不一樣,但是主要的是對NAND FLASH DATA (NFDATA) REGISTER的操作,或?qū)懀ň幊蹋┗蛘咦x。通過讀或?qū)懞瘮?shù)的參數(shù)來返回或傳遞讀出的值或?qū)懭氲闹。寫得操作通常比較麻煩,他要將寫到flash的內(nèi)容重新讀出后進(jìn)行ECC校驗,如果數(shù)據(jù)正確則在重新真正的寫(編程),如果錯誤,則將數(shù)據(jù)寫入flash的另一個塊。讀和寫都是以頁為單位進(jìn)行操作。而擦除則以塊為單位,三個周期發(fā)送完地址。擦除完畢后同樣需要進(jìn)行檢察以確定是否擦除成功。 四、De-select the NAND device 實現(xiàn)代碼: #define nand_deselect() this->hwcontrol(NAND_CTL_CLRNCE); 反選flash吧,不知這樣叫正確與否,跟select the NAND device相反,亦即使用完后將使能flash位清0,代碼是NFCONF位于0x4e00_0000的位置(NFCONF |= NFCONF_nFCE_HIGH;),有興趣的可以讀讀代碼,看看這是怎么實現(xiàn)的,我的感覺就是關(guān)于寄存器的清置讀起來都比較暈。 rnn本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處: http://www.ixpub.net/home.php?mod=space&uid=10821989&do=blog&id=409482 |