//=============================================================
// 文件名称: Nand.c
// 功能描述: NandFlash驱动
// 选择Nand类型:1.K9F1208(small page) 2.K9F2G08(large page)
// 选择要执行的操作:
// 0: 读取Chip ID
// 1: 复位Nand
// 2: 块擦除,输入要擦除的块
// 3: 读Nand,输入要读取的块,页
// 4: 写Nand,输入要写入的块,页,偏移量
// 5: 检查坏块
//
// 维护记录: 2009-08-15 V1.0
// 2009-10-14 V1.1 支持大页Nand,还需完善ECC校验
//=============================================================
#include "def.h"
#include "2440lib.h"
#include "2440addr.h"
#include "Nand.h"
#include "uart.h"
//====================================================
// 常量定义区
//====================================================
#define EnNandFlash() (rNFCONF |= (1<<0)) //bit0=1 enable NAND flash controller
#define DsNandFlash() (rNFCONF &= ~(1<<)) //bit0=1 disable NAND flash controller
#define InitEcc() (rNFCONF |= (1<<4)) //bit4=1 initialize ECC
#define NoEcc() (rNFCONT &= ~(1<<4)) //bit4=0 initialize ECC
#define NF_ChipEn() (rNFCONT&=~(1<<1)) //bit1=0 NAND flash nFCE = L (active)
#define NF_ChipDs() (rNFCONT|=(1<<1)) //bit1=1 NAND flash nFCE = H (inactive)
#define NF_MECC_UnLock() {rNFCONT&=~(1<<5);}
#define NF_MECC_Lock() {rNFCONT|=(1<<5);}
#define NF_SECC_UnLock() {rNFCONT&=~(1<<6);}
#define NF_SECC_Lock() {rNFCONT|=(1<<6);}
#define NF_CMD(cmd) {rNFCMD=cmd;}
#define NF_ADDR(addr) {rNFADDR=addr;}
#define NF_RSTECC() {rNFCONT|=(1<<4);}
#define NF_RDDATA() (rNFDATA)
#define NF_RDDATA8() ((*(volatile unsigned char*)0x4E000010) )
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_WRDATA8(data) {rNFDATA8=data;}
#define NFIsBusy() (!(rNFSTAT&1)) //whether nand flash is busy?
#define NFIsReady() (rNFSTAT&1) //whether nand flash is ready?
#define READCMD0 0 //Read0 model command == Page addr 0~127
#define READCMD1 1 //Read1 model command == Page addr 128~511
#define READCMD2 0x50 //Read2 model command == Page addr 512~527
#define READCMD3 0x30 //Read3 model for Large Page
#define ERASECMD0 0x60 //Block erase command 0
#define ERASECMD1 0xd0 //Block erase command 1
#define PROGCMD0 0x80 //page write command 0
#define PROGCMD1 0x10 //page write command 1
#define QUERYCMD 0x70 //query command
#define RdIDCMD 0x90 //read id command
#define RESETCMD 0xFF //reset command
// RnB Signal
#define NF_CLEAR_RB() {rNFSTAT |= (1<<2);} // Have write '1' to clear this bit.
#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));}
#define TACLS 0 // 1-clk(0ns)
#define TWRPH0 3 // 3-clk(25ns)
#define TWRPH1 0 // 1-clk(10ns) //TACLS+TWRPH0+TWRPH1>=50ns
#define OK 1
#define FAIL 0
#define ASM 1
#define C_LANG 2
#define DMA 3
#define TRANS_MODE 2
#define K9F1208_SUPPORT 1
#define K9F2G08_SUPPORT 2
volatile int NFConDone;
U8 Spare_Data_1208[16];
U8 Spare_Data_2G08[64];
U8 Nand_Selet;
static U8 se8Buf[16]={
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff
};
void __irq NFCon_Int(void);
void * nand_func[][2]=
{
(void *)Print_Id, "Read ID ",
(void *)Nand_Reset, "Nand reset ",
(void *)Test_Block_Erase, "Block erase ",
(void *)Test_Page_Read, "Page read ",
(void *)Test_Page_Write, "Page write ",
(void *)PrintBadBlockNum, "Check Badblock ",
0,0
};
void Test_Nand(void)
{
U8 ch;
U32 gpacon;
Uart_Printf("Nand test\n");
gpacon = rGPACON;
rGPACON = (rGPACON &~(0x3f<<17)) | (0x3f<<17);
// GPA 22 21 20 19 18 17
// nFCE nRSTOUT nFRE nFWE ALE CLE
Uart_Printf("Select Nand flash type, K9F1208(1)/K9F2G08(2) : ");
ch=Uart_Getch();
Uart_Printf("%c\n\n", ch);
switch(ch) {
case '1':
Nand_Selet = 1;
Test_K9F1208();
break;
case '2':
Nand_Selet = 2;
Test_K9F2G08();
break;
default:
break;
}
rGPACON = gpacon;
}
void Test_K9F1208(void)
{
// int i;
U8 i;
Uart_Printf("\nK9F1208(Small Page) Nand flash test start.\n");
InitNandFlash();
while(1)
{
PrintSubMessage();
Uart_Printf("\nSelect: ");
i = Uart_GetIntNum_GJ();
// Uart_Printf("i=%d\n",i);
if(i>=0 && (i<(sizeof(nand_func)/8)) )
( (void (*)(void)) (nand_func[i][0]) )(); // execute selected function.
else
Uart_Printf("\nWrong Num!\n");
}
}
void Test_K9F2G08(void)
{
// int i;
U8 i;
Uart_Printf("\nK9F2G08(Large Page) Nand flash test start.\n");
InitNandFlash();
while(1)
{
PrintSubMessage();
Uart_Printf("\nSelect: ");
i = Uart_GetIntNum_GJ();
// Uart_Printf("i=%d\n",i);
if(i>=0 && (i<(sizeof(nand_func)/8)) )
( (void (*)(void)) (nand_func[i][0]) )(); // execute selected function.
else
Uart_Printf("\nWrong Num!\n");
}
}
void PrintSubMessage(void)
{
int i;
i=0;
Uart_Printf("\n");
while(1)
{ //display menu
Uart_Printf("%2d:%s\n",i,nand_func[i][1]);
i++;
if((int)(nand_func[i][0])==0)
{
Uart_Printf("\n");
break;
}
}
}
static void InitNandCfg(void)
{
// for S3C2440
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
// TACLS [14:12] CLE&ALE duration = HCLK*TACLS.
// TWRPH0 [10:8] TWRPH0 duration = HCLK*(TWRPH0+1)
// TWRPH1 [6:4] TWRPH1 duration = HCLK*(TWRPH1+1)
// AdvFlash(R) [3] Advanced NAND, 0:256/512, 1:1024/2048
// PageSize(R) [2] NAND memory page size
// when [3]==0, 0:256, 1:512 bytes/page.
// when [3]==1, 0:1024, 1:2048 bytes/page.
// AddrCycle(R) [1] NAND flash addr size
// when [3]==0, 0:3-addr, 1:4-addr.
// when [3]==1, 0:4-addr, 1:5-addr.
// BusWidth(R/W) [0] NAND bus width. 0:8-bit, 1:16-bit.
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
// Lock-tight [13] 0:Disable lock, 1:Enable lock.
// Soft Lock [12] 0:Disable lock, 1:Enable lock.
// EnablillegalAcINT[10] Illegal access interupt control. 0:Disable, 1:Enable
// EnbRnBINT [9] RnB interrupt. 0:Disable, 1:Enable
// RnB_TrandMode[8] RnB transition detection config. 0:Low to High, 1:High to Low
// SpareECCLock [6] 0:Unlock, 1:Lock
// MainECCLock [5] 0:Unlock, 1:Lock
// InitECC(W) [4] 1:Init ECC decoder/encoder.
// Reg_nCE [1] 0:nFCE=0, 1:nFCE=1.
// NANDC Enable [0] operating mode. 0:Disable, 1:Enable.
// rNFSTAT = 0;
// Nand_Reset();
}
U16 Read_Status(void)
{
U16 stat;
int i;
NF_ChipEn();
NF_CMD(QUERYCMD);
for(i=0; i<10; i++);
stat = NF_RDDATA();
NF_ChipDs();
return stat;
}
//定义一个全局变量,生存期从此处开始到程序结束,在程序中使用,改变其值,然后
//可以使调用程序返回一个以上的值。
U8 Device=0;
U32 ReadChipId(void)
{
U32 id;
NF_ChipEn();
NF_CMD(RdIDCMD);
NF_ADDR(0);
while(NFIsBusy());
id = NF_RDDATA()<<24; //Maker Code 1
//PlaneNum = NF_RDDATA(); //PlaneNum 5
id |= NF_RDDATA()<<16; //Device Code
id |= NF_RDDATA()<<8; //Internal Chip Number, Cell Type, Number of Simultaneously Programmed Pages, Etc
id |= NF_RDDATA(); //Page Size , Block Size,Redundant Area Size, Organization, Serial Access Minimum
Device = NF_RDDATA();
NF_ChipDs();
return id;
}
void Print_Id(void)
{
U32 id;
U8 maker,chipNum, pageSize,PlaneNum;
id = ReadChipId();
pageSize = (U8)(id>>8);
chipNum = (U8)id;
PlaneNum = (U8)(id>>16);
maker = (U8)(id>>24);
//PlaneNum =
Uart_Printf("\nMaker:%x, Device:%x, Chipnum:%x, Pagesize:%x PlaneNum:%x\n", maker, Device,chipNum,pageSize,PlaneNum);
}
void Nand_Reset(void)
{
int i;
NF_ChipEn();
NF_CLEAR_RB();
NF_CMD(RESETCMD); //reset co
评论0