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

📄 nandmtd.c

📁 cpc-1631的BSP包for VxWorks操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 	address	: Address of sector to write to.			*/
/*	buffer	: buffer to write from.					*/
/*	length	: number of bytes to write (up to sector size).		*/
/*	modes	: OVERWRITE, EDC flags etc.				*/
/*									*/
/* Returns:                                                          	*/
/*	FLStatus: 0 on success, otherwise failed.			*/
/*									*/
/*----------------------------------------------------------------------*/
static FLStatus nandMTDWrite( FLFlash vol,
			 CardAddress address,       /* target flash address*/
			 const void FAR1 *buffer,    /* source RAM buffer  */
			 int length,                /* bytes to write      */
			 int modes)                 /* Overwrite, EDC flags etc.*/
{
	int writeNow;
	const char FAR1 *temp;
	FLStatus      status = flOK;

#ifdef VERIFY_AFTER_WRITE
	CardAddress  saveAddress = address;
	unsigned short flReadback[SECTOR_SIZE / sizeof(unsigned short)];
#endif 

	/* write in sectors; first and last might be partial*/
	int page = modes & EXTRA ? 16 : 512;
#if 0
	if(1==nand_is_bad_block((address&(~page))/32))/*坏块判断*/
	{
	address+=page;
	}
#endif
	writeNow = page - ((unsigned short)address & (page - 1));
	temp = (const char FAR1 *)buffer;

	for ( ; length > 0 ; )
	{
		if (writeNow > length)
		{
			writeNow = length;
		}

		/* turn off EDC on partial block write*/
		status = writeOnePage(&vol, address, temp, writeNow,
		writeNow != 512 ? (modes & ~EDC) : modes);

		if (status != flOK)
		{
			break;
		}

#ifdef VERIFY_AFTER_WRITE
		status = readOnePage (&vol, address, (char FAR1 *)flReadback,
		writeNow, (writeNow != SECTOR_SIZE ? (modes & ~EDC) : modes));

		if((status != flOK) || (tffscmp(temp, flReadback, writeNow) != 0))
		{ 
			printf("nandMTDWrite:verify error! status=%d\n",status);
			status = flWriteFault; 
			break; 
		}
#endif

		length -= writeNow;
		address += writeNow;
		temp += writeNow;

		/* align at sector */
		writeNow = page;
	}

	return flOK ;
}


/*----------------------------------------------------------------------*/
/*		          n a n d E r a s e				*/
/*									*/
/* Erase number of blocks. This routine will be registered as the	*/
/* erase routine for this MTD.						*/
/*                                                                      */
/* Author: kuangyaowen              Date:2007-11-21                            */
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	blockNo		: First block to erase.				*/
/*	blocksToErase   : Number of blocks to erase.			*/
/*									*/
/* Returns:                                                          	*/
/*	FLStatus	: 0 on success, otherwise failed.		*/
/*									*/
/*----------------------------------------------------------------------*/

static FLStatus nandMTDErase( FLFlash vol,
			 int blockNo,              /* start' block (0 .. chipNoOfBlocks-1)*/
			 int blocksToErase)        /* Number of blocks to be erased */
{
	int i;
	FLStatus status   = flOK;

	blockNo %= thisVars->noOfBlocks;                       /* within flash device  */

	if ( blockNo + blocksToErase > thisVars->noOfBlocks )    /* accross device boundary */
	{
		printf("blockNo + blocksToErase=0x%x,thisVars->noOfBlocks=0x%x\n",blockNo + blocksToErase,thisVars->noOfBlocks );
		return flBadParameter;
	}

#ifdef DEBUG_PRINT
	DEBUG_PRINT("firstBlock = 0x%x, numOfBlock = 0x%x\n", blockNo, blocksToErase);
#endif

	for ( i=0; i < blocksToErase; i++)
	{
		
		unsigned int pageNo = (blockNo+i) * PAGES_PER_BLOCK ;
#if 0
		if(1==nand_is_bad_block(i))/*坏块判断*/
		{
			printf("nandMTDErase :block%d is bad\n",i);
		continue;
		}

#endif
		nand_ce_low();  /*片选有效*/

		nand_write_command(SETUP_ERASE);/* 发送块擦除命令0x60*/

		nand_ale_high();
		nand_write_address((unsigned char)(pageNo&0xff));        /* A9 ~ A16 */
		nand_write_address((unsigned char)((pageNo>>8)&0xff));   /* A17 ~ A24 */
		nand_write_address((unsigned char)((pageNo>>16)&0x01));   /* A25 */
		nand_ale_low();

		nand_write_command(CONFIRM_ERASE);/*0xd0*/

		waitForReady();

		if(readStatus() & FAIL)
		{    
			status = flWriteFault;  /* erase operation failed */
		}
		
		nand_ce_high(); /*片选取消*/

#ifdef DEBUG_PRINT
		DEBUG_PRINT("ERASE: blockNo = 0x%x\n", blockNo);
#endif

		if (status != flOK)       /* reset flash device and abort */
		{                              
#ifdef DEBUG_PRINT
		DEBUG_PRINT("Debug: erase failed in K9F1208.\n");
#endif

		nand_reset();/*reset*/

		break ;
		}
	}       /* block loop */

	return status;
}


