S3C2440 NandFlash控制器介紹:
NAND Flash控制器提供幾個寄存器來簡化對NAND Flash的操作。比如要發出讀命令,只需往NFCMD寄存器寫入0即可,NAND FLash控制器會自動發出各種控制信號。
1、操作方法概述
訪問NAND Flash時需要先發出命令,然後發出地址序列,最後讀/寫數據;需要使用各種使能信號來分辨是命令、地址還是數據。S3C2410的NAND Flash控制器提供了NFCONF、NFCMD、NFADDR、NFDATA、NFSTAT和NFECC等6個寄存器來簡化這些操作。S3C2440的NAND Flash控制器則提供了NFCONF、NFCONT、NFCMMD、NFADDR、NFDATA、NFSTAT和其它與ECC有關的寄存器。對NAND Flash控制器的操作,S3C2410和S3C2440有一些小的差別:有些寄存器不一樣,有些寄存器內容不一樣,這在實例程序中會體現出來。
NAND Flash的讀寫操作次序如下:
(1)設置NFCONF(對於S3C2440,還要設置NFCONT)寄存器,配置NAND Flash。
(2)向NFCMD寄存器寫入命令,這些命令可以參考表8.2。
(3)向NFADDR寄存器寫入地址。
(4)讀/寫數據:通過寄存器NFSTAT檢測NAND Flash的狀態,在啟動某個操作後,應該檢測R/nB信號以確定該操作是否完成、是否成功。
2.下面講解這些寄存器的功能和用法:
1)NFCONF:NAND Flash配置寄存器
這個寄存器在S3C2410、S3C2440上功能有所不同。S3C2410的NFCONF寄存器被用來使能禁止NAND Flash控制器、使能禁止控制引腳信號nFCE、初始化ECC,設置NAND Flash的時序參數等。
(2)NFCONT:NAND Flash控制寄存器,S3C2410沒有這個寄存器。
被用來使能/禁止NAND Flash控制寄存器,使能/禁止控制引腳信號nFCE、初始化ECC。它還有其它功能,在一般的應用中用不到,比如鎖定NAND Flash。
(3)NFCMD:NAND Flash命令寄存器
對於不同型號的Flash,操作命令一般不一樣。對於本板使用的K9F1208U0M,可參考表8.2。
(4)NFADDR:NAND Flash地址寄存器。
當寫這個寄存器時,它將對Flash發出地址信號。
(5)NFDATA:NAND Flash數據寄存器。
只用到低8位,讀、寫此寄存器將啟動對NAND Flash的讀數據、寫數據操作。
(6)NFSTAT:NAND Flash狀態寄存器
只用到位0,0:busy,1:ready
讀NandFlash的步驟:
①設置NFCONF
在HCLK=100Mhz的情況下,TACLS=0,TWRPH0=3,TWRPH1=0,則
NFCONF = 0x300
使能NAND Flash控制器、禁止控制引腳信號nFCE,初始化ECC
NFCONT = (1<<4) | (1<<1) | (1<<0)
②操作NAND Flash前,復位
NFCONT &= ~(1<<1) 發出片選信號
NFCMD = 0xff reset命令
然後循環查詢NFSTAT位0,直到等於1,處於就緒態
最後禁止片選信號,在實際使用時再使能
NFCONT |= 0x2 禁止NAND Flash
③發出讀命令
NFCONT &= ~(1<<1) 發出片選信號
NFCMD = 0 讀命令
④發出地址信號
⑤循環查詢NFSTAT,直到等於1
⑥連續讀NFDATA寄存器,得到一頁數據
⑦最後禁止NAND Flash片選信號
NFCONT |= (1<<1)
介紹幾個Nand Flash初期化的函數:
/* 初始化NAND Flash */
void nand_init(void)
{
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
/* 判斷是S3C2410還是S3C2440 */
if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
{
nand_chip.nand_reset = s3c2410_nand_reset;
nand_chip.wait_idle = s3c2410_wait_idle;
nand_chip.nand_select_chip = s3c2410_nand_select_chip;
nand_chip.nand_deselect_chip = s3c2410_nand_deselect_chip;
nand_chip.write_cmd = s3c2410_write_cmd;
nand_chip.write_addr = s3c2410_write_addr;
nand_chip.read_data = s3c2410_read_data;
/* 使能NAND Flash控制器, 初始化ECC, 禁止片選, 設置時序 */
s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
}
else
{
nand_chip.nand_reset = s3c2440_nand_reset;
nand_chip.wait_idle = s3c2440_wait_idle;
nand_chip.nand_select_chip = s3c2440_nand_select_chip;
nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
nand_chip.write_cmd = s3c2440_write_cmd;
#ifdef LARGER_NAND_PAGE
nand_chip.write_addr = s3c2440_write_addr_lp;
#else
nand_chip.write_addr = s3c2440_write_addr;
#endif
nand_chip.read_data = s3c2440_read_data;
/* 設置時序 */
s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
/* 使能NAND Flash控制器, 初始化ECC, 禁止片選 */
s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
}
/* 復位NAND Flash */
nand_reset();
}