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

📄 nand.c

📁 Sirf/Centrality公司GPS平台AtlasIII芯片AT640的Nboot源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				// Merge 16bits UUID data
				if (i%2)
				{
					pDriverGlobals->dwUUID[i/2] |= (((dwRead & 0xff) | ((dwRead & 0xff0000)>>8)) << 16);
				}
				else
				{
					pDriverGlobals->dwUUID[i/2] = (dwRead & 0xff) | ((dwRead & 0xff0000)>>8);
				}
			}
			if (i>=g_FlashExtInfo.fi.wDataBytesPerSector/4 && i <=g_FlashExtInfo.fi.wDataBytesPerSector/4+1)
			{
				if (i%2)
					dwSig |= (((dwRead & 0xff) | ((dwRead & 0xff0000)>>8)) << 16);
				else
					dwSig = (dwRead & 0xff) | ((dwRead & 0xff0000)>>8);
			}
		}
		else
		{
			if (i<8)
			{
				pDriverGlobals->dwUUID[i] = dwRead;
#if 0
				NandDbgPutString("\r\n &(pDriverGlobals->dwUUID)=");
				NandDbgPutHex((int)(pDriverGlobals->dwUUID));
				NandDbgPutString("\r\nUUID");
				NandDbgPutHex(pDriverGlobals->dwUUID[i]);
				NandDbgPutHex(dwRead);
#endif
			}
			if (i==g_FlashExtInfo.fi.wDataBytesPerSector/4)
				dwSig = dwRead;
		}
	}

	if (0xaa55aa55 != dwSig)
	{
		pDriverGlobals->dwUUID[8]=0x00;
		NandDbgPutString("\r\nUUID ERR!");
//		NandDbgPutHex(dwSig);
		goto ERREXIT;
	}

	for (i=4;i<8; i++)
	{
		if(pDriverGlobals->dwUUID[i]+pDriverGlobals->dwUUID[i-4]+1)
		{
		    pDriverGlobals->dwUUID[8]=0x00;
		    NandDbgPutString("UUID C ERR!\r\n");
		    goto ERREXIT;
		}
	}
	pDriverGlobals->dwUUID[8]=0xF1;

ERREXIT:
	NF_CMD(SMDF_CMD_RESET);
}
#endif

/*-----------------------------------------------------------------------------
 *  FMD Interface functions
 *
 *----------------------------------------------------------------------------*/

//  FMD_Init
//  
//  Initialize the flash chip
//
void FMD_Init(void)
{
	// Read UUID here
//	FMDReadUUID();

	//  Issue a reset command here
	FMDInitHardware();
	FMDReadFlashID();
	PROTECT_NAND();
	g_SI.bBadBlock = BADBLOCKMARK;
	g_SI.bOEMReserved = OEM_RESERVED_BLOCK;
	g_SI.dwReserved1 = 0;
	g_SI.wReserved2 = 0;
}

BOOL FMDReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pSectorInfoBuff)
{
	NF_STOP_FIFO();
	NF_IO_RD_MODE();
	NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
	NF_LEN(g_FlashExtInfo.wSpareDataLength/2);
	NF_FIFO_THRD(g_FlashExtInfo.wSpareDataLength/2);
	FMDSetAddress (sectorAddr,
				   g_FlashExtInfo.fi.wDataBytesPerSector,
				   0);

	//the FIFO threshold interrupt should be cleared 
	//just before write NandFlash command
	NF_CLR_INT(SMDF_FIFO_INT);
	NF_CMD(SMDF_CMD_READ2);
	NF_START_FIFO();

	NF_WAIT_INT(SMDF_FIFO_INT);

	FMDReadFifo ((PDWORD)pSectorInfoBuff, g_FlashExtInfo.wSpareDataLength/2);

#if 0
	NandDbgPutString ("si.bBadBlock=");
	NandDbgPutHex (pSectorInfoBuff->bBadBlock);
	NandDbgPutString ("\r\n");
	NandDbgPutString ("si.bOEMReserved=");
	NandDbgPutHex (pSectorInfoBuff->bOEMReserved);
	NandDbgPutString ("\r\n");
	NandDbgPutString ("FMDReadSectorInfo: end.\r\n");
#endif

	return TRUE;
}

BOOL FMDWriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pSectorInfoBuff)
{
	UNPROTECT_NAND();
	FMDChangePointer (POINTER_TO_SPARE_AREA);

	NF_STOP_FIFO();
	NF_IO_WR_MODE();
	NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
	NF_LEN(g_FlashExtInfo.wSpareDataLength/2);
	FMDSetAddress (sectorAddr,
				   g_FlashExtInfo.fi.wDataBytesPerSector,
				   0);

    NF_CLR_INT (0xFF);
	NF_CMD (SMDF_CMD_SEQ_DATA_INPUT);
	NF_WAIT_INT (SMDF_ADD_INT);

	NF_START_FIFO ();
	FMDWriteFifo ((PDWORD) pSectorInfoBuff, g_FlashExtInfo.wSpareDataLength/2);
	NF_WAIT_INT (SMDF_DMA_INT);

    FMDPageProgram ();
	PROTECT_NAND();
	if (!FMDVerifyWrite(g_nNandCS)) {
//    	NandDbgPutHex (SectorAddr);
//		NandDbgPutString (" Verify Write Error\r\n");
        return FALSE;
    }

	return TRUE;
}

BOOL FMDWriteEcc(SECTOR_ADDR sectorAddr, PBYTE eccBuf)
{
	FMDChangePointer (POINTER_TO_SPARE_AREA);

	NF_INIT_FIFO();
	NF_IO_WR_MODE();
	NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
	NF_LEN(g_FlashExtInfo.wSpareDataLength/2);
//	v_pSMDFRegs->SmFIFOLevelChk = 0;
	FMDSetAddress (sectorAddr,
				   g_FlashExtInfo.fi.wDataBytesPerSector + g_FlashExtInfo.wSpareDataLength/2,
				   g_FlashExtInfo.wSpareDataLength/2);

    NF_CLR_INT (0xFF);
	NF_CMD (SMDF_CMD_SEQ_DATA_INPUT);
	NF_WAIT_INT (SMDF_ADD_INT);

    NF_START_FIFO ();
	FMDWriteFifo ((PDWORD) eccBuf, g_FlashExtInfo.wSpareDataLength/2);
	NF_WAIT_INT (SMDF_DMA_INT);

    FMDPageProgram ();
	return TRUE;
}


/*
    @func   BOOL | FMD_WriteSector | Writes the specified data to the specified NAND flash sector/page.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm    
    @xref   
*/
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    ULONG SectorAddr = (ULONG)startSectorAddr;
	BYTE eccBuf[32];

    if (!pSectorBuff && !pSectorInfoBuff)
        return(FALSE);
	UNPROTECT_NAND();
	//PreWrite Initialization
	while (dwNumSectors--)
	{
		if (pSectorBuff)
		{
			//  Special case to handle un-aligned buffer pointer.
			memcpy(v_pDMAAddr, pSectorBuff, g_FlashExtInfo.fi.wDataBytesPerSector); // Write page/sector data.
			CacheRangeFlush ((PVOID)v_pDMAAddr, g_FlashExtInfo.fi.wDataBytesPerSector, CACHE_SYSNC_DISCARD);
			NF_CLR_INT(SMDF_DMA_INT);
			NF_STOP_FIFO();

			NF_RESET_ECC();
			//We need to change the write pointer to the correct area by issueing a read cmd in the area
			FMDChangePointer (POINTER_TO_DATA_AREA);

			NF_DMA_WR_MODE();
			NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
			FMDSetAddress (SectorAddr, 0, 0);
			NF_LEN(g_FlashExtInfo.fi.wDataBytesPerSector);

			NF_CLR_INT (0xFF);
			NF_CMD (SMDF_CMD_SEQ_DATA_INPUT);
			NF_WAIT_INT (SMDF_ADD_INT);

			NF_START_FIFO();
			NF_WRITE_DMA(g_FlashExtInfo.fi.wDataBytesPerSector);
			NF_WAIT_INT(SMDF_DMA_INT);

			//Commit what we have just write
			FMDPageProgram ();
			ECC_ENCODE (pSectorBuff, g_FlashExtInfo.fi.wDataBytesPerSector, (DWORD *)eccBuf);

			FMDWriteEcc(SectorAddr, eccBuf);
			if (!FMD_ReadSector(SectorAddr, ReadSectBuf, NULL, 1))
			{
				NandDbgPutString ("FMD: read error!\r\n");
				PROTECT_NAND();
				return FALSE;
			}

			if (memcmp (pSectorBuff, ReadSectBuf, g_FlashExtInfo.fi.wDataBytesPerSector))
			{
//				NandDbgPutString ("FMD: check error!\r\n");
	      PROTECT_NAND();
				return FALSE;
			}

			pSectorBuff += g_FlashExtInfo.fi.wDataBytesPerSector;
		}
		if(pSectorInfoBuff)
		{
			FMDWriteSectorInfo(SectorAddr, pSectorInfoBuff);
			pSectorInfoBuff++;
		}
		SectorAddr++;
	}
	PROTECT_NAND();
    if (!FMDVerifyWrite(g_nNandCS)) {
//    	NandDbgPutHex (SectorAddr);
//		NandDbgPutString (" Verify Write Error\r\n");
        return FALSE;
    }

	return(TRUE);
}

/*
    @func   BOOL | FMD_EraseBlock | Erases the specified flash block.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm    
    @xref   
*/
BOOL FMD_EraseBlock(DWORD blockID)
{
	DWORD Sector = BOOT_BLOCK_TO_SECTOR(blockID);
	UNPROTECT_NAND();
	NF_CMD_MODE();

	NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucNumBlockCycles);

	NF_SET_ADDR(Sector);
	NF_SET_ADDR_HI(0);

	NF_CLR_INT (SMDF_ADD_INT);
	NF_CMD (SMDF_CMD_BLOCK_ERASE);
	NF_WAIT_INT (SMDF_ADD_INT);
	PROTECT_NAND();
    if (!FMDVerifyWrite(g_nNandCS)) {
//    	NandDbgPutHex (Sector);
//    	NandDbgPutString (" Verify Erase Error\r\n");
        return FALSE;
    }

    return TRUE;
}

BOOL WriteImage(DWORD dwStartSearchBlock, DWORD dwTotalBlocks, PBYTE pImageCache/*, DWORD *pdwActualStartBlock, DWORD *pdwNextAvailableBlock*/)
{
	int i,j;
	DWORD dwBlock, dwSector;
	PBYTE pBuf = pImageCache;

	dwBlock = dwStartSearchBlock;
	pBuf = pImageCache;

	i = 0;
	while((i < dwTotalBlocks) && (dwBlock < (dwStartSearchBlock + SEARCH_BLOCKS)) )
	{
		i++;
		if(!NandCheckAndReserveBlock(dwBlock)) 
		{
			dwBlock ++;
			continue;
		}
		if(!NandIsOEMReservedBlock(dwBlock))
		{
			dwBlock ++;
			continue;
		}

		dwSector = BOOT_BLOCK_TO_SECTOR(dwBlock);
		for(j = 0; j < g_FlashExtInfo.fi.wSectorsPerBlock; j++)	
		{
			if(!FMD_WriteSector(dwSector, pBuf, &g_SI, 1)) {
				return FALSE;
			}
			dwSector ++;
			pBuf += g_FlashExtInfo.fi.wDataBytesPerSector;
		}
		dwBlock ++;
	}

	if(i != dwTotalBlocks || dwBlock >= (dwStartSearchBlock + SEARCH_BLOCKS))
		return FALSE;

	return TRUE;
}

BOOL NandIsOEMReservedBlock(DWORD dwBlock)
{
	SectorInfo si;
	if(FMDReadSectorInfo(BOOT_BLOCK_TO_SECTOR(dwBlock), &si))
	{
		if( si.bBadBlock == BADBLOCKMARK && 
			si.bOEMReserved == OEM_RESERVED_BLOCK && 
			si.dwReserved1 == 0 && 
			si.wReserved2 == 0)
			{
				return TRUE;
			}
	}
//	NandDbgPutString ("NandIsOEMReservedBlock: failed.\r\n");
	return FALSE;
}

