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

📄 nandflash.c

📁 linux下nand flash驱动
💻 C
📖 第 1 页 / 共 2 页
字号:
			WRITE_BYTE(*buf++);
		}
		WRITE_CMD(PAGE_PROGRAM_CMD);
		while(!NANDFLASH_READY());
		if((Status = ReadStatus()) == PROGRAM_ERROR)
		{
			break;
		}
	}
	NANDFLASH_DISABLE();
	return Status;
}


/** 向NandFlash中写一块数据.
 **
 ** 输入参数: UCHAR *pbyBuf -- 要写入的数据的缓冲区
 ** ULONG nBlockNum -- 要写入的块号
 **
 ** 返回值: 0 -- 写成功; 其他 -- 读失败
 **
 ** @param  pbyBuf   要写入的数据的缓冲区
 ** @param  nBlockNum   要写入的块号
 ** @return whatever
 ** @author 吕剑国
 ** @version    v0.1 beta
 ** @see       
*/
UCHAR
NandProgramBlock(UCHAR *pbyBuf, ULONG nBlockNum)
{
	UWORD i, j;
	UCHAR Status = 0;
	ULONG nSector;

	// 擦除要写入的块
	if (EraseBlock(nBlockNum))
		return (PROGRAM_ERROR);

	nSector = nBlockNum << 5;
	NANDFLASH_ENABLE();
	
	for (i = 0; i < SECTOR_PER_BLOCK; i++) {
		WRITE_CMD(SDATA_INPUT_CMD);
		ADD_LATCH_ENABLE();
		WRITE_BYTE(0);
		WRITE_BYTE((UCHAR) nSector);
		WRITE_BYTE((UCHAR) (nSector >> 8));
		ADD_LATCH_DISABLE();

		nSector++;
		for(j = 0; j < 512; j++)
			WRITE_BYTE(*pbyBuf++);
		
		WRITE_CMD(PAGE_PROGRAM_CMD);
		while(!NANDFLASH_READY());
		if ((Status = ReadStatus()) == PROGRAM_ERROR)
			break;
	}
	
	NANDFLASH_DISABLE();
	return (Status);
}


void 
EraseNandFlash(void)
{
	UWORD i;

	for (i=0; i<BLOCK_NUM*2; i++)
	{
		EraseBlock(i);
	}
}

/*
UCHAR Tep_Buf1[512*32];
UCHAR Tep_Buf2[512*32];


UCHAR WriteSector1(UCHAR *buf, ULONG startsector, UWORD sectornum)//武东宏添加
{
	ULONG blocknum;
	UWORD front_sectornum,back_secternum,i;
	UWORD begin_block,end_block;
	ULONG front_startsector,back_startsector;
	UCHAR result;
	
	if(sectornum>0)
	{
		begin_block = startsector/32;
		end_block = (startsector+sectornum-1)/32;
		blocknum = end_block - begin_block+1;
		front_sectornum = startsector - begin_block*32;
		back_secternum = (end_block+1)*32 - startsector - sectornum;
		front_startsector = startsector - front_sectornum;
		back_startsector = startsector + sectornum;
		if(front_sectornum>0)
		{
			ReadSector1(Tep_Buf1, front_startsector, front_sectornum);
		}
		if(back_secternum>0)
		{
			ReadSector1(Tep_Buf2, back_startsector, back_secternum);
		}
		for(i=0;i<blocknum;i++)
		{
			result = EraseBlock(begin_block++);
			if (result)
				return (result);
		}
		if(front_sectornum>0)
		{
			result = ProgramSector(Tep_Buf1, front_startsector, front_sectornum);
			if (result)
				return (result);
		}
		if(back_secternum>0)
		{
			result = ProgramSector(Tep_Buf2, back_startsector, back_secternum);
			if (result)
				return (result);
		}

		result = ProgramSector(buf, startsector, sectornum);
	}

	return (result);
}
*/

UCHAR 
WriteSector1(UCHAR *buf, ULONG startsector, UWORD sectornum)
{
	NAND_CACHE_HEADER *pstHeader;
	ULONG nBlockNum, nSectorNum = startsector, nSectorOffsetInBlock, nSectors;
	SWORD sIndex;
	UCHAR cIndex, *pbyBuf = buf;

	do {
		nBlockNum = nSectorNum >> 5;
		nSectorOffsetInBlock = nSectorNum & (SECTOR_PER_BLOCK - 1);
		nSectors = (sectornum > (SECTOR_PER_BLOCK - nSectorOffsetInBlock) ? 
			(SECTOR_PER_BLOCK - nSectorOffsetInBlock) : sectornum);

		sIndex = IsBlockInCache(nBlockNum);
		// Found!!!
		if (sIndex >= 0) {
			pstHeader = (NAND_CACHE_HEADER *) (nand_cache_start + (sIndex << 6));
		}
		// Not Found!!!
		else {
			cIndex = LRUSearchBlock();
			pstHeader = (NAND_CACHE_HEADER *) (nand_cache_start + (cIndex << 6));

			if (pstHeader->bDirty) {
				NandProgramBlock(pstHeader->pSectorBuf, pstHeader->nBlockNum);
			}

			pstHeader->bUsed = 1;
			pstHeader->nUseCount = 0;
			pstHeader->bDirty = 1;
			pstHeader->nBlockNum = nBlockNum;
			NandReadBlock(pstHeader->pSectorBuf, nBlockNum);
		}

		NandBufferCopy((UCHAR *) (pstHeader->pSectorBuf + (nSectorOffsetInBlock << 9)), pbyBuf, 
			nSectors << 9);
		pbyBuf += nSectors << 9;
		sectornum -= nSectors;
		nSectorNum += nSectors;
		
		pstHeader->nTickCount = nand_cache_tick_count++;
		pstHeader->nUseCount++;
	} while (sectornum > 0);
	
	return (NOERR);
}



// ----------------------------------------------------------------------
/*
//UCHAR printread = 0;
UWORD Exec_ATAPI_Command1()		//Writed by zhangjj
{
	ULONG tmp = 0;
	UCHAR i;
	UWORD secnum;
	ULONG secindex;
	UCHAR opcode;
	
	//ddfor (tmp=0; tmp<10000; tmp++);
	opcode = TPBulk_CommandBlock_bAtapi_CommandPackage0;
	
	switch(opcode)
	{
		//ATAPI read command,read data from NANDFlash
		case ATAPI_READ10:
			secnum = TPBulk_CommandBlock_bAtapi_CommandPackage7;
			secnum <<=8;
			secnum |= TPBulk_CommandBlock_bAtapi_CommandPackage8;
			
			//Get the start sector 
			secindex = TPBulk_CommandBlock_bAtapi_CommandPackage2;
			secindex <<=8;
			secindex |= TPBulk_CommandBlock_bAtapi_CommandPackage3;
			secindex <<=8;
			secindex |= TPBulk_CommandBlock_bAtapi_CommandPackage4;
			secindex <<=8;
			secindex |= TPBulk_CommandBlock_bAtapi_CommandPackage5;
			
//			printk("secindex = %x, secnum = %x\n", secindex, secnum);	
//			for (i=0; i<32; i++)
//			{
//				Buffer_Pointer[i] = 0;
//			}
			ReadSector1(Buffer_Pointer, secindex, secnum);
			//if (printread)
//			{
//			for (i=0; i<12; i++)
//				printk("%02x\t", CBWBuf[15+i]);
//			printk("\n-------------");
//				printread = 0;

//			for (i=0; i<32; i++)
//				printk("%02x\t", Buffer_Pointer[i]);
//			printk("\n");
//			}
			break;		
		//ATAPI Write command,Write data to NANDFlash
		case ATAPI_WRITE10:
			secnum = TPBulk_CommandBlock_bAtapi_CommandPackage7;
			secnum <<=8;
			secnum |= TPBulk_CommandBlock_bAtapi_CommandPackage8;
			
			//Get the start sector 
			secindex = TPBulk_CommandBlock_bAtapi_CommandPackage2;
			secindex <<=8;
			secindex |= TPBulk_CommandBlock_bAtapi_CommandPackage3;
			secindex <<=8;
			secindex |= TPBulk_CommandBlock_bAtapi_CommandPackage4;
			secindex <<=8;
			secindex |= TPBulk_CommandBlock_bAtapi_CommandPackage5;

//			printk("secindex = %x, secnum = %x\n", secindex, secnum);	
//			for (i=0; i<12; i++)
//				printk("%02x\t", CBWBuf[15+i]);
//			printk("\n---------------");
			WriteSector1(Buffer_Pointer, secindex, secnum);
//			for (i=0; i<32; i++)
//				printk("%02x\t", Buffer_Pointer[i]);
//			printk("\n");
//			printread = 1;
			break;
		case ATAPI_READFORMATCAPA:
			i=0;	
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x10;

			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0xff;
			Buffer_Pointer[i++] = 0x00;

			Buffer_Pointer[i++] = 0x01;

			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x02;
			Buffer_Pointer[i++] = 0x00;

			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0xff;
			Buffer_Pointer[i++] = 0x00;

			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x02;
			Buffer_Pointer[i++] = 0x00;
			//Buffer_Pointer[i++] = 0xd0;
			break;
		case ATAPI_RAEDCAPACITY:		//需要底层提供读NANDFlash容量的函数
			i=0;	
			Buffer_Pointer[i++] = 0x00;
			//Buffer_Pointer[i++] = 0x01;
			//Buffer_Pointer[i++] = 0x00;
			//Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0xff;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x02;
			Buffer_Pointer[i++] = 0x00;
			break;
		case ATAPI_INQUIRE:			//Command 0x12:to request the configuration of the NANDFlash
			i=0;	
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x80;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x01;
			Buffer_Pointer[i++] = 0x75;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x00;
			Buffer_Pointer[i++] = 0x20;
			Buffer_Pointer[i++] = 'E';
			Buffer_Pointer[i++] = '-';
			Buffer_Pointer[i++] = 'W';
			Buffer_Pointer[i++] = 'O';
			Buffer_Pointer[i++] = 'R';
			Buffer_Pointer[i++] = 'L';
			Buffer_Pointer[i++] = 'D';
			Buffer_Pointer[i++] = 0x20;
			Buffer_Pointer[i++] = 'N';
			Buffer_Pointer[i++] = 'A';
			Buffer_Pointer[i++] = 'N';
			Buffer_Pointer[i++] = 'D';
			Buffer_Pointer[i++] = '-';
			Buffer_Pointer[i++] = 'F';
			Buffer_Pointer[i++] = 'L';
			Buffer_Pointer[i++] = 'A';
			Buffer_Pointer[i++] = 'S';
			Buffer_Pointer[i++] = 'H';
			Buffer_Pointer[i++] = '1';
			Buffer_Pointer[i++] = '.';
			Buffer_Pointer[i++] = '0';
			Buffer_Pointer[i++] = 0x20;
			Buffer_Pointer[i++] = 0x20;
			Buffer_Pointer[i++] = 0x33;
			Buffer_Pointer[i++] = 0x31;
			Buffer_Pointer[i++] = 0x61;
			Buffer_Pointer[i++] = 0x59;
			break;
		case ATAPI_REQUESTSENSE:	//Command 0x03:allows the host to request status and sense data from the PocketZip drive.
			for( i=0; i<TPBulk_CommandBlock_bAtapi_CommandPackage4; i++ )
			{
				Buffer_Pointer[i] = 0;
			}
			Buffer_Pointer[0] = 0x70;
			break;
		case ATAPI_MODESENSE5A:
			Buffer_Pointer[0] = 0;
			Buffer_Pointer[1] = 0;
			Buffer_Pointer[2] = 0;
			Buffer_Pointer[3] = 0;
			Buffer_Pointer[4] = 0;
			Buffer_Pointer[5] = 0;
			Buffer_Pointer[6] = 0;
			Buffer_Pointer[7] = 0;
			break;
		case ATAPI_NONSENSE:	//Command 0x06:Non-sense is used to report vendor specific drive and disk data including current status and diagnostic information.
			switch(TPBulk_CommandBlock_bAtapi_CommandPackage2)
			{			//*****Allocation Length is not used
				case 0x00:	//Supported Page Codes Page (00h)
					//Non-Sense Page Header
					Buffer_Pointer[0] = 0;
					Buffer_Pointer[1] = 4;
					
					Buffer_Pointer[2] = 0x00;
					Buffer_Pointer[3] = 0x01;
					Buffer_Pointer[4] = 0x02;
					Buffer_Pointer[5] = 0x03;
					break;
				case 0x01:	//Format Data page (Page 01h)
					//Non-Sense Page Header
					Buffer_Pointer[0] = 1;
					Buffer_Pointer[1] = 0x56;

					Buffer_Pointer[2] = 0x01;
					Buffer_Pointer[3] = 0x00;
					Buffer_Pointer[4] = 0x00;
					Buffer_Pointer[5] = 0x00;
					Buffer_Pointer[6] = 0x00;
					Buffer_Pointer[7] = 0x00;
					Buffer_Pointer[8] = 0x00;
					Buffer_Pointer[9] = 0x00;	
					Buffer_Pointer[10] = 0x00;	//-
					Buffer_Pointer[11] = 0x00;	//w
					Buffer_Pointer[12] = 0x00;	//o
					Buffer_Pointer[13] = 0x00;	//r
					Buffer_Pointer[14] = 0x00;	//l
					Buffer_Pointer[15] = 0x00;	//d
					Buffer_Pointer[16] = 0x00;
					break;
				case 0x02:	//Cartridge Status page (Page 02h)
					//Non-Sense Page Header
					Buffer_Pointer[0] = 2;
					Buffer_Pointer[1] = 62;
					
					Buffer_Pointer[2] = 0x00;
					Buffer_Pointer[3] = 0x01;
					Buffer_Pointer[4] = 0x00;
					Buffer_Pointer[5] = 0x00;
					Buffer_Pointer[6] = 0x00;
					Buffer_Pointer[7] = 0x00;
					Buffer_Pointer[8] = 0x00;
					Buffer_Pointer[9] = 0x00;	
					Buffer_Pointer[10] = 0x00;	//-
					Buffer_Pointer[11] = 0x02;	//w
					Buffer_Pointer[12] = 0x00;	//o
					Buffer_Pointer[13] = 0x00;	//r
					Buffer_Pointer[14] = 0x00;	//l
					Buffer_Pointer[15] = 0x00;	//d
					Buffer_Pointer[16] = 0x00;
					Buffer_Pointer[17] = 0x00;	
					Buffer_Pointer[18] = 0x00;
					Buffer_Pointer[29] = 0x00;
					Buffer_Pointer[20] = 0x00;
					
					for( i=21; i<64; i++ )
					{
						Buffer_Pointer[i] = 0;
					}
					break;
			}
		case ATAPI_MODESELECT55:	//Command 0x15:Mode Select(0x15),specify media or device parameters
			break;		//Is not use to NANDFalsh
		case ATAPI_TESTUNIT:	//Command 0x00:Test unit Ready tests the readiness of the drive for disk access.
			for( i=0; i<TPBulk_CommandBlock_bAtapi_CommandPackage4; i++ )
			{
				Buffer_Pointer[i] = 0;
			}
			break;
		case 0x1e:	//Command 0x00:Test unit Ready tests the readiness of the drive for disk access.
			for( i=0; i<TPBulk_CommandBlock_bAtapi_CommandPackage4; i++ )
			{
				Buffer_Pointer[i] = 0;
			}
			break;
		case 0x2f:	////Command 0x2f: Verify Packet Command confirms that the drive wrote the data correctly in the requested LBAs.
			//for (i=0; i<12; i++)
			//	printf("%02x\t", CBWBuf[15+i]);
			//printf("\n");
			break;		//Is not use to NANDFalsh
	}
	return 0;
}
*/

// That's all

⌨️ 快捷键说明

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