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

📄 nand.c

📁 Embest IDE下s3c2440的测试工程
💻 C
📖 第 1 页 / 共 4 页
字号:

	NF_CMD(0x70);   // Read status command   
    
	for(i=0;i<3;i++);  //twhr=60ns
    
       if (NF_RDDATA()&0x1) {// Page write error
    	       NF_nFCE_H();
		Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);
		NF8_MarkBadBlock(block);
		return FAIL;
       } else {
    	      NF_nFCE_H();
	      return OK;
	}
#elif ID_NAND == ID_K9K8G08U0A
	blockPage=(block<<6)+page;

	NF_nFCE_L(); 
	NF_CMD(0x0);//??????
	NF_CMD(0x80);   // Write 1st command
	NF_ADDR(0); 	// Column = 0
	NF_ADDR(0);			    // Column 0
	NF_ADDR(blockPage&0xff);	    //
	NF_ADDR((blockPage>>8)&0xff);   // Block & page num.
	NF_ADDR((blockPage>>16)&0xff);

 	for(i=0;i<2048;i++) {
		NF_WRDATA8(*bufPt++);	// Write one page to NFM from buffer
    }


       NF_MECC_Lock();
	// Get ECC data.
	// Spare data for 8bit
	// byte  0     1    2     3     4          5               6      7            8         9
	// ecc  [0]  [1]  [2]  [3]    x   [Bad marking]                    SECC0  SECC1
	Mecc = rNFMECC0;
	se8Buf[0]=(U8)(Mecc&0xff);
	se8Buf[1]=(U8)((Mecc>>8) & 0xff);
	se8Buf[2]=(U8)((Mecc>>16) & 0xff);
	se8Buf[3]=(U8)((Mecc>>24) & 0xff);
	se8Buf[5]=0xff;		// Marking good block

	NF_SECC_UnLock();
	//Write extra data(ECC, bad marking)
	for(i=0;i<4;i++) {
		NF_WRDATA8(se8Buf[i]);	// Write spare array(Main ECC)
		NF8_Spare_Data[i]=se8Buf[i];
    	}  
      NF_SECC_Lock(); 
	Secc=rNFSECC; 
	se8Buf[8]=(U8)(Secc&0xff);
	se8Buf[9]=(U8)((Secc>>8) & 0xff);
	for(i=4;i<64;i++) {
		NF_WRDATA8(se8Buf[i]);  // Write spare array(Spare ECC and Mark)
		NF8_Spare_Data[i]=se8Buf[i];
	}  
 	NF_CLEAR_RB();
	NF_CMD(0x10);	 // Write 2nd command
#if USE_NFINIT
	while(NFConDone==0);
	 rNFCONT&=~(1<<9);
	 rNFCONT&=~(1<<10); // Disable Illegal Access Interrupt
#else
	NF_DETECT_RB();
#endif
	if(rNFSTAT&0x8) return FAIL;		// soft lock or tight lock

	NF_CMD(0x70);   // Read status command   
    
	for(i=0;i<3;i++);  //twhr=60ns
    
       if (NF_RDDATA()&0x1) {// Page write error
    	       NF_nFCE_H();
		Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);
		NF8_MarkBadBlock(block);
		return FAIL;
       } else {
    	      NF_nFCE_H();
	      return OK;
	}
#elif ID_NAND == ID_K9S1208V0M
	blockPage=(block<<5)+page;

	NF_nFCE_L(); 
	NF_CMD(0x0);//??????
	NF_CMD(0x80);   // Write 1st command
	NF_ADDR(0);			    // Column 0
	NF_ADDR(blockPage&0xff);	    //
	NF_ADDR((blockPage>>8)&0xff);   // Block & page num.
	NF_ADDR((blockPage>>16)&0xff);  //

	
#if TRANS_MODE==C_LANG
     
	for(i=0;i<512;i++) {
		NF_WRDATA8(*bufPt++);	// Write one page to NFM from buffer
    }
#elif TRANS_MODE==DMA
      
	// Memory to Nand dma setting
	rSRCPND=BIT_DMA0;	// Init DMA src pending.
	rDISRC0=(unsigned)bufPt; 	// Nand flash data register
	rDISRCC0=(0<<1) | (0<<0); //arc=AHB,src_addr=inc
	rDIDST0=NFDATA;
	rDIDSTC0=(0<<1) | (1<<0); //dst=AHB,dst_addr=fix;
	rDCON0=(1<<31)|(1<<30)|(1<<29)|(0<<28)|(1<<27)|(0<<23)|(1<<22)|(2<<20)|(512/4);
	//  only unit transfer in writing!!!!
	//Handshake,AHB,interrupt,(unit),whole,S/W,no_autoreload,word,count=128;
	
	// DMA on and start.
	rDMASKTRIG0=(1<<1)|(1<<0);
	
	while(!(rSRCPND & BIT_DMA0));	// Wait until Dma transfer is done.
	rSRCPND=BIT_DMA0;	
#endif

       NF_MECC_Lock();
	// Get ECC data.
	// Spare data for 8bit
	// byte  0     1    2     3     4          5               6      7            8         9
	// ecc  [0]  [1]  [2]  [3]    x   [Bad marking]                    SECC0  SECC1
	Mecc = rNFMECC0;
	se8Buf[0]=(U8)(Mecc&0xff);
	se8Buf[1]=(U8)((Mecc>>8) & 0xff);
	se8Buf[2]=(U8)((Mecc>>16) & 0xff);
	se8Buf[3]=(U8)((Mecc>>24) & 0xff);
	se8Buf[5]=0xff;		// Marking good block

	NF_SECC_UnLock();
	//Write extra data(ECC, bad marking)
	for(i=0;i<4;i++) {
		NF_WRDATA8(se8Buf[i]);	// Write spare array(Main ECC)
		NF8_Spare_Data[i]=se8Buf[i];
    	}  
      NF_SECC_Lock(); 
	Secc=rNFSECC; 
	se8Buf[8]=(U8)(Secc&0xff);
	se8Buf[9]=(U8)((Secc>>8) & 0xff);
	for(i=4;i<16;i++) {
		NF_WRDATA8(se8Buf[i]);  // Write spare array(Spare ECC and Mark)
		NF8_Spare_Data[i]=se8Buf[i];
	}  
 	NF_CLEAR_RB();
	NF_CMD(0x10);	 // Write 2nd command
#if  USE_NFINIT
	while(NFConDone==0);
	 rNFCONT&=~(1<<9);
	 rNFCONT&=~(1<<10); // Disable Illegal Access Interrupt
#else
	NF_DETECT_RB();
#endif

	if(rNFSTAT&0x8) return FAIL;

	NF_CMD(0x70);   // Read status command   
    
	for(i=0;i<3;i++);  //twhr=60ns
    
       if (NF_RDDATA()&0x1) {// Page write error
    	       NF_nFCE_H();
		Uart_Printf("[PROGRAM_ERROR:block#=%d]\n",block);
		NF8_MarkBadBlock(block);
		return FAIL;
       } else {
    	      NF_nFCE_H();
	      return OK;
	}

#endif
}

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


void Nand_Reset(void)
{
    int i;
   
	NF_nFCE_L();

	NF_CLEAR_RB();
	NF_CMD(0xFF);	//reset command
	for(i=0;i<10;i++);  //tWB = 100ns. //??????
	NF_DETECT_RB();
	
	NF_nFCE_H();

}

void NF8_Init(void)
{
	// for S3C2440

#if ID_NAND == ID_K9F1G08U0A
	rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(1<<3)|(1<<2)|(0<<0);	
#elif ID_NAND == ID_K9K8G08U0A
	rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(1<<3)|(1<<2)|(1<<1)|(0<<0);	
#elif ID_NAND == ID_K9S1208V0M
	rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);	
#endif
	// 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();
}
/*
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
    SECTOR_ADDR sectorAddr = blockID << 6;
    SectorInfo SI;
    DWORD dwResult = 0;

	if(!FMD_ReadSector(sectorAddr, NULL, &SI, 1))
	{
        return BLOCK_STATUS_UNKNOWN;
	}

    if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
	{
        dwResult |= BLOCK_STATUS_READONLY;
	}

    if(SI.bBadBlock != 0xFF)
	{
        dwResult |= BLOCK_STATUS_BAD;
	}

    return dwResult;
}
*/
//  FMD_ReadSector
//
//  Read the content of the sector.
//
//  startSectorAddr: Starting page address
//  pSectorBuff  : Buffer for the data portion
//  pSectorInfoBuff: Buffer for Sector Info structure
//  dwNumSectors : Number of sectors
//

