flash.c

来自「FreeScale imx21开发板Nand flash烧写程序」· C语言 代码 · 共 1,195 行 · 第 1/3 页

C
1,195
字号
{
   u32 ByteDone = 0;
   /* FlashAddress is byte offset in nand */
   u32 BlockNum = FlashAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
   u32 PageNum  = 0;
   u32 ReadSize;
   u32 tmp;

   while(ByteSize > ByteDone)
   {
    /* if end of a block*/
     if( PageNum >= NAND_NUM_OF_PAGES ) {
       BlockNum++;                        /*go to next block*/
       PageNum=0;
     }
       
     if( PageNum == 0 ) {                 /* if Start of Block */
       if(!nand_block_is_good(BlockNum))   /* if Block is not Good */
       {
         BlockNum++;                     
         continue;
       }
     }
     
     ReadSize = ((ByteSize-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (ByteSize-ByteDone);
     tmp = nand_read_page(BlockNum, PageNum, TargetAddress+ByteDone, ReadSize);
     if( tmp != NAND_ERROR_NO ) { /* if error */
       //flash_report_error(REPORT_ERROR_STOP, 0);
       return tmp;
     }
     
     ByteDone+=ReadSize;
     PageNum++;
   }
   
   return 0; // complete for no error
}

U8 nand_write_page(U32 BlockNum, U32 PageNum, U32 SourceAddress, U32 ByteSize/*,u8 file_format*/)
{
	U8 i;

//	if (FILE_FORMAT_NB0 == file_format)
//	{
		/* fill internal RAM buffer */
//		for(i=0; i<64; i+=2)
//		{
//			if((i == 4)||(i == 20) ||(i == 36)||(i == 52))
//			*(volatile u16 *)(NFC_SAB0_BASE+i) = 0xFF00;
//		else
//			*(volatile u16 *)(NFC_SAB0_BASE+i) = 0xFFFF;
//		}
//	}
//	else
//	{

		/* fill internal RAM buffer */
		for(i=0; i<64; i+=2)
			*(volatile u16 *)(NFC_SAB0_BASE+i) = 0xFFFF;
//	}
	
	nfc_memcpy(SourceAddress, NFC_MAB0_BASE, ByteSize);

	*(volatile u16 *)NFC_RAM_BUF_ADDR = 0;
	nfc_command_input(NAND_CMD_PAGE_PROG);  
	nfc_address_cycle(0, 2);
	nfc_address_cycle(BlockNum*NAND_NUM_OF_PAGES+PageNum, NAND_NUM_OF_ROW_ADDR_CYCLES);
	nfc_flash_data_input();

	*(volatile u16 *)NFC_RAM_BUF_ADDR = 1;
	nfc_flash_data_input();
	*(volatile u16 *)NFC_RAM_BUF_ADDR = 2;
	nfc_flash_data_input();
	*(volatile u16 *)NFC_RAM_BUF_ADDR = 3;
	nfc_flash_data_input();
	
	nfc_command_input(NAND_CMD_PAGE_PROG_CONFIRM);

	nand_wait();

	if( nand_read_status() & NAND_STATUS_PROG_ERROR )
	{
		return NAND_ERROR_PROG; 
	}

	return NAND_ERROR_NO;  
}
//CheckFlashComplete(0x67676767);
U32 FlashWrite(U32 sAddress, 
               U32  pData, 
               U32 nData)
{

	U32 tmp;
	U32 ByteDone = 0;
	U32 BlockNum = sAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
	U32 PageNum  = 0;
	U32 WriteSize;
	
	while(nData>ByteDone)
	{
		if( PageNum >= NAND_NUM_OF_PAGES ) 
		{ /* if end of a block */
			BlockNum++;                        /* go to next block */
			PageNum=0;
			//flash_report_program_byte_done(ByteDone);       
		}

		if( PageNum == 0 ) 
		{                 /*  if Start of Block */
			nand_wait();

			if(!nand_block_is_good(BlockNum)) 
			{ /* if Block is not Good */
				//dbg("Write meet bad block:%d",BlockNum);

				BlockNum++;                     
				continue;
			}
			
			nand_wait();
			
			if( nand_erase_block(BlockNum) != NAND_ERROR_NO ) 
			{	
				/* block erase error */
				//flash_report_error(REPORT_ERROR_ERASE, BlockNum);
				nand_mark_bad_block(BlockNum);
				BlockNum++;   /* Skip this block  */                 
				continue;
			}
		}//end of if( PageNum == 0 ) by fcding
     
		nand_wait();
 
		WriteSize = ((nData-ByteDone)>NAND_MAIN_BYTESIZE) ? NAND_MAIN_BYTESIZE : (nData-ByteDone);
     
		tmp = nand_write_page(BlockNum, PageNum, pData+ByteDone, WriteSize/*,file_format*/);
		if( tmp == NAND_ERROR_ECC ) /* if ECC error */
		{
			nand_wait();
			nand_mark_bad_block(BlockNum);
			BlockNum++;                        /* Skip this block */
			PageNum = 0;
			continue;
		}
		

		if( tmp == NAND_ERROR_PROG ) /* if PROG error */
		{
			//flash_report_error(REPORT_ERROR_PROGEAM, 
     	     //                 BlockNum*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES+PageNum*NAND_MAIN_BYTESIZE);
			//flash_report_program_complete();
			return NAND_ERROR_PROG;
		}
     
		/*Preparation for Next Page*/
		ByteDone+=WriteSize;
		PageNum++;
		
	}//end of while by fcding
   
	//flash_report_program_byte_done(ByteDone);
	return 0; 

}


void Nand_bad_test(void)
{
	U32 BlockNum = 0;
	
	for (BlockNum = 150; BlockNum < 200; BlockNum++)
	{
		if(!nand_block_is_good(BlockNum)) 
		{ 
			while(1);
			printf("Bad Block#\n");
		}
	}

}


void Nand_test(void)
{
	U32 fWalk, mWalk;
	U32 result;
	U32 blockIndex, i;
	fWalk  = 0xC2000000;
	mWalk  = 0xC3000000;
	result = 0xC1900000;
	
	
	for (blockIndex = 0; blockIndex < 1024; blockIndex++)
	{
		FlashWrite(blockIndex*NAND_NUM_OF_PAGES*2048, 0xC2000000, 2048*64);
		nand_read (blockIndex*NAND_NUM_OF_PAGES*2048, 0xC3000000, 2048*64);
		for (i = 0; i < (2048*64/4); i++)
		{
			if (*(volatile U32 *)(fWalk + i) != *(volatile U32 *)(mWalk + i))
			{
				break;
			}
		}
		if (i != (2048*64/4)) 
		{
			*(volatile U32 *)(result+4) = 77;
			break;
		}
		*(volatile U32 *)(result) = 99;
	}

}

void nand_unconditional_erase_all(void)
{
  U32 i;
   
  for(i=0; i<NAND_NUM_OF_BLOCKS; i++) {
  	nand_wait();
    if(nand_erase_block(i)) {
      //flash_report_error(REPORT_ERROR_ERASE, i*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES);
    //dbg("Erasing Block# %d\n", i+1);
    }
  }
}

U32 FlashSectorErase(U32 sAddress, 
               		 U32 nAddress)
{
   U32 i;
   U32 j=0;
   U8 ret = 0;
    
   i=sAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
   
	for(; i<=(nAddress/(NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE)); i++){

		nand_wait();

		if(nand_block_is_good(i)) {
			nand_wait();

			if(nand_erase_block(i)){

				ret = NAND_ERROR_ERASE;

			//flash_report_error(REPORT_ERROR_ERASE, i*NAND_MAIN_BYTESIZE*NAND_NUM_OF_PAGES);
 			}
			else {
				j++;
				//flash_report_erase_byte_done(j*NAND_NUM_OF_PAGES*NAND_MAIN_BYTESIZE);
 			}
		}
		else{
		}
	}
	//flash_report_erase_complete();

    return ret;
    
}
//end change by fcding

// ***************************************************************************
//
//  Function:       FlashSectorErase
//
//                  This function erases all flash memory sectors overlapping
//                  the address range specified in the parameters.
//
//
//  Parameters:     U32             sAddress        start address for erase
//                  U32             nAddress        end address for erase
//
//  Return Value:   U32             number of bytes erased (rounded up to
//                                  next sector limit), or zero on error
//
// ***************************************************************************
/*
U32 FlashSectorErase(U32 sAddress, 
               		 U32 nAddress)
{
    volatile U32*       pBase;
    volatile U32*       pWalk;
    BOOL                bFailTotal;
    BOOL                bDone;
    BOOL                bFail;
    U32                 nWalk;
    U32                 nSize;
    U32                 nPoll;
    U32                 nDone;
    U32                 nSec;
    U32					SA;
    U32					i = 0;

	U32 Flash_Erase			= 0x17171717;

        // Check the Flash Starting Address
        pBase = (volatile U32*)(sAddress & 0xFE000000);


        // Reset flash devices before starting erase sequences
        // ***************************************************
        *(pBase + 0x000) = 0x00f000f0;
		
		nSec = (U32)pBase;
		nDone = 0;
		nWalk = sAddress;
		#ifdef DEBUG
		printf("Sector Erase at [0x%08X - 0x%08X]...\n",sAddress, nAddress);
		#endif		
		
		for (SA = 1; SA <= 270; SA++)
		{
			if ((SA >= 1 && SA <= 8) || (SA >= 263 && SA <= 270))
			{	
				nSize = 0x1000*4;
			}
			else
			{
				nSize = 0x8000*4;
			}
			
			if ((nSec <= nWalk) && (nSec + nSize > nWalk) && (nSec <= nAddress))
			{
				
				// This sector overlaps the address range. Erase it
				// ************************************************
				pWalk = (volatile U32*) nWalk;

				// Execute "normal" sector erase algorithm
				// ***************************************
				*(pBase + 0x555) = 0x00aa00aa;
				*(pBase + 0x2aa) = 0x00550055;
				*(pBase + 0x555) = 0x00800080;
				*(pBase + 0x555) = 0x00aa00aa;
				*(pBase + 0x2aa) = 0x00550055;
				*(pWalk)         = 0x00300030;


				// Data polling algorithm for erase operation
				// ******************************************
				bDone = FALSE;
				bFail = FALSE;

				while ((!bDone) && (!bFail))
				{
					nPoll = *(pWalk);
					if (((~nPoll) & FLASH_DQ7_2X16) == 0)
					{  
						bDone = TRUE;
					}
					else if ((nPoll & FLASH_DQ5_2X16) == FLASH_DQ5_2X16)
					{
						nPoll = *(pWalk);
						if (((~nPoll) & FLASH_DQ7_2X16) == 0)
						{
							bDone = TRUE;
						}
						else
						{
							bFail      = TRUE;
							bFailTotal = TRUE;
						}
					}
					if ( (i &= 0xFFFF) ==0)
					{
						#ifdef DEBUG
						printf(".");
						#endif
						
						CheckFlashComplete(Flash_Erase);
					}
					i++;
                }
                nDone += nSize;
                nWalk += nSize;
            }
            nSec += nSize;
        }


        // Reset flash devices
        // *******************
        *(pBase + 0x000) = 0x00f000f0;

    return bFailTotal ? 0 : nDone;
}
*/
// ***************************************************************************
//
//  Function:       FlashRead
//
//                  
//
//  Parameters:     U32             sAddress        start address for read
//                  void*           pData           data to read
//                  U32             nData           number of bytes to read

⌨️ 快捷键说明

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