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

📄 nand.c

📁 davinci的NANDFLASH烧写程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	pNandInfo->pageShift = (pNandInfo->bigBlock)?16:8;
	pNandInfo->blkShift += pNandInfo->pageShift;
	
	// Set number of column address bytes needed
	pNandInfo->numColAddrBytes = pNandInfo->pageShift >> 3;
	
	j = 0;
	while( (pNandInfo->numBlocks >> j) > 1)
	{
		j++;
	}
				
	// Set number of row address bytes needed
	if ( (pNandInfo->blkShift + j) <= 24 )
	{
	    pNandInfo->numRowAddrBytes = 3 - pNandInfo->numColAddrBytes;
	}
	else if ((pNandInfo->blkShift + j) <= 32)
	{
	    pNandInfo->numRowAddrBytes = 4 - pNandInfo->numColAddrBytes;
	}
	else
	{
	    pNandInfo->numRowAddrBytes = 5 - pNandInfo->numColAddrBytes;
	}
	
	// Set the ECC bit mask
	pNandInfo->ECCMask = 0x00000000;
	for (j = 0; (((pNandInfo->bytesPerOp*8)>>j) > 0x1); j++)
	{
	    pNandInfo->ECCMask |= (0x00010001<<j);
	}
	
	pNandInfo->ECCOffset = (pNandInfo->bigBlock)?2:0;

	pNandInfo->ECCEnable = TRUE;
				    		
	return E_PASS;
}


// *******************
// NAND Read Functions
// *******************

// Routine to read a page from NAND
Uint32 NAND_ReadPage(PNAND_INFO pNandInfo, Uint32 block, Uint32 page, Uint8 *dest)
{
	Uint32 eccValue[4];
    Uint32 spareValue[4];
	Uint8 i;
	
    // Write read command
    flash_write_cmd(pNandInfo,NAND_LO_PAGE);
	
	// Write address bytes
	flash_write_addr_cycles(pNandInfo, block, page);

    // Additional confirm command for big_block devices
	if(pNandInfo->bigBlock)	
		flash_write_cmd(pNandInfo, NAND_READ_30H);

	// Wait for data to be available
	if(NAND_WaitForRdy(NAND_TIMEOUT) != E_PASS)
		return E_FAIL;

	// Starting the ECC in the NANDFCR register for CS region
	NAND_ECCReadAndRestart(pNandInfo);

    // Read the page data
    for (i=0; i < pNandInfo->numOpsPerPage; i++)
    {
        // Actually read bytes
		flash_read_bytes(pNandInfo, (void*)(dest), pNandInfo->bytesPerOp);
	    
	    // Get the ECC Value
	    eccValue[i] = NAND_ECCReadAndRestart(pNandInfo);
	    	    
	    //Increment pointer
	    dest += pNandInfo->bytesPerOp;
	}

    // Reset the page pointer
    dest -= pNandInfo->bytesPerPage;

    // Check ECCs
    for (i=0; i<pNandInfo->numOpsPerPage; i++)
	{
        flash_read_bytes(pNandInfo, (void*)(spareValue), pNandInfo->spareBytesPerOp);
        flash_swap_data(pNandInfo, (Uint32*)(spareValue+pNandInfo->ECCOffset));

		// Verify ECC values
		if(eccValue[i] != spareValue[pNandInfo->ECCOffset])
        {
			if ( (!pNandInfo->ECCEnable) && 
				 (NAND_ECCCorrection( pNandInfo,
					                  spareValue[pNandInfo->ECCOffset],
						              eccValue[i],
							          dest+(i*pNandInfo->bytesPerOp) ) != E_PASS) )
			{
				printf("NAND ECC failure!\r\n");
				return E_FAIL;
			}
		}
    }
    
    // Return status check result
	return NAND_WaitForStatus(pNandInfo, NAND_TIMEOUT);
}

// ********************
// NAND Write Functions
// ********************

// Generic routine to write a page of data to NAND
Uint32 NAND_WritePage(PNAND_INFO pNandInfo, Uint32 block, Uint32 page, Uint8 *src) {
	Uint32 eccValue[4];
	Uint32 spareValue[4];
	Uint8 i;

    // Make sure the NAND page pointer is at start of page
    flash_write_cmd(pNandInfo,NAND_LO_PAGE);

	// Write program command
	flash_write_cmd(pNandInfo, NAND_PGRM_START);
	
	// Write address bytes
	flash_write_addr_cycles(pNandInfo,block,page);
	
	// Starting the ECC in the NANDFCR register for current CS region
	NAND_ECCReadAndRestart(pNandInfo);
	
	// Write data
	for (i=0; i<pNandInfo->numOpsPerPage; i++)
	{
	    flash_write_bytes(pNandInfo, (void*) src, pNandInfo->bytesPerOp);    
	    	    	    
	    // Read the ECC value
	    eccValue[i] = NAND_ECCReadAndRestart(pNandInfo);	    

	    // Increment the pointer
	    src += pNandInfo->bytesPerOp;
	}
	
    // Write spare bytes
    spareValue[0] = 0xFFFFFFFF;
    spareValue[1] = 0xFFFFFFFF;
    spareValue[2] = 0xFFFFFFFF;
    spareValue[3] = 0xFFFFFFFF;
    for (i=0; i<pNandInfo->numOpsPerPage; i++)
    {
        // Swap the bytes for how the ROM needs them
        flash_swap_data(pNandInfo, &(eccValue[i]));
        
		// Place the ECC values where the ROM read routine expects them    
        spareValue[pNandInfo->ECCOffset] = eccValue[i];
        
		// Actually write the Spare Bytes               
        flash_write_bytes(pNandInfo, (void*)(spareValue), pNandInfo->spareBytesPerOp);
    }
    			
    // Write program end command
    flash_write_cmd(pNandInfo, NAND_PGRM_END);
	
	// Wait for the device to be ready
	if (NAND_WaitForRdy(NAND_TIMEOUT) != E_PASS)
		return E_FAIL;

    // Return status check result	
	return NAND_WaitForStatus(pNandInfo, NAND_TIMEOUT);
}


// **********************************************************
// Verify data written by reading and comparing byte for byte
// **********************************************************
Uint32 NAND_VerifyPage(PNAND_INFO pNandInfo, Uint32 block, Uint32 page, Uint8* src, Uint8* dest)
{
    Uint32 i;

    if (NAND_ReadPage(pNandInfo, block, page, dest) != E_PASS)
        return E_FAIL;
    
    for (i=0; i< pNandInfo->bytesPerPage; i++)
    {
        // Check for data read errors
        if (src[i] != dest[i])
        {
            printf("Data mismatch! Verification failed.\r\n");            
            printf("Block   = %d\r\n", block);         
            printf("Page    = %d\r\n", page);          
            printf("i       = %d\r\n", i);
            printf("src[i]  = %d\r\n", src[i]);          
            printf("dest[i] = %d\r\n", dest[i]);
            return E_FAIL;
        }
    }
	return E_PASS;
}


// *******************************
// NAND Flash erase block function
// *******************************
Uint32 NAND_EraseBlocks(PNAND_INFO pNandInfo, Uint32 startBlkNum, Uint32 blkCnt)
{	
	Uint32 i;
		
	// Do bounds checking
	if ( (startBlkNum + blkCnt - 1) >= pNandInfo->numBlocks )
		return E_FAIL;
	
	// Output info about what we are doing
	printf("Erasing blocks 0x%8.8X through 0x%8.8X.\r\n", startBlkNum, (startBlkNum + blkCnt - 1) );

	for (i = 0; i < blkCnt; i++)
	{
		// Start erase command
		flash_write_cmd(pNandInfo, NAND_BERASEC1);

		// Write the row addr bytes only
		flash_write_row_addr_bytes(pNandInfo, (startBlkNum+i), 0);
		
		// Confirm erase command
		flash_write_cmd(pNandInfo, NAND_BERASEC2);

		// Wait for the device to be ready
		if (NAND_WaitForRdy(NAND_TIMEOUT) != E_PASS)
			return E_FAIL;

		// verify the op succeeded by reading status from flash
        if (NAND_WaitForStatus(pNandInfo,NAND_TIMEOUT) != E_PASS)
			return E_FAIL;
	}

	return E_PASS;
}


// *******************************************************************
// NAND Protect and Unprotect commands (not all devices support these)
// *******************************************************************

// NAND Flash unprotect command
Uint32 NAND_UnProtectBlocks(PNAND_INFO pNandInfo, Uint32 startBlkNum, Uint32 blkCnt)
{
	Uint32 endBlkNum;
	endBlkNum = startBlkNum + blkCnt - 1;

	// Do bounds checking
	if (endBlkNum >= pNandInfo->numBlocks)
		return E_FAIL;

	// Output info about what we are doing
	printf("Unprotecting blocks 0x%8.8X through 0x%8.8X.\r\n", startBlkNum, endBlkNum);

	flash_write_cmd(pNandInfo, NAND_UNLOCK_START);
	flash_write_row_addr_bytes(pNandInfo, startBlkNum, 0);
	
	flash_write_cmd(pNandInfo, NAND_UNLOCK_END);
	flash_write_row_addr_bytes(pNandInfo, endBlkNum, 0);
		
	return E_PASS;
}

// NAND Flash protect command
void NAND_ProtectBlocks(PNAND_INFO pNandInfo)
{
	printf("Protecting the entire NAND flash.\r\n");
	flash_write_cmd(pNandInfo, NAND_LOCK);
}


// Generic function to write a UBL or Application header and the associated data
Uint32 NAND_WriteHeaderAndData( PNAND_INFO pNandInfo, NAND_BOOT *nandBoot, Uint8 *srcBuf)
{
	Uint32     endBlockNum;
	Uint32     *ptr;
	Uint32     blockNum;
	Uint32     count;
	Uint32     countMask;
	Uint32     numBlks;

    // Get total number of blocks needed
	numBlks = 0;
	while ( (numBlks * pNandInfo->pagesPerBlock)  < (nandBoot->numPage + 1) )
	{
		numBlks++;
	}
    printf("Number of blocks needed for writing: 0x%8.8X\r\n",numBlks);

	// Check whether writing UBL or APP (based on destination block)
	blockNum = nandBoot->block;
	if (blockNum == START_UBL_BLOCK_NUM)
	{
		endBlockNum = END_UBL_BLOCK_NUM;
	}
	else if (blockNum == START_APP_BLOCK_NUM)
	{
		endBlockNum = END_APP_BLOCK_NUM;
	}
	else
	{
		return E_FAIL; /* Block number is out of range */
	}

NAND_WRITE_RETRY:
	if (blockNum > endBlockNum)
	{
		return E_FAIL;
	}
	printf("Attempting to start in block number 0x%8.8X\r\n", blockNum);

	// Unprotect all needed blocks of the Flash 
	//if (NAND_UnProtectBlocks(pNandInfo,blockNum,numBlks) != E_PASS)
	//{
	//	blockNum++;
	//	printf("Unprotect failed.\r\n");
	//	goto NAND_WRITE_RETRY;
	//}

	// Erase the block where the header goes and the data starts
	if (NAND_EraseBlocks(pNandInfo,blockNum,numBlks) != E_PASS)
	{
		blockNum++;
		printf("Erase failed.\r\n");
		goto NAND_WRITE_RETRY;
	}
		
	// Setup header to be written
	ptr = (Uint32 *) pNandInfo->writeBuff;
	ptr[0] = nandBoot->magicNum;
	ptr[1] = nandBoot->entryPoint;
	ptr[2] = nandBoot->numPage;
	ptr[3] = blockNum;	//always start data in current block
	ptr[4] = 1;			//always start data in page 1 (this header goes in page 0)
	ptr[5] = nandBoot->ldAddress;


    // Write the header to page 0 of the current blockNum
	printf("Writing header...");
	if (NAND_WritePage(pNandInfo, blockNum, 0, pNandInfo->writeBuff) != E_PASS)
    {
		blockNum++;
		printf("Page Write failed.\r\n");
		goto NAND_WRITE_RETRY;
	}
		
	waitloop(200);

	// Verify the page just written
	if (NAND_VerifyPage(pNandInfo, blockNum, 0, pNandInfo->writeBuff, pNandInfo->readBuff) != E_PASS)
    {
		blockNum++;
		printf("Page Verify failed.\r\n");
		goto NAND_WRITE_RETRY;
	}
    printf("Successful!\r\n");
	count = 1; 

	// The following assumes power of 2 page_cnt -  *should* always be valid 
	countMask = (Uint32)pNandInfo->pagesPerBlock - 1;

	printf("Writing data...");
	do {
		// Write the UBL or APP data on a per page basis
		if (NAND_WritePage(pNandInfo, blockNum, (count & countMask), srcBuf) != E_PASS)
        {
		    blockNum++;
		    printf("Page Write failed.\r\n");
		    goto NAND_WRITE_RETRY;
	    }

		waitloop(200);
		
		// Verify the page just written
		if (NAND_VerifyPage(pNandInfo, blockNum, (count & countMask), srcBuf, pNandInfo->readBuff) != E_PASS)
		{
    		blockNum++;
	    	printf("Page Verify failed.\r\n");
		    goto NAND_WRITE_RETRY;
	    }
		
		count++;
		srcBuf += pNandInfo->bytesPerPage;
		if (!(count & countMask))
		{
			blockNum++;
		}
	} while (count <= nandBoot->numPage);
    printf("Successful!\r\n");

	//NAND_ProtectBlocks(pNandInfo);

	return E_PASS;
}


⌨️ 快捷键说明

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