#if 0
BOOL 
FMD_ReadSector(
    SECTOR_ADDR startSectorAddr, 
    LPBYTE pSectorBuff,
    PSectorInfo pSectorInfoBuff, 
    DWORD dwNumSectors
    )
{
    DWORD   i, r = 0;
    BYTE   ecc0,ecc1,ecc2;
    BOOL   rc = TRUE;
    ECCRegVal eccRegVal;

    if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1 || !pSectorBuff) {
        Uart_Printf("ERROR_INVALID_PARAMETER\n");
        return FALSE;
    }

_retry:
    //  Initialize ECC register
    NF_RSTECC();
	NF_MECC_UnLock();

    //  Enable the chip
    NF_nFCE_L();   
	NF_CLEAR_RB();

    // Issue Read command
    NF_CMD(0x00);

    //  Set up address
    NF_ADDR(0x00);
    NF_ADDR(0x00);
    NF_ADDR((startSectorAddr) & 0xff);
    NF_ADDR((startSectorAddr >> 8) & 0xff);
#if ID_NAND == ID_K9K8G08U0A
    NF_ADDR((startSectorAddr>>16) &0xff);
#endif
    NF_CMD(0x30);	// Read command 2nd

    NF_DETECT_RB();        // wait tR(max 12us)

    // read the data
    __RdPage2048(pSectorBuff);
//    __RdPage256(pSectorBuff);
	NF_MECC_Lock();

//	for ( i = 0; i < 2048; i++ )
//		Uart_SendByte(*(pSectorBuff+i));

//
	//	Read the ECC from ECC Register
	eccRegVal.dwECCVal = NF_ECC();

	//	Skip first 8 bytes
	for(i=0; i<8; i++){
		ecc0 = (BYTE)NF_DATA_R();
	}
	
	ecc0 = (BYTE)NF_DATA_R();
	ecc1 = (BYTE)NF_DATA_R();
	ecc2 = (BYTE)NF_DATA_R();
	
    NF_nFCE_H();

    if ( !rc && r++ < 3 ) {
        Uart_Printf("FMD_ReadSector: ");
		Uart_Printf("startSectorAddr = %x \n",startSectorAddr);

        Nand_Reset();
        
        for (i = 0; i < 5; i++);   // delay

        rc = TRUE;
        
        goto _retry;
    }
    
    if ( startSectorAddr < 0x120 ) // NO ECC Check about EBOOT
    {
    	rc = TRUE;
    }
    else
    {
//	if(	ecc0 != eccRegVal.bECCBuf[0] ||
//		ecc0 != eccRegVal.bECCBuf[0] ||
//		ecc0 != eccRegVal.bECCBuf[0] )  {
//		Uart_Printf("ECC mismatch for Sector: ");
//		Uart_Printf("startSectorAddr = %x \n",startSectorAddr);
		rc = TRUE;//FALSE;
//	}
    }

    return rc;
}

BOOL NAND_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo)
{
    BOOL    bRet = TRUE;

//	RETAILMSG(1, (TEXT("FlashDrv!FMD!NAND_WriteSectorInfo:  \r\n")));

    //  Chip enable
    NF_nFCE_L();
	NF_CLEAR_RB();

    //  Write the command
    //  First, let's point to the spare area
//    NF_CMD(CMD_READ2);
    NF_CMD(CMD_WRITE);

    //  Write the address
    NF_ADDR(2048&0xFF);
    NF_ADDR((2048>>8)&0xFF);
    NF_ADDR(sectorAddr & 0xff);
    NF_ADDR((sectorAddr >> 8) & 0xff);
    NF_ADDR((sectorAddr>>16)&0xff);

//    if (NEED_EXT_ADDR) {
//        NF_ADDR((sectorAddr >> 16) & 0xff);
//    }

    //  Now let's write the SectorInfo data
    //
    //  Write the first reserved field (DWORD)
    NF_DATA_W4( pInfo->dwReserved1 );

    //  Write OEM reserved flag
    NF_DATA_W( (pInfo->bOEMReserved) );

    //  Write the bad block flag
    NF_DATA_W( (pInfo->bBadBlock) );

    //  Write the second reserved field
    NF_DATA_W( (pInfo->wReserved2 >> 8) & 0xff );
    NF_DATA_W( (pInfo->wReserved2) );

    //  Issue the write complete command
    NF_CMD(CMD_WRITE2);

    //  Check ready bit
	NF_DETECT_RB();	 // Wait tR(max 12us)

    //  Check the status of program
    NF_CMD(CMD_STATUS);

    if(NF_DATA_R() & STATUS_ERROR) {
        Uart_Printf("NAND_WriteSectorInfo() ######## Error Programming page %d!\n", sectorAddr);
        bRet = FALSE;
    }

    NF_nFCE_H();
    return bRet;
}

BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff,
                        DWORD dwNumSectors)
{
    DWORD   i;
    BOOL    bRet = TRUE;
    DWORD   dwECCVal;
    BYTE    eccBuf[4];

    if((!pSectorBuff && !pSectorInfoBuff) || dwNumSectors != 1) {
        Uart_Printf("Invalid parameters!\r\n");
        return FALSE;
    }

	Nand_Reset();

    if(!pSectorBuff) {
        //  If we are asked just to write the SectorInfo, we will do that separately
        bRet = NAND_WriteSectorInfo(startSectorAddr, pSectorInfoBuff);
		return bRet;			// Do not write the actual sector information...
    }

    //  Initialize ECC register
    NF_RSTECC();
	NF_MECC_UnLock();

    //  Enable Chip
    NF_nFCE_L();

    //  Issue command
    NF_CMD(CMD_READ);
    NF_CMD(CMD_WRITE);

    //  Setup address
    NF_ADDR(0x00);
    NF_ADDR(0x00);
    NF_ADDR((startSectorAddr) & 0xff);
    NF_ADDR((startSectorAddr >> 8) & 0xff);
    NF_ADDR((startSectorAddr >> 16) & 0xff);
//    if (NEED_EXT_ADDR) {
//        NF_ADDR((startSectorAddr >> 16) & 0xff);
//    }

    //  Special case to handle un-aligned buffer pointer.
    //
    if( ((DWORD) pSectorBuff) & 0x3) {
        //  Write the data
        for(i=0; i<SECTOR_SIZE; i++) {
            NF_DATA_W(pSectorBuff[i]);
        }
    }
    else {
        __WritePage2048(pSectorBuff, pNFDATA);
    }

    //  Read out the ECC value generated by HW
	NF_MECC_Lock();
    dwECCVal = NF_ECC();

	// Write the SectorInfo data to the media
	// NOTE: This hardware is odd: only a byte can be written at a time and it must reside in the
	//       upper byte of a USHORT.
	if(pSectorInfoBuff)
	{
        //  Write the first reserved field (DWORD)
        NF_DATA_W4(pSectorInfoBuff->dwReserved1);

        //  Write OEM reserved flag
        NF_DATA_W( (pSectorInfoBuff->bOEMReserved) );

        //  Write the bad block flag
        NF_DATA_W( (pSectorInfoBuff->bBadBlock) );

        //  Write the second reserved field
        NF_DATA_W( (pSectorInfoBuff->wReserved2 >> 8) & 0xff );
        NF_DATA_W( (pSectorInfoBuff->wReserved2) & 0xff );

	}else
	{
		// Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
		for(i=0; i<sizeof(SectorInfo); i++)
		{
            NF_DATA_W(0xff);
		}
	}

    //  ECC stuff should be here
    eccBuf[0] = (BYTE) ((dwECCVal) & 0xff);
    eccBuf[1] = (BYTE) ((dwECCVal >> 8) & 0xff);
    eccBuf[2] = (BYTE) ((dwECCVal >> 16) & 0xff);

    //  Write the ECC value to the flash
    for(i=0; i<3; i++) {
        NF_DATA_W(eccBuf[i]);
    }

    for(i=0; i<5; i++) {
        NF_DATA_W(0xff);
    }

	NF_CLEAR_RB();
    //  Finish up the write operation
    NF_CMD(CMD_WRITE2);

    //  Wait for RB
	NF_DETECT_RB();	 // Wait tR(max 12us)

    //  Check the status
    NF_CMD(CMD_STATUS);

    if(NF_DATA_R() & STATUS_ERROR) {

        Uart_Printf("FMD_WriteSector() ######## Error Programming page %d!\n", startSectorAddr);

        bRet = FALSE;
    }

    //  Disable the chip
    NF_nFCE_H();
    return bRet;
}
#endif

⌨️ 快捷键说明

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