Chinaunix首页 | 论坛 | 博客
  • 博客访问: 344860
  • 博文数量: 92
  • 博客积分: 2500
  • 博客等级: 少校
  • 技术积分: 960
  • 用 户 组: 普通用户
  • 注册时间: 2009-08-21 19:38
文章分类

全部博文(92)

文章存档

2010年(71)

2009年(21)

我的朋友

分类: 嵌入式

2010-06-19 20:41:44

S3C2440存储单元-----K9F2G08 NAND FLASH文档

  

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,

};

 

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_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;

           }

       }

}

 

初始化NAND FLASH仅仅是做最简单的配置,通过#define的形式

static void InitNandCfg(void)

{

       // for S3C2440

       rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);

       //Nand Flash configuration Register,主要配置三个时序

 

       rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);

       //Nand Flash control Register

}

#define    EnNandFlash()       (rNFCONF |= (1<<0))  //bit0=1 enable NAND flash controller

#define    DsNandFlash()       (rNFCONF &= ~(1<<0)) //bit0=1 disable NAND flash controller

#define    InitEcc()        (rNFCONT |= (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);}

 

//Nand Flash Command Register(NFCMMD)

#define NF_CMD(cmd)               {rNFCMD=cmd;}

 

 

#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

这里的设置是根据K9F2G08UXA开发手册:

 

 

//Nand Flash Data Register,(这个寄存器只用低8位)

#define NF_RDDATA()               (rNFDATA)

 

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;

}

1 擦除操作

static int EraseBlock_2G08(U32 block)

{

       U32 blockPage=(block<<5);

    int i;

 

//启动NAND FLASH 中断

    NFConDone=0;

    rNFCONT|=(1<<9);

    rNFCONT|=(1<<10);

    pISR_NFCON= (unsigned)NFCon_Int;

    rSRCPND=BIT_NFCON;

    rINTMSK=~(BIT_NFCON);

      

#if BAD_CHECK

    if(IsBadBlock_2G08(block))

       return FAIL;

#endif

 

       NF_ChipEn();

   

       NF_CMD(ERASECMD0);       

// Erase one block 1st command, Block Addr:A9-A252048Blocks

       // Address 3-cycle

       NF_ADDR(blockPage&0xff);           // Page number=0

       NF_ADDR((blockPage>>8)&0xff);  

       NF_ADDR((blockPage>>16)&0xff);

 

 

       NF_CLEAR_RB();

       NF_CMD(ERASECMD1);           // Erase one blcok 2nd command

    while(NFConDone==0);

       rNFCONT&=~(1<<9);

       rNFCONT&=~(1<<10); // Disable Illegal Access Interrupt

       if(rNFSTAT&0x8)

              return FAIL;

 

       NF_CMD(QUERYCMD);   // Read status command状态被放到rNFDATA

 

    if (NF_RDDATA()&0x1) // Erase error

    {    

           NF_ChipDs();

              Uart_Printf("[ERASE_ERROR:block#=%d]\n",block);

//     MarkBadBlock_1208(block);

              return FAIL;

    }

    else

    {

           NF_ChipDs();

              return OK;

    }

}

 

2 读操作

static int ReadPage_2G08(U32 block,U32 page,U8 *buffer)

{

    int i;

    unsigned int blockPage;

       U32 Mecc, Secc;

       U8 *bufPt=buffer;

       U8 se[64], ecc0, ecc1, ecc2, ecc3,a,b,c,d,e;

   

    blockPage=(block<<5)+page;

       NF_RSTECC();    // Initialize ECC

       NF_MECC_UnLock();

   

       NF_ChipEn();   

 

       NF_CLEAR_RB();

       NF_CMD(READCMD0);     // Read command

       NF_ADDR(0);      // Column = 0

       NF_ADDR(0);

       NF_ADDR(blockPage&0xff);              //

       NF_ADDR((blockPage>>8)&0xff);     // Block & Page num.

       NF_ADDR((blockPage>>16)&0xff);    //

      

       NF_CMD(READCMD3);

       NF_DETECT_RB();

        

      

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

       {

              *bufPt++=NF_RDDATA8(); // Read one page,2k大小

       }

}

阅读(3650) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~