/*
    @func   BOOL | FMD_ReadSector | Reads the specified sector(s) from NAND flash.
    @rdesc  TRUE = Success, FALSE = Failure.
    @comm    
    @xref   
*/
BOOL FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
	BYTE eccBuf[32];
	ULONG SectorAddr = (ULONG)startSectorAddr;

	if (!pSectorBuff && !pSectorInfoBuff)
	{
		return(FALSE);
	}

	pSectorBuff = (LPBYTE) ((DWORD)pSectorBuff & ~0xc0000000);

	while (dwNumSectors--)
	{
 		CacheRangeFlush ((PVOID)v_pDMAAddr, g_FlashExtInfo.dwPageSize, CACHE_SYSNC_DISCARD);
		if (pSectorBuff)
		{
			NF_RESET_ECC();

			//We will totally read out the whole page bytes.
			NF_STOP_FIFO();
			NF_DMA_RD_MODE();
			NF_ADDR_CYCLE_NUM(g_FlashExtInfo.ucChipAddrCycleNum);
			FMDSetAddress (SectorAddr, 0, 0);
			NF_LEN(g_FlashExtInfo.dwPageSize);
			NF_CLR_INT(SMDF_DMA_INT);
			NF_CMD(SMDF_CMD_READ1);
			NF_READ_DMA(g_FlashExtInfo.dwPageSize, dwDmaPhysAddr);
			NF_START_FIFO();
			NF_WAIT_INT (SMDF_DMA_INT);
			while((v_pDMAReg->chnValid.chn4))
			{
			}

			IOBG_FLUSH = 1;
			while (IOBG_FLUSH);
			memcpy(eccBuf,
				(void*)(v_pDMAAddr + g_FlashExtInfo.fi.wDataBytesPerSector + g_FlashExtInfo.wSpareDataLength/2),
				g_FlashExtInfo.wSpareDataLength/2);

			if (!ECC_DECODE (v_pDMAAddr, g_FlashExtInfo.fi.wDataBytesPerSector, (DWORD *)eccBuf)) {
//				NandDbgPutHex (SectorAddr);
//				NandDbgPutString (" ecc error\r\n");
				return FALSE;
			}

			memcpy (pSectorBuff, v_pDMAAddr, g_FlashExtInfo.dwPageSize);
			pSectorBuff += g_FlashExtInfo.fi.wDataBytesPerSector;
			if(pSectorInfoBuff)
			{
				memcpy(pSectorInfoBuff, pSectorBuff, sizeof (SectorInfo));
				pSectorInfoBuff ++;
			}
		}
		else if(pSectorInfoBuff)//Only ask for pSectorInfo
		{
			FMDReadSectorInfo(SectorAddr, pSectorInfoBuff);
			pSectorInfoBuff ++;
		}

        ++SectorAddr;
    }

	return(TRUE);
}

static BOOL NandCheckAndReserveBlock(DWORD dwBlockIndex)
{
	DWORD dwSector;
	SectorInfo WriteSectInfo, ReadSectInfo;
	int j;

	if (!FMD_EraseBlock(dwBlockIndex)) {
		goto BadBlockReturn;
	}

	// Because the bits denoting a bad block can be erased, we take the cautious approach - we'll write an read-verify each sector in this
	// block to make sure the block is good.  If it's good, we'll re-erase else we'll mark the block bad.
	dwSector = BOOT_BLOCK_TO_SECTOR (dwBlockIndex);
	for (j = 0 ; j < g_FlashExtInfo.fi.wSectorsPerBlock ; j++)
	{
		// Make sure erase set all bits high.
		memset(WriteSectBuf, 0xFF, g_FlashExtInfo.fi.wDataBytesPerSector);
		memset(&WriteSectInfo, 0xFF, g_FlashExtInfo.wSpareDataLength/2);

		FMD_ReadSector((dwSector + j), ReadSectBuf, &ReadSectInfo, 1);

		if (memcmp(ReadSectBuf, WriteSectBuf, g_FlashExtInfo.fi.wDataBytesPerSector) ||
			memcmp(&ReadSectInfo, &WriteSectInfo, g_FlashExtInfo.wSpareDataLength/2))
		{
//			NandDbgPutString ("Bad block: read after erasing not FF\r\n");
			goto BadBlockReturn;
		}

		// Now, make sure we can store zero - this is meant to check for bad blocks (in the event that the bad block marker was erased).
		// Note that we *don't* write sector info data here - this is where bad block data is stored.
		memset(WriteSectBuf, 0, g_FlashExtInfo.fi.wDataBytesPerSector);
		if (!FMD_WriteSector((dwSector + j), WriteSectBuf, NULL, 1))
		{
//			NandDbgPutString ("Bad block: write 0 error\r\n");
			goto BadBlockReturn;
		}
	}

	// If the block has already been marked bad, skip it and increase the total number of blocks to be erased by a block.  Note that bad
	// blocks do count against the total number of blocks to be erased since the caller has max constraints on the erase region size.

	if (!FMD_EraseBlock(dwBlockIndex)) {
		goto BadBlockReturn;
	}

	for (j = 0 ; j < g_FlashExtInfo.fi.wSectorsPerBlock ; j++)
	{
/*		WriteSectInfo.dwReserved1 = 0;
		WriteSectInfo.bOEMReserved = OEM_RESERVED_BLOCK;
		WriteSectInfo.bBadBlock = BADBLOCKMARK;
		WriteSectInfo.wReserved2 = 0;
		
		if (!FMD_WriteSector (dwSector + j, NULL, &WriteSectInfo, 1))
*/			
		if (!FMD_WriteSector (dwSector + j, NULL, &g_SI, 1))			
			goto BadBlockReturn;

⌨️ 快捷键说明

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