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

📄 nand.c

📁 2440超级bios(ads1.2 rvds2.2)通用
💻 C
字号:
/*
*******************************************************************************
* file name:	nand.c
* description:	nand driver
* author:		xzChen(chxzh123@163.com)
* QQ / msn:		36725175 / chxzh123@hotmail.com
*******************************************************************************
*/
#ifndef __NAND_C__
#define __NAND_C__

#include "Includes.h"

void Nand_Reset(void)
{                       
    NF_CE_L();
	NF_CLEAR_RB();
    NF_CMD(CMD_RESET);
    NF_CE_H();
}
void Nand_init(void)
{
    rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
    rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
    rNFSTAT = 0;
//    Nand_Reset();
}
void Nand_ReadID(void)
{
    USHORT  wData1,wData2;

    NF_CE_L();
	NF_CLEAR_RB();
    NF_CMD(CMD_READID);
    NF_ADDR(0x00);
//    NF_DETECT_RB();
    wData1 = (BYTE)NF_DATA_R();
    wData2 = (BYTE)NF_DATA_R();
    NF_CE_H();

    UartPutStr(SHL_PRT,"Nand Mfg: ");
    Uart_SendDWORD(SHL_PRT,(DWORD)wData1);
    UartPutStr(SHL_PRT,"Nand Dev: ");
    Uart_SendDWORD(SHL_PRT,(DWORD)wData2);
}

#ifdef READ_SECTOR_INFO
void NAND_ReadSectorInfo(SECTOR_ADDR sectorAddr,PSectorInfo pInfo)
{
    NF_CE_L();
	NF_CLEAR_RB();
    NF_CMD(CMD_READ2);
    NF_ADDR(0x00);
    NF_ADDR(sectorAddr & 0xff);
    NF_ADDR((sectorAddr >> 8) & 0xff);
    NF_ADDR((sectorAddr >> 16) & 0xff);
    NF_DETECT_RB();
    // Read the SectorInfo data (we only need to read first 8 bytes) 
    pInfo->dwReserved1  = (DWORD) ((BYTE) NF_DATA_R()) << 24;
    pInfo->dwReserved1 |= (DWORD) ((BYTE) NF_DATA_R()) << 16;
    pInfo->dwReserved1 |= (DWORD) ((BYTE) NF_DATA_R()) << 8;
    pInfo->dwReserved1 |= (DWORD) ((BYTE) NF_DATA_R());
    // OEM byte
    pInfo->bOEMReserved = (BYTE) NF_DATA_R();
    // Read the bad block mark
    pInfo->bBadBlock = (BYTE) NF_DATA_R();
    // Second reserved field (WORD)
    pInfo->wReserved2 = ((BYTE) NF_DATA_R() << 8);
    pInfo->wReserved2 |= ((BYTE) NF_DATA_R());
    NF_CE_H();
}
#endif

// 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
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;
    
    // BUGBUGBUG: I need to come back to support dwNumSectors > 1
    // Sanity check
    if (!pSectorBuff &&
    	!pSectorInfoBuff ||
    	dwNumSectors > 1 ||
    	!pSectorBuff)
    {
        UartPutStr(SHL_PRT,"ERROR_INVALID_PARAMETER\n");
        return FALSE;
    }

_retry:
    // Initialize ECC register
    NF_RSTECC();
	NF_MECC_UnLock();
    NF_nFCE_L();   
	NF_CLEAR_RB();
    NF_CMD(CMD_READ0);
    NF_ADDR(0x00);
    NF_ADDR((startSectorAddr) & 0xff);
    NF_ADDR((startSectorAddr >> 8) & 0xff);
    NF_ADDR((startSectorAddr >> 16) & 0xff);
    for (i = 0; i < 5; i++);	// wait tWB(100ns)
    NF_DETECT_RB();        		// wait tR(max 12us)
    __RdPage512(pSectorBuff);
    NF_MECC_Lock();
#if 	(LCD_TYPE == LTV350QVF04)
if (++len > 180)
{
  	len = 0;
  	if (progress < 320)
	{
		Glib_Line(progress,220,progress,240,0x001f);
    	progress++;
    }
    if (++p > 3)
    {
    	p = 0;
		gPrintf(140,222,0xFFFF,0,"%d%%",++pers);
    }
}
#elif 	(LCD_TYPE == MT502TML8B)
#endif
//	Delay(0x010000);
	// 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 )
    {
        UartPutStr(SHL_PRT,"FMD_ReadSector: ");
        Uart_SendDWORD(SHL_PRT,startSectorAddr);
        Nand_Reset();    
        for (i=0; i<5; i++);   // delay
        rc = TRUE;
        
        goto _retry;
    }   
	if(	ecc0 != eccRegVal.bECCBuf[0] ||
		ecc0 != eccRegVal.bECCBuf[0] ||
		ecc0 != eccRegVal.bECCBuf[0] )
		rc = FALSE;

    return rc;
}
U08 NF08_EraseBlk(U32 pNumber)
{
    U08 err;

    NF_nFCE_L();
    NF_CMD(CMD_ERASE0);
    NF_ADDR((U08)(pNumber&0xff));
    NF_ADDR((U08)((pNumber>>8)&0xff));   
    NF_ADDR((U08)((pNumber>>16)&0xff));
    NF_CMD(CMD_ERASE1);
    Delay(1);				//wait tWB(100ns)
    NF_WAITRB();
    NF_CMD(CMD_STATUS);
    if (NF_RDDATA()&0x1)	// Erase error
//		NF_MarkBadBlock(block);
    	err = FAIL;
    else
    	err = OK;
    NF_nFCE_H();
	
	return err;
}
U08 NF08_Page_R(U32 pStart,U08 *buf)
{
	U08 result;
	U32 i;
	UNION ecc,se[4];
    
	NF_RSTECC();
	NF_MECC_UnLock();
    NF_nFCE_L();
	NF_CLEAR_RB();
    NF_CMD(CMD_READ0);
    NF_ADDR(0);				//Column = 0
    NF_ADDR(pStart&0xff);
    NF_ADDR((pStart>>8)&0xff);
    NF_ADDR((pStart>>16)&0xff);
	Delay(1);				//wait tWB(100ns)
	NF_WAITRB();
   
    for(i=0; i<512; i++)
    	*buf++ = NF_RDDATA();
	NF_MECC_Lock();
	ecc.B32 = rNFMECC0;
    NF_nFCE_H();
    if(	(ecc.B08[0] == se[0].B08[0]) &&
    	(ecc.B08[1] == se[0].B08[1]) &&
    	(ecc.B08[2] == se[0].B08[2]))
		result = OK;
    else
		result = FAIL;
	
    return OK;
}
void NF08_Read(U32 pStart,U08 *buf,U32 len)
{
	U32 i,ipage,pagelen;
	
	ipage = pStart;
	pagelen	= (len + 512 - 1)/512;
	for (i=0; i<pagelen; i++)
	{
		if (NF08_Page_R(ipage,buf) == OK)
		{
			buf	+= 512;
			ipage++;
		}
		Delay(100);
	}
}

U08 NF08_Page_W(U32 pStart,U08 *buf)
{
    U32 i;
    U08 err;

    NF_nFCE_L();
    NF_CMD(CMD_READ0);
    NF_CMD(CMD_WRITE0);
    NF_ADDR(0x00);				//Column 0
    NF_ADDR(pStart&0xff);
    NF_ADDR((pStart>>8)&0xff);
    NF_ADDR((pStart>>16)&0xff);

    for(i=0; i<512; i++)
		NF_WRDATA(*buf++);
    NF_CMD(CMD_WRITE1);
    Delay(1);					// tWB = 100ns. 
    NF_WAITRB();
    NF_CMD(CMD_STATUS);
    Delay(1);					// twhr = 60ns
    if (NF_RDDATA()&0x1)		// Page write error
		err = FAIL;
    else
		err = OK;
    NF_nFCE_H();
    
    return err;
}
void NF08_Write(U32 pStart,U08 *buf,U32 len)
{
	U08 ipage;
	U32 i,pagelen;
	
	ipage	= pStart;
	pagelen	= (len + 512 - 1)/512;

	for (i=0; i<pagelen; i++)
	{
		if ((ipage%32) == 0)
		    NF08_EraseBlk(ipage);
		if (NF08_Page_W(ipage,buf) == OK)
		{
			buf	+= 512;
			ipage++;
		}
	}
}
int NF08_ChkBadBlk(U32 pStart)
{
    U08 data;
    U32 tmp;
    
//    blockPage=(block<<5);		// For 2'nd cycle I/O[7:5] 
    NF_nFCE_L();    
    NF_CMD(CMD_READ2);			// Spare array read command
    NF_ADDR(517&0xf);			// Read the mark of bad block in spare array(M addr=5) 
    NF_ADDR(pStart&0xff);		// The mark of bad block is in 0 page
    NF_ADDR((pStart>>8)&0xff);  // For block number A[24:17]
    NF_ADDR((pStart>>16)&0xff); // For block number A[25]
    Delay(1);		// wait tWB(100ns)
    NF_WAITRB();	// Wait tR(max 12us)
    data = NF_RDDATA();
    NF_nFCE_H();    
    if(data != 0xff)
    {
    	tmp = pStart>>5;
		UartPrintf(SHL_PRT,"\r\n[block %d:bad block(%x)]",tmp,data);
    	return 1;
    }
    else
    {
		UartPrintf(SHL_PRT,".");
    	return 0;
    }
}
int NF08_MarkBadBlk(U32 pStart)
{
    NF_nFCE_L(); 
	NF_CLEAR_RB();
    NF_CMD(CMD_READ2);   
    NF_CMD(CMD_WRITE0);
    NF_ADDR(517&0xf);
    NF_ADDR(pStart&0xff);		// marked 5th spare array 
    NF_ADDR((pStart>>8)&0xff);	// in the 1st page.
    NF_ADDR((pStart>>16)&0xff);  
	NF_WRDATA(BADBLKMARK);		// Write spare array
    NF_CMD(CMD_WRITE1);			// Write 2nd command
	Delay(1);  					// tWB = 100ns.
	NF_DETECT_RB();				// Wait tR(max 12us)
//    NF_WAITRB();      		// Wait tPROG(200~500us)
    NF_CMD(CMD_STATUS);
    if (NF_RDDATA()&0x1)		// Spare arrray write error
    {	
    	NF_nFCE_H();
//    	printf("[Program error is occurred but ignored]\n");
    }
    else 
    	NF_nFCE_H();
//    printf("[block #%d is marked as a bad block]\n",block);
    return 1;
}

DWORD ReadImageFromNand(DWORD dwEntry, DWORD dwSig)
{
	DWORD dwSectorsNeeded;
	DWORD dwSector,dwLength;	// Start Sector & Length
	DWORD dwRAM,i;

	// TOC_SECTOR = 32
	if ( !FMD_ReadSector(TOC_SECTOR,(LPBYTE)&toc,NULL, 1) )
	{
        UartPutStr(SHL_PRT,"ERR_DISK_OP_FAIL1\n");
        return ERR_DISK_OP_FAIL1;
    }

    if ( !VALID_TOC(&toc) )
    {
        UartPutStr(SHL_PRT,"ERR_INVALID_TOC: ");
        Uart_SendDWORD(SHL_PRT,toc.dwSignature);
        return ERR_INVALID_TOC;
    }

    if ( !(toc.id[dwEntry].dwImageType & IMAGE_TYPE_RAMIMAGE) )
    {
        UartPutStr(SHL_PRT,"ERR_INVALID_FILE_TYPE: ");
        Uart_SendDWORD(SHL_PRT,toc.id[dwEntry].dwImageType);
        return ERR_INVALID_FILE_TYPE;
    }
// ??
//    if ( !(toc.id[dwEntry].dwImageType & IMAGE_TYPE_BINFS) ) {
//        dwSectorsNeeded = toc.id[dwEntry].dwTtlSectors;
//    } else {
        dwSectorsNeeded = toc.id[dwEntry].dwTtlSectors;		// xipkernel size = 0x9B4
//    }
    dwRAM    = VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);
    JumpAddr = toc.id[0].dwJumpAddress ?
    				VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwJumpAddress):
                    VIRTUAL_TO_PHYSICAL(toc.id[dwEntry].dwLoadAddress);
    // Load the disk image directly into RAM
    // BUG: recover from read failures
	i = 0;
	while (dwSectorsNeeded && i < MAX_SG_SECTORS)  // 14
	{
		dwSector = toc.id[dwEntry].sgList[i].dwSector;
		dwLength = toc.id[dwEntry].sgList[i].dwLength;
        // read each sg segment
		while (dwLength)
		{
			if ( !FMD_ReadSector(dwSector,(LPBYTE)dwRAM,NULL,1) )
			{
				dwSector++;
				continue;
            }
    		dwSector++;
    		dwLength--;
			dwRAM += SECTOR_SIZE;
        }
        dwSectorsNeeded -= toc.id[dwEntry].sgList[i].dwLength;
        i++;
    }
	return 1 ;// ERR_SUCCESS; 
}

#endif

⌨️ 快捷键说明

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