⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 nand_mini.c

📁 由三星的2442修改而来,正确引导eboot,请注意用三星公版的硬件配置,具体可以参考QQ2440,因为我在些平台上跑过,具体操作 1.target settings : post-linker:选
💻 C
字号:
//====================================================================
// File Name : Nand.c
// Function  : S3C2442 8-bit interface Nand Test program(this program use K9k2g16.c).
// Date      : May xx, 2003
// Version   : 0.0
// History
//   R0.0 (200305xx): Modified for 2442 from 2410. -> DonGo
//====================================================================


/**************** K9s1206 NAND flash ********************/
// 1block=(512+16)bytes x 32pages
// 4096block
// Block: A[23:14], Page: [13:9]
/**************** K9K2G16 NAND flash *******************/
// 1block=(2048+64)bytes x 64pages
// 2048block
// Block: A[23:14], page: [13:9]
/*****************************************************/

#include <string.h>
#include <stdlib.h>
#include "def.h"
#include "option.h"
#include "2442addr.h"
#include "2442lib.h"
#include "2442slib.h" 

#include "Nand.h"
//#include "k9k2g16.h" 

#define ASM		1
#define C_LANG	2
#define DMA		3
#define TRANS_MODE 2



//*************************************************
//*************************************************
//**           H/W dependent functions           **
//************************************************* 
//*************************************************

//The code is made for bi-endian mode

// block0: reserved for boot strap
// block1~4095: used for OS image
// badblock SE: xx xx xx xx xx 00 ....
// good block SE: ECC0 ECC1 ECC2 FF FF FF ....
#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_nFCE_L()      {rNFCONT &= ~(1<<1);}
#define NF_nFCE_H()      {rNFCONT |= (1<<1);}
#define NF_RSTECC()      {rNFCONT |= (1<<4);}
#define NF_RDDATA() 	    (rNFDATA)
#define NF_RDDATA8() 	 (rNFDATA8)
#define NF_WRDATA(data)  {rNFDATA=data;}
#define NF_WRDATA8(data) {rNFDATA8=data;}

#define NF_WAITRB()      {while(!(rNFSTAT&(1<<2)));} 
#define NF_CLEAR_RB() {rNFSTAT |= (1<<2);}	
#define NF_DETECT_RB(){while(!(rNFSTAT&(1<<2)));}


#define ID_K9S1208V0M	   0xec76
#define ID_K9K2G16U0M	   0xecca



#define TACLS		3	// 1-clk(0ns) 
#define TWRPH0		7	// 3-clk(25ns)
#define TWRPH1		7	// 1-clk(10ns)  //TACLS+TWRPH0+TWRPH1>=50ns


 

#if 0
U16 NF8_CheckId(void)
{
   int i;
	U16 id, id4th;

	NF_nFCE_L();
	
  	NF_CMD(0x90);
	NF_ADDR(0x0);
	for (i=0; i<10; i++);
//	Uart_Printf("NFSTAT: 0x%x\n", rNFSTAT);
   id  = NF_RDDATA8()<<8;	// Maker code 0xec
   id |= NF_RDDATA8();	// Devide code(K9S1208V:0x76), (K9K2G16U0M:0xca)

	NF_nFCE_H();
	
   return id;
}
#endif



 int NF8_IsBadBlock(U32 block)
{
    int i;
    unsigned int blockPage;
	U8 data;
    
    
    	blockPage=(block<<5);	// For 2'nd cycle I/O[7:5] 
    
	NF_nFCE_L();
	NF_CLEAR_RB();

	NF_CMD(0x50);		 // Spare array read command
	NF_ADDR((512+5)&0xf);		 // Read the mark of bad block in spare array(M addr=5), A4-A7:Don't care

	NF_ADDR(blockPage&0xff);	 // The mark of bad block is in 0 page
	NF_ADDR((blockPage>>8)&0xff);	 // For block number A[24:17]
	NF_ADDR((blockPage>>16)&0xff);  // For block number A[25]
	 
	NF_DETECT_RB();	 // Wait tR(max 12us)

   	 data=NF_RDDATA();

	NF_nFCE_H();    

    if(data!=0xff) 	return FAIL;
    else  	return OK;
    
}



// 1block=(512+16)bytes x 32pages
// 4096block

// A[23:14][13:9]
//  block   page

int NF_ReadPage(U32 block,U32 page,U8 *buffer)
{
    int i;
    register U8 * bufPt=buffer;
    unsigned int blockPage;
    U8 ecc0,ecc1,ecc2;
    U32 Mecc, Secc;
    U8 se[16];	   
    
    //page=page&0x1f;
    blockPage=(block<<5)+page;
    NF_RSTECC();    // Initialize ECC
    NF_MECC_UnLock();
    NF_nFCE_L();    
    NF_CLEAR_RB();
    NF_CMD(0x00);     // Read command
    NF_ADDR(0);	    // Column = 0
    NF_ADDR(blockPage&0xff);	      //
    NF_ADDR((blockPage>>8)&0xff);   // Block & Page num.
    NF_ADDR((blockPage>>16)&0xff);  //
    NF_DETECT_RB();

    for (i=512; i; i--) {
      *bufPt++ = NF_RDDATA8();
    }

    NF_MECC_Lock();
    Mecc = rNFMECC0;
    ecc0 = (U8)(Mecc & 0xff);
    ecc1 = (U8)((Mecc>>8) & 0xff);
    ecc2 = (U8)((Mecc>>16) & 0xff);

    for (i=0; i<16; i++) {
      se[i] = NF_RDDATA8();
    }
    
    NF_nFCE_H();

    if (ecc0==se[0] && ecc1==se[1] && ecc2==se[2])
      return 1;

    //Uart_Printf("ECC FAIL!\n");
    return 0;
   
    
}


int NF_IsBadBlock(U32 block)
{
    int i;
    unsigned int blockPage;
    U8 data;
    
    
    blockPage=(block<<5);	// For 2'nd cycle I/O[7:5] 
    
    NF_nFCE_L();    
    NF_CLEAR_RB();
    NF_CMD(0x50);		// Spare array read command
    NF_ADDR(517&0xf);		// Read the mark of bad block in spare array(M addr=5) 
    NF_ADDR(blockPage&0xff);	// The mark of bad block is in 0 page
    NF_ADDR((blockPage>>8)&0xff);   // For block number A[24:17]
    NF_ADDR((blockPage>>16)&0xff);  // For block number A[25]
    
    NF_WAITRB();	// Wait tR(max 12us)
    
    data=NF_RDDATA();

    NF_nFCE_H();    

    if(data!=0xff)
    {
    	//Uart_Printf("[block %d has been marked as a bad block(%x)]\n",block,data);
    	return 0;
    }
    else
    {
    	return 1;//ok
    }
}



void NF_Reset(void)
{
    int i;   
    
    NF_nFCE_L();
    NF_CLEAR_RB();
    NF_CMD(0xFF);	//reset command

    for(i=0;i<10;i++);  //tWB = 100ns. 

    NF_WAITRB();      //wait 200~500us;
     
    NF_nFCE_H();
}



void NF_Init(void)
{
    //rNFCONF=(1<<15)|(1<<14)|(1<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);	
    // 1  1    1     1,   1      xxx,  r xxx,   r xxx        
    // En 512B 4step ECCR nFCE=H tACLS   tWRPH0   tWRPH1
    rNFCONF = (3<<12) | (7<<8) | (7<<4);
    rNFCONT = (1<<4) | (1<<0);
    rNFSTAT = 0x04;
    NF_Reset();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -