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

📄 nandmtd.c

📁 44b0 vxwork5.5 bsp 支持基于flash 39VF3201的tffs驱动
💻 C
字号:
#include "tffs/flflash.h"#include "tffs/reedsol.h"#define WRITE_COMMAND(val)  (*(volatile UINT8 *)0x02000002 = (UINT8)(val)) /* CLE = A20 */#define WRITE_DATA(val)     (*(volatile UINT8 *)0x02000000 = (UINT8)(val)) /* CE = 0 */#define READ_DATA(val)      val = *(volatile UINT8 *)0x02000000 /* CE = 0 */#define NAND_EN()	  	rPDATC &=~(0x200)#define NAND_DS()		rPDATC |=0x0200#define rPCONC		(*(volatile UINT32 *)0x1d20010)#define rPDATC		(*(volatile UINT32 *)0x1d20014)#define PAGES_PER_BLOCK     32          			/* 16 pages per block on a single chip*//* Flash IDs*/#define K9F2808U0C			0xec73/* Flash commands:*/#define SERIAL_DATA_INPUT   0x80#define READ_MODE_A         0x00#define READ_MODE_B	   		0x01#define READ_MODE_2         0x50#define RESET_FLASH         0xff#define SETUP_WRITE         0x10#define SETUP_ERASE         0x60#define CONFIRM_ERASE     	0xd0#define READ_STATUS         0x70#define READ_ID             0x90#define FAIL                0x01					#undef DEBUG_PRINT         printf/* commands for moving flash pointer to areeas A,B or C of page*/typedef enum  { AREA_A = READ_MODE_A, AREA_B = READ_MODE_B, AREA_C = READ_MODE_2 } PointerOp;/* customization for this MTD*/typedef struct {  unsigned short	vendorID;  unsigned short	chipID;  unsigned short   	pageSize ;              /* all....................*/  unsigned short   	pageMask ;              /* ...these...............*/  unsigned short   	pageAreaSize ;          /* .......variables.......*/  unsigned short   	tailSize ;              /* .............interleave*/  unsigned short   	noOfBlocks ;            /* total erasable blocks in flash device*/  FLBuffer  		*buffer;				/* buffer for map through buffer */} Vars;UINT8 mapBuffer[6000];static Vars mtdVars[DRIVES];#define thisVars   ((Vars *) vol.mtdVars) void flashPinInit(){	rPCONC&=~(0x0f<<16);	rPCONC|=0x01<<18;}LOCAL void WRITE_ADDRESS(UINT8 val){/*	UINT8 temp;	char i;	temp=0;	for(i=0;i<8;i++)	{		temp<<=1;		if(val&0x01)			temp|=0x01;		val>>=1;	}*/	*(volatile UINT8 *)0x02000004 = val; }	#define TFFS_DEBUG#ifdef TFFS_DEBUGSTATUS checkBlock(short blockNum){  int j;  UINT32 address;  UINT8 data;  NAND_EN();	  for(j=0;j<2;j++)	{		address=0x4000*blockNum+0x200*j+0x05;	      WRITE_COMMAND(READ_MODE_2);    	      WRITE_ADDRESS((UINT8)address);            WRITE_ADDRESS((UINT8)(address >> 9));            WRITE_ADDRESS((UINT8)(address >> 17));            waitForReady();            READ_DATA(data);            if(data != 0xFF)            {	           	printf("Block %d is a invalid block\n",blockNum );            					return ERROR;            }	}	NAND_DS();	return OK;}short checkAllBlock(void){    int i;    short badBlockNum=0;    for(i=0; i<1024; i++)    {			if(checkBlock(i)==ERROR) badBlockNum++;	    }    return badBlockNum;}void readFlash(int address, UINT8 *buffer,int length, int mode){    int i, bit8;    NAND_EN();    if(mode == 0)    {    bit8 = (unsigned short)address & 0x100;    if(bit8 == 0)        WRITE_COMMAND(READ_MODE_A);    else        WRITE_COMMAND(READ_MODE_B);    }    else        WRITE_COMMAND(READ_MODE_2);    WRITE_ADDRESS(address&0xff);    WRITE_ADDRESS((address >> 9)&0xff);    WRITE_ADDRESS((address >> 17)&0xff);    waitForReady();    for(i=0; i<length; i++)    {        READ_DATA(buffer[i]);    }	NAND_DS();}FLStatus writeFlash(int address, UINT8 *buffer,int len,int mode){    int i, bit8;       /*printf("readFlash: address = 0x%x, length = %d\n", address, length);*/    NAND_EN();        if(mode == 0)    {    bit8 = (unsigned short)address & 0x100;    if(bit8 == 0)        WRITE_COMMAND(READ_MODE_A);    else        WRITE_COMMAND(READ_MODE_B);    }    else        WRITE_COMMAND(READ_MODE_2);/*  address += 1; */    WRITE_COMMAND(SERIAL_DATA_INPUT);    WRITE_ADDRESS((unsigned char)address);    WRITE_ADDRESS((unsigned char)(address >> 9));    WRITE_ADDRESS((unsigned char)(address >> 17));    for(i=0; i<len; i++)    {        WRITE_DATA(buffer[i]);       /* printf("WriteFlash: data = 0x%x\n", data);*/    }    WRITE_COMMAND(SETUP_WRITE);    waitForReady();	NAND_DS();    if(readStatus() & FAIL)      return flWriteFault;}void flashErase(int blockNo){    unsigned short pageNo = blockNo * PAGES_PER_BLOCK ;    NAND_EN();    WRITE_COMMAND(SETUP_ERASE);    WRITE_ADDRESS((unsigned char)pageNo);  /* A9 ~ A16 */    WRITE_ADDRESS((unsigned char)(pageNo >> 8));            /* A17 ~ A22 */    WRITE_COMMAND(CONFIRM_ERASE);    waitForReady();    if(readStatus() & FAIL)	{		printf("block %d failed!\n",blockNo);      	return flWriteFault;	}    NAND_DS();	}void flashEraseAll(void){    int i;    for(i=0; i<1024; i++)    {    	flashErase(i);    }}#endifLOCAL FLBoolean waitForReady (void){   int val;   do    {        val=rPDATC;        val &= 0x100;    /* R/B PORTE.0 */     } while(val == 0);    return TRUE; }LOCAL void makeCommand (PointerOp *cmd, CardAddress address, int modes){    int bit8;    if (modes & EXTRA)      *cmd = AREA_C;    else      {       	bit8 = (unsigned short)address & 0x100;      	if(bit8 == 0)      	  *cmd = AREA_A;      	else      	  *cmd = AREA_B;      }}LOCAL void setAddress(CardAddress address ){  WRITE_ADDRESS((unsigned char)address);  WRITE_ADDRESS((unsigned char)(address >> 9));  WRITE_ADDRESS((unsigned char)(address >> 17));}LOCAL void readCommand (PointerOp  cmd, CardAddress address){  WRITE_COMMAND (cmd);       /* move flash pointer to respective area of the page*/  setAddress (address);  waitForReady();}LOCAL void writeCommand (PointerOp  cmd, CardAddress address){  WRITE_COMMAND(cmd);       /* move flash pointer to respective area of the page  */  WRITE_COMMAND(SERIAL_DATA_INPUT);       /* start data loading for write  */  setAddress (address);}LOCAL UINT8 readStatus(void){  UINT8 chipStatus ;  WRITE_COMMAND(READ_STATUS);  READ_DATA(chipStatus);  return chipStatus;}UINT8 statusRead(void){  UINT8 chipStatus ;  NAND_EN();  WRITE_COMMAND(READ_STATUS);  READ_DATA(chipStatus);  NAND_DS();  return chipStatus;}LOCAL FLStatus writeExecute (void){   UINT8 chipStatus;  WRITE_COMMAND(SETUP_WRITE);             /* execute page program*/  WRITE_COMMAND(READ_STATUS);  waitForReady();  READ_DATA(chipStatus);  if(chipStatus & FAIL)    return flWriteFault ;  return flOK ;}LOCAL FLStatus readOnePage (FLFlash vol,			     CardAddress address,  /* starting flash address*/			     UINT8 FAR1 *buffer,     /* target buffer */			     int length,           /* bytes to read */			     int modes)            /* EDC flag etc.*/{  FLStatus  status = flOK;  PointerOp   cmd;  UINT8 FAR1 *tempBuffer;  int oldLenth;  UINT8 readBuffer[512];  tempBuffer=buffer;  oldLenth=length;  /* move flash pointer to areas A,B or C of page*/retry:  makeCommand (&cmd, address, modes);  taskLock();  NAND_EN();  readCommand (cmd, address);   while(length-->0)		READ_DATA(*buffer++);  readFlash(address,readBuffer,oldLenth,0);  taskUnlock();  if(memcmp(tempBuffer,readBuffer,oldLenth)==0)	  return status;  else  {	  printf("read error, retry!\n");  	  buffer=tempBuffer;	  length=oldLenth;  	goto retry;  }	}LOCAL FLStatus writeOnePage(FLFlash vol,			     CardAddress address,    /* target flash addres  */			     const UINT8 FAR1 *buffer, /* source RAM buffer   */			     int length,             /* bytes to write (up to BLOCK) */			     int modes)              /* OVERWRITE, EDC flags etc.  */{  FLStatus    status=flOK;  PointerOp cmd;  UINT8 FAR1 *tempBuffer;  UINT8 readBuffer[512];  int oldLenth;  tempBuffer=buffer;  oldLenth=length;  if (flWriteProtected(vol.socket))    return flWriteProtect;  /* move flash pointer to areas A,B or C of page  */  makeCommand (&cmd, address, modes);  taskLock();  NAND_EN();  writeCommand (cmd, address);  while(length-->0)	 WRITE_DATA(*buffer++);  status = writeExecute();  readFlash(address,readBuffer,oldLenth,0);  taskUnlock();  if(memcmp(tempBuffer,readBuffer,oldLenth)!=0)	{		printf("write %08x error!\n",address);		status=flWriteFault;	}	return status;}LOCAL FLStatus nandMTDRead(  FLFlash vol,			 CardAddress address, /* target flash address */			 const FAR1 *buffer,    /* source RAM buffer  */			 int length,          /* bytes to write      */			 int modes)           /* Overwrite, EDC flags etc. */{  char FAR1 *temp;  int readNow;		      /* read in sectors; first and last might be partial */  int page = modes & EXTRA ? 16 : 512;  readNow = page - ((unsigned short)address & (page - 1));  temp = (UINT8 FAR1 *)buffer;  for ( ; length > 0 ; )  {    if (readNow > length) 	/* 如果要读的长度小于一个页面中偏移地址之后的空间大小 */      readNow = length;     /* 那要读的就是该长度 04-8-6 */						   							 /* turn off EDC on partial block read*/   /* 如果要读的长度大于一个页面的大小,就先读一个页面 */#ifdef DEBUG_PRINT  DEBUG_PRINT("READ: address = 0x%x, length = 0x%x , 0x%x\n", address, readNow,modes);#endif      checkStatus(readOnePage(&vol, address, temp, readNow,				(readNow != SECTOR_SIZE ? (modes & ~EDC) : modes)) );      length -= readNow;      address += readNow;      temp += readNow;    /* align at sector */      readNow = page;  }  return flOK ;}void resetFlash(void){    NAND_EN();        WRITE_COMMAND(RESET_FLASH);    waitForReady();    NAND_DS();}LOCAL FLStatus nandMTDWrite( FLFlash vol,			 CardAddress address,       /* target flash address*/			 const FAR1 *buffer,    /* source RAM buffer  */			 int length,                /* bytes to write      */			 int modes)                 /* Overwrite, EDC flags etc.*/	{  int writeNow;  const UINT8 FAR1 *temp;  FLStatus      status = flOK;  /* write in sectors; first and last might be partial*/  int page = modes & EXTRA ? 16 : 512;  writeNow = page - ((unsigned short)address & (page - 1));  temp = (const UINT8 FAR1 *)buffer;  for ( ; length > 0 ; )  {    if (writeNow > length)      writeNow = length; 	  status = writeOnePage(&vol, address, temp, writeNow,	  writeNow != 512 ? (modes & ~EDC) : modes);#ifdef DEBUG_PRINT  DEBUG_PRINT("WRITE: address = 0x%x, length = 0x%x, mode = %d\n", address, writeNow, modes);#endif	if(status!=flOK)	{		printf("write flash disk failted!\n");		return flWriteFault;	}    length -= writeNow;    address += writeNow;    temp += writeNow;    /* align at sector */    writeNow = page;  }  return flOK ;}LOCAL FLStatus nandMTDErase( FLFlash vol,			 int blockNo,              /* start' block (0 .. chipNoOfBlocks-1)*/			 int blocksToErase)        /* Number of blocks to be erased */{  int i;  FLStatus status   = flOK;  if (flWriteProtected(vol.socket))    	return flWriteProtect; /* blockNo %= thisVars->noOfBlocks; */                       /* within flash device  */  if ( blockNo + blocksToErase > thisVars->noOfBlocks )    /* accross device boundary */    return flBadParameter;    #ifdef DEBUG_PRINT      DEBUG_PRINT("firstBlock = 0x%x, numOfBlock = 0x%x\n", blockNo, blocksToErase);   #endif  for ( i=0; i < blocksToErase; i++, blockNo++ )  {    unsigned short pageNo = blockNo * PAGES_PER_BLOCK ;    taskLock();     	NAND_EN();        WRITE_COMMAND(SETUP_ERASE);    WRITE_ADDRESS((unsigned char)pageNo);        /* A9 ~ A16 */    WRITE_ADDRESS((unsigned char)(pageNo >> 8));   /* A17 ~ A22 */    WRITE_COMMAND(CONFIRM_ERASE);    waitForReady();    if(readStatus() & FAIL)    {          status = flWriteFault;  /* erase operation failed */    }  #ifdef DEBUG_PRINT   DEBUG_PRINT("ERASE: blockNo = 0x%x\n", blockNo); /*   DEBUG_PRINT("ERASE: blockNo = 0x%x\n", blockNo); */  #endif    if(checkBlock(blockNo)==ERROR)     {		taskUnlock();    	status=flWriteFault;    }	    	taskUnlock();	    if (status != flOK)       /* reset flash device and abort */    {                                  #ifdef DEBUG_PRINT      DEBUG_PRINT("Debug: erase failed in K9F2808U0C.\n");    #endif      NAND_EN();          WRITE_COMMAND(RESET_FLASH);      waitForReady();      NAND_DS();      break ;    }  }       /* block loop */  return status;}LOCAL void FAR0 * nandMTDMap ( FLFlash vol,			    CardAddress address,			    int length ){  nandMTDRead(&vol,address,mapBuffer,length, 0);  vol.socket->remapped = 1;  return (void FAR0 *)mapBuffer;}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 0x73:                         	/*SAMSUNG K9F2808U0C				 /* 16M */		vol.type=K9F2808U0C; 		vol.chipSize=0x1000000L;				vol.flags|=BIG_PAGE; 		return TRUE; 	default:		return FALSE;      }    } }  else		     /* dev != 0*/ 	 if( (vendorId_p == thisVars->vendorID) && (chipId_p == thisVars->chipID) )    	 return TRUE ;  return FALSE ;}LOCAL int readFlashID (FLFlash vol, int dev){  unsigned char vendorId_p, chipId_p;  NAND_EN();  WRITE_COMMAND(RESET_FLASH);  waitForReady();  WRITE_COMMAND(READ_ID);  WRITE_ADDRESS(0x00);  /* Address. 1cycle */  READ_DATA(vendorId_p);  READ_DATA(chipId_p);/*  printf("vendorId=%04x chipId=%04x\n",vendorId_p,chipId_p); */  NAND_DS();  if (isKnownMedia(&vol, vendorId_p, chipId_p, dev) != TRUE)    /* no chip or diff.*/    return  FALSE ;                                         /* type of flash  */  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 ;}FLStatus nandMTDIdentify(FLFlash vol){#ifdef DEBUG_PRINT  DEBUG_PRINT("Debug: Entering K9F6408U0C identification routine\n");#endif  flSetWindowBusWidth(vol.socket,8);/* use 8-bits */  flSetWindowSpeed(vol.socket,120);  /* 120 nsec. */  flSetWindowSize(vol.socket,2);	/* 4 KBytes */  vol.mtdVars = &mtdVars[flSocketNoOf(vol.socket)];  thisVars->buffer = flBufferOf(flSocketNoOf(vol.socket));   vol.interleaving = 1;  vol.noOfChips = 1;  /* 以1为起始 */  if(readFlashID(&vol, vol.noOfChips) != TRUE )  {  #ifdef DEBUG_PRINT    DEBUG_PRINT("Debug: did not identify K9F2808U0C 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;#ifdef DEBUG_PRINT  DEBUG_PRINT("Debug: Identified K9F2808U0C.\n");#endif  return flOK;}

⌨️ 快捷键说明

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