/*----------------------------------------------------------------------*/
/*		          nand M a p					*/
/*									*/
/* Map through buffer. This routine will be registered as the map	*/
/* routine for this MTD.						*/
/*									*/
/* Parameters:								*/
/*	vol	: Pointer identifying drive		                */
/*	address	: Flash address to be mapped.				*/
/*	length	: number of bytes to map.				*/
/*									*/
/* Returns:                                                          	*/
/* 	Pointer to the buffer data was mapped to.			*/
/*									*/
/*----------------------------------------------------------------------*/

static void FAR0 * nandMTDMap ( FLFlash vol,
			    CardAddress address,
			    int length )
{
	nandMTDRead(&vol,address,thisBuffer,length, 0);
	
	vol.socket->remapped = TRUE;
	
	return (void FAR0 *)thisBuffer;
}


/*----------------------------------------------------------------------*/
/*		          i s K n o w n M e d i a			*/
/*									*/
/* Check if this flash media is supported. Initialize relevant fields	*/
/* in data structures.							*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	vendorId_P	: vendor ID read from chip.			*/
/*	chipId_p	: chip ID read from chip.			*/
/*	dev		: dev chips were accessed before this one.	*/
/*									*/
/* Returns:                                                          	*/
/* 	TRUE if this media is supported, FALSE otherwise.		*/
/*									*/
/*----------------------------------------------------------------------*/
static FLBoolean isKnownMedia( FLFlash vol,
			 unsigned short vendorId_p,
			 unsigned short chipId_p,
			 int dev )
{
	if (dev == 1)
	{
		thisVars->vendorID = vendorId_p;  /* remember for next chips */
		thisVars->chipID = chipId_p;

		if (vendorId_p == 0xEC)                  /* Samsung */
		{
			switch (chipId_p)
			{
				case 0x64:                         /* 2M */
				case 0xEA:
				vol.type = KM29N16000_FLASH ;
				vol.chipSize = 0x200000L;
				return TRUE;

				case 0xE5:
				case 0xE3:				/* 4M */
				vol.type = KM29N32000_FLASH;
				vol.flags |= BIG_PAGE;
				vol.chipSize = 0x400000L;
				return TRUE;

				case 0xE6:				/* 8M */
				vol.type = K9F6408X0C_FLASH;
				vol.flags |= BIG_PAGE;
				vol.chipSize = 0x800000L;
				return TRUE;

				case 0x76:
				vol.type = K9F1208_FLASH;  /*64M*/
				vol.flags |= BIG_PAGE;
				vol.chipSize = 0x04000000L;
				return TRUE;	  	
			}
		}	
		else if (vendorId_p == 0x8F)  		/* National */
		{
			switch (chipId_p)
			{
				case 0x64:                         /* 2M */
				vol.type = NM29N16_FLASH;
				vol.chipSize = 0x200000L;
				return TRUE;
			}
		}
		else if (vendorId_p == 0x98)			/* Toshiba */
		{
			vol.flags |= FULL_PAGE;             /* no partial page programming */

			switch (chipId_p)
			{
				case 0x64:                         /* 2M */
				case 0xEA:
				vol.type = TC5816_FLASH;
				vol.chipSize = 0x200000L;
				return TRUE;

				case 0x6B:                         /* 4M */
				case 0xE5:
				vol.type = TC5832_FLASH;
				vol.flags |= BIG_PAGE;
				vol.chipSize = 0x400000L;
				return TRUE;

				case 0xE6:				/* 8M */
				vol.type = TC5816_FLASH;
				vol.flags |= BIG_PAGE;
				vol.chipSize = 0x800000L;
				return TRUE;
			}
		}
	}
	else if( (vendorId_p == thisVars->vendorID) && (chipId_p == thisVars->chipID) )
	{
	return TRUE ;  /* dev != 0*/
	}

	return FALSE ;
}


/*----------------------------------------------------------------------*/
/*		          r e a d F l a s h I D				*/
/*									*/
/* Read vendor and chip IDs, count flash devices. Initialize relevant	*/
/* fields in data structures.						*/
/*									*/
/* Parameters:								*/
/*	vol		: Pointer identifying drive			*/
/*	interface	: Pointer to window.				*/
/*	dev		: dev chips were accessed before this one.	*/
/*									*/
/* Returns:                                                          	*/
/* 	TRUE if this media is supported, FALSE otherwise.		*/
/*									*/
/*----------------------------------------------------------------------*/

static int readFlashID (FLFlash vol, int dev)
{
	unsigned char vendorId_p, chipId_p;

	int id_code=0;

	nand_init();/*reset flash*/

	id_code = nand_get_id();  /*读出芯片的ID信息*/

	vendorId_p = (id_code&0xff000000)>>24;/*manufacture ID*/
	chipId_p = (id_code&0x00ff0000)>>16;/*device code*/
	
#ifdef DEBUG_PRINT
	printf("manufacture id:0x%x,device code:0x%x\n",vendorId_p,chipId_p);
#endif

	if (isKnownMedia(&vol, vendorId_p, chipId_p, dev) != TRUE)    /* no chip or diff.*/
	{
		return  FALSE ;         /* type of flash  */
	}

	/* set flash parameters*/
	if ( dev == 1 )
	{
		thisVars->pageAreaSize   = 0x100 * vol.interleaving;
		thisVars->pageSize = (vol.flags & BIG_PAGE ? 0x200 : 0x100) * vol.interleaving;
		thisVars->tailSize = (vol.flags & BIG_PAGE ? 16 : 8) * vol.interleaving;
		thisVars->pageMask = thisVars->pageSize - 1 ;
		vol.erasableBlockSize = PAGES_PER_BLOCK * thisVars->pageSize;
		thisVars->noOfBlocks = (unsigned short)( (vol.chipSize * vol.interleaving)
													/ vol.erasableBlockSize ) ;
	}

	return TRUE ;
}


/*----------------------------------------------------------------------*/
/*		     n a n d M T D I d e n t i f y			*/
/*									*/
/* Identify flash. This routine will be registered as the		*/
/* identification routine for this MTD.                                 */
/*									*/
/* Returns:                                                          	*/
/*	FLStatus: 0 on success, otherwise failed.			*/
/*									*/
/*----------------------------------------------------------------------*/
FLStatus nandMTDIdentify(FLFlash vol)
{
#ifdef DEBUG_PRINT
  printf("Debug: Entering K9F1208 identification routine\n");
#endif

  flSetWindowBusWidth(vol.socket,8);/* use 16-bits */
  flSetWindowSpeed(vol.socket,120);  /* 120 nsec. */
  flSetWindowSize(vol.socket,2);	/* 4 KBytes */

  vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];
  /* get pointer to buffer (we assume SINGLE_BUFFER is not defined) */
  thisVars->buffer = flBufferOf(flSocketNoOf(vol.socket));

  vol.interleaving = 1;
  vol.noOfChips = 1;  /* 以1为起始 */
  
  if(readFlashID(&vol, vol.noOfChips) != TRUE )
  {
  #ifdef DEBUG_PRINT
    printf("Debug: did not identify K9F1208 flash media.\n");
  #endif
    return flUnknownMedia;
  }
  
  /* Register our flash handlers */
  vol.write = nandMTDWrite;
  vol.erase = nandMTDErase;
  vol.read = nandMTDRead;
  vol.map = nandMTDMap;

  vol.flags |= SUSPEND_FOR_WRITE/*|NFTL_ENABLED*/;/*支持nand flash传输层*/

#ifdef DEBUG_PRINT
  printf("Debug: Identified K9F1208.\n");
#endif

  return flOK;
}


#if	TRUE
/*----------------------------------------------------------------------*/
/*                      f l R e g i s t e r N A N D 			*/
/*									*/
/* Registers this MTD for use						*/
/*									*/
/* Parameters:                                                          */
/*	None								*/
/*                                                                      */
/* Returns:								*/
/*	FLStatus	: 0 on success, otherwise failure		*/
/*----------------------------------------------------------------------*/

FLStatus flRegisterNAND(void)
{
  if (noOfMTDs >= MTDS)
    return flTooManyComponents;

  mtdTable[noOfMTDs++] = nandMTDIdentify;

  return flOK;
}
#endif	/* FALSE */

⌨️ 快捷键说明

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