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

📄 nand_mtd.c

📁 8032底层驱动部分。因为可以移植 所以单独来拿出来
💻 C
📖 第 1 页 / 共 5 页
字号:

	 readfifo_512((kal_uint32 *)Data, NULL, 0, 128);

	 /* ECC info generated by NFI  */
	 error_detect = *NFI_ERRDET & 0x01;
	 sym0_address = *NFI_SYM0_ADDR;
	 sym0_data = *NFI_SYM0_DAT;
	 *NFI_OPCON = 0x0;

	 /* read spare if SpareFlag==1 */
	 if (SpareFlag && (Spare==NULL))
		 ReadSpare_512_default(DriveData, PageIndex, (Data+512));
	 else if (SpareFlag && (Spare!=NULL))
		 ReadSpare_512_default(DriveData, PageIndex, Spare);

	/* ECC check: two-bit error detection or one-bit error correction */
	 if (error_detect)
	 {
		 return MTD_STATUS_ERROR;
	 }

	 if (sym0_address != 0)
	 {
		 mybuffer[sym0_address >> 2] ^= sym0_data;
		 return MTD_STATUS_CORRECTED;
	 }

	return MTD_STATUS_NO_ERROR;

}	/*  End of ReadPage_512 */

/*******************************************************************************/
#ifdef _NAND_FLASH_BOOTING_
int NFB_ReadPage_512_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 * ECC_pointer = NULL;
	kal_uint16 i, error_bit_address;
	kal_uint32 tmp_ecc[16/sizeof(kal_uint32)];
	static kal_uint32 parity[4], parity_old[4]; // for ECC detection/correct; use static variable for debug
	static kal_uint32 exclusive_parity[4];
	static kal_uint16 ex_check_parity[2];
   static kal_uint8  update_data;

	/* NFI setting */
	*NFI_FIFOCON = RESET;
   *NFI_CON = AUTOECC_DEC_EN;	  				// for NFI ECC decoding
	*NFI_CMD = RD_1ST_CMD;						// read command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 8;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// number of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_OPCON = BURST_RD;						// set burst read

	readfifo_512((kal_uint32 *)Data, NULL, 0, 128);

	 /* ECC parity bits generated by NFI */
   while (!(*NFI_FIFOCON & WR_EMPTY_MASK));
   
   parity[0] = *NFI_PAR0;
   parity[0] |= (*NFI_PAR1) << 16;

   *NFI_OPCON = 0x0;

   /*Read spare to local buffer if SpareFlag==0;
     The spare area must be read for ECC detection/correction */  
   ReadSpare_512_default(DriveData, PageIndex, (BYTE *)tmp_ecc);
   ECC_pointer = tmp_ecc;

   /* ECC check: two-bit error detection or one-bit error correction */
   parity_old[0] = *(ECC_pointer+2);    

   exclusive_parity[0] = (parity[0]^parity_old[0])&0x0fff0fff;
   
   // process ECC block
   for (i=0; i<1; i++)
   {
      if (exclusive_parity[i]==0)
   	   continue;
   
      // ECC correct
      ex_check_parity[0] = exclusive_parity[i]&0x0fff;
      ex_check_parity[1] = (exclusive_parity[i]>>16)&0x0fff;
   
      if ( ((ex_check_parity[0]^ex_check_parity[1])&0x0fff)==0x0fff )
      { 
         // one-bit correctable error
         error_bit_address = ex_check_parity[1]&(~ex_check_parity[0]); // 16 bits
         update_data = Data[512*i+(error_bit_address>>3)];
         update_data = update_data^(1<<(kal_uint8)(error_bit_address&0x0007));
         Data[512*i+(error_bit_address>>3)] = update_data;
      }
      else
      {
         return FS_DATA_ERROR;
      }
   }
   
   return FS_NO_ERROR;
   
}	/*  End of ReadPage_512 */
#endif

/*******************************************************************************/
int ProgramSpare_512_default (void * DriveData, DWORD PageIndex, BYTE * Data)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status;

	cmd_sparepointer();

	if (nfi_egid && use_interrupt == KAL_TRUE)
	   *NFI_INTR_EN = WR_COMPLETE_EN;

	*NFI_CON = SW_PROGSPARE_EN;
	*NFI_CMD = INPUT_DATA_CMD;					// Issue data input command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 8;
	*NFI_ADDNOB = D->flash_info.address_cycle ;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);
	*NFI_OPCON = BURST_WR;						// set burst write

	writefifo_512((kal_uint32*)Data, NULL, ECC_WHOLE, 4);	// option:write data without dma

	while (!((status = read_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;
}	/*  End of ProgramSpare_512 */

/*******************************************************************************/
int ReadSpare_512_default(void * DriveData, DWORD PageIndex, BYTE * Data)	//need modification
{
	NAND_FLASH_DRV_DATA * D = DriveData;


	*NFI_CON = SW_PROGSPARE_EN;						// program spare area enable
	*NFI_CMD = RD_SPARE_CMD;								// read spare command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 8;
	// set up start address, A7-A4 don't care, A3-A0 is the offset whthin the spare area
	*NFI_ADDNOB = D->flash_info.address_cycle;		 // number of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_OPCON = BURST_RD;								// set burst read

	readfifo_512((kal_uint32*)Data, NULL, 0, 4);

	return FS_NO_ERROR;

} /*  End of ReadSpare_512 */


/*******************************************************************************
 *  2K page-size MTD sub functions for defualt device
 *******************************************************************************/

int ProgramPage_2K_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE ECCFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status;


	cmd_resetpointer();

	if (nfi_egid != 0 && use_interrupt == KAL_TRUE)
		*NFI_INTR_EN = WR_COMPLETE_EN;

	*NFI_FIFOCON = RESET;
	*NFI_CON = SW_PROGSPARE_EN;
	*NFI_CMD = INPUT_DATA_CMD;					// Issue data input command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 16;
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = PageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_OPCON = BURST_WR;						// set burst write

	writefifo_2K((kal_uint32*)Data, (kal_uint32*)Spare, ECCFlag, 512);	 // option:write data without dma

	while (!((status = read_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;
} /*  End of ProgramPage */


/*******************************************************************************/
int ReadPage_2K_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag, BYTE ECCFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 * ECC_pointer = NULL;
	kal_uint16 i, error_bit_address, istart = 0, iend = 0;
	static kal_uint32 parity[4], parity_old[4]; // for ECC detection/correct; use static variable for debug
	static kal_uint32 exclusive_parity[4];
	static kal_uint16 ex_check_parity[2];
   static kal_uint8  update_data;
        kal_uint32 status = MTD_STATUS_NO_ERROR;

	/* NFI setting */
	*NFI_FIFOCON = RESET;
	*NFI_CON = 0x0;
	*NFI_CMD = RD_1ST_CMD;						// read command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 16;
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = PageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// number of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_CMD = RD_2ND_CYCLE_CMD;
	while (*NFI_PSTA & STATUS_CMD);

	*NFI_OPCON = BURST_RD;						// set burst read

	 readfifo_2K((kal_uint32 *)Data, NULL, 0, 512);

	 /* ECC parity bits generated by NFI */
	 while (!(*NFI_FIFOCON & RD_EMPTY_MASK) || (*NFI_PSTA & STATUS_DATAR));
	 parity[0] = *NFI_PAR0;
	 parity[0] |= (*NFI_PAR1) << 16;
	 parity[1] = *NFI_PAR2;
	 parity[1] |= (*NFI_PAR3) << 16;
	 parity[2] = *NFI_PAR4;
	 parity[2] |= (*NFI_PAR5) << 16;
	 parity[3] = *NFI_PAR6;
	 parity[3] |= (*NFI_PAR7) << 16;

	 *NFI_OPCON = 0x0;

	 /* Read spare area to argument buffer if SpareFlag==1,
		while read spare to local buffer if SpareFlag==0;
		The spare area must be read for ECC detection/correction */
	 if (SpareFlag && (Spare==NULL))
	 {
		 ReadSpare_2K_default(DriveData, PageIndex, (Data+2048));
		 ECC_pointer = (kal_uint32 *)(Data+2048);
	 }
	 else if (SpareFlag && (Spare!=NULL))
	 {
		 ReadSpare_2K_default(DriveData, PageIndex, Spare);
		 ECC_pointer = (kal_uint32 *)Spare;
	 }
	 else
	 {
		kal_uint32 tmp_ecc[64/sizeof(kal_uint32)];

		ReadSpare_2K_default(DriveData, PageIndex, (BYTE *)tmp_ecc);
		ECC_pointer = tmp_ecc;
	 }

	 /* ECC check: two-bit error detection or one-bit error correction */
	 parity_old[0] = *(ECC_pointer+2);
	 parity_old[1] = *(ECC_pointer+6);
	 parity_old[2] = *(ECC_pointer+10);
	 parity_old[3] = *(ECC_pointer+14);

	 exclusive_parity[0] = (parity[0]^parity_old[0])&0x0fff0fff;
	 exclusive_parity[1] = (parity[1]^parity_old[1])&0x0fff0fff;
	 exclusive_parity[2] = (parity[2]^parity_old[2])&0x0fff0fff;
	 exclusive_parity[3] = (parity[3]^parity_old[3])&0x0fff0fff;

	 // process ECC block
	 if(ECCFlag == ECC_FIRST_HALF)
	 {
	    istart = 0;
	    iend = 2;
	 }
	 else if(ECCFlag == ECC_SECOND_HALF)
	 {
	    istart = 2;
	    iend = 4;
	 }
	 else if(ECCFlag == ECC_WHOLE)
	 {
	    istart = 0;
	    iend = 4;
	 }
	 else if(ECCFlag == ECC_SKIP)
	 {
	    istart = 0;
	    iend = 0;
	 }
	 else
	    EXT_ASSERT(0, ECCFlag, 0, 0);
	
	 //for (i=0; i<4; i++)
	 for (i=istart; i<iend; i++)
	 {
		 if (exclusive_parity[i]==0)
			continue;

		 // ECC correct
		 ex_check_parity[0] = exclusive_parity[i]&0x0fff;
		 ex_check_parity[1] = (exclusive_parity[i]>>16)&0x0fff;

		 if ( ((ex_check_parity[0]^ex_check_parity[1])&0x0fff)==0x0fff )
		 {
			 // one-bit correctable error
			 error_bit_address = ex_check_parity[1]&(~ex_check_parity[0]); // 16 bits
			 update_data = Data[512*i+(error_bit_address>>3)];
			 update_data = update_data^(1<<(kal_uint8)(error_bit_address&0x0007));
			 Data[512*i+(error_bit_address>>3)] = update_data;
			 return MTD_STATUS_CORRECTED;
		 }
		 else
		 {
			 return MTD_STATUS_ERROR;
		 }
	 }

	return MTD_STATUS_NO_ERROR;

}	/*  End of ReadPage_2K_default */

/*******************************************************************************/
#ifdef _NAND_FLASH_BOOTING_
int NFB_ReadPage_2K_default (void * DriveData, DWORD PageIndex, BYTE * Data, BYTE * Spare, BYTE SpareFlag)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint32 * ECC_pointer = NULL;
	kal_uint16 i, error_bit_address;
	kal_uint32 tmp_ecc[64/sizeof(kal_uint32)];
	static kal_uint32 parity[4], parity_old[4]; // for ECC detection/correct; use static variable for debug
	static kal_uint32 exclusive_parity[4];
	static kal_uint16 ex_check_parity[2];
   static kal_uint8  update_data;

	/* NFI setting */
	*NFI_FIFOCON = RESET;
	*NFI_CON = 0x0;
	*NFI_CMD = RD_1ST_CMD;						// read command
	while (*NFI_PSTA & STATUS_CMD);
	*NFI_ADDRL = PageIndex << 16;
	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = PageIndex >> 16;
	*NFI_ADDNOB = D->flash_info.address_cycle;	// number of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_CMD = RD_2ND_CYCLE_CMD;
	while (*NFI_PSTA & STATUS_CMD);

	*NFI_OPCON = BURST_RD;						// set burst read

   readfifo_2K((kal_uint32 *)Data, NULL, 0, 512);

   /* ECC parity bits generated by NFI */
   while (!(*NFI_FIFOCON & WR_EMPTY_MASK));
   
   parity[0] = *NFI_PAR0;
   parity[0] |= (*NFI_PAR1) << 16;
   parity[1] = *NFI_PAR2;
   parity[1] |= (*NFI_PAR3) << 16;
   parity[2] = *NFI_PAR4;
   parity[2] |= (*NFI_PAR5) << 16;
   parity[3] = *NFI_PAR6;
   parity[3] |= (*NFI_PAR7) << 16;


   *NFI_OPCON = 0x0;


   /*Read spare to local buffer if SpareFlag==0;
     The spare area must be read for ECC detection/correction */  
   ReadSpare_2K_default(DriveData, PageIndex, (BYTE *)tmp_ecc);
   ECC_pointer = tmp_ecc;

   /* ECC check: two-bit error detection or one-bit error correction */
   parity_old[0] = *(ECC_pointer+11);
   parity_old[1] = *(ECC_pointer+12);
   parity_old[2] = *(ECC_pointer+13);
   parity_old[3] = *(ECC_pointer+14);    

   exclusive_parity[0] = (parity[0]^parity_old[0])&0x0fff0fff;
   exclusive_parity[1] = (parity[1]^parity_old[1])&0x0fff0fff;
   exclusive_parity[2] = (parity[2]^parity_old[2])&0x0fff0fff;
   exclusive_parity[3] = (parity[3]^parity_old[3])&0x0fff0fff;
   
   // process ECC block
   for (i=0; i<4; i++)
   {
      if (exclusive_parity[i]==0)
   	   continue;
   
      // ECC correct
      ex_check_parity[0] = exclusive_parity[i]&0x0fff;
      ex_check_parity[1] = (exclusive_parity[i]>>16)&0x0fff;
   
      if ( ((ex_check_parity[0]^ex_check_parity[1])&0x0fff)==0x0fff )
      { 
         // one-bit correctable error
         error_bit_address = ex_check_parity[1]&(~ex_check_parity[0]); // 16 bits
         update_data = Data[512*i+(error_bit_address>>3)];
         update_data = update_data^(1<<(kal_uint8)(error_bit_address&0x0007));
         Data[512*i+(error_bit_address>>3)] = update_data;
      }
      else
      {
         return FS_DATA_ERROR;
      }
   }
   
   return FS_NO_ERROR;

}	/*  End of ReadPage_2K */
#endif
/*******************************************************************************/
int ProgramSpare_2K_default(void * DriveData, DWORD PageIndex, BYTE * Data)
{
	NAND_FLASH_DRV_DATA * D = DriveData;
	kal_uint8 status;


	cmd_resetpointer();

	if (nfi_egid && use_interrupt == KAL_TRUE)
	   *NFI_INTR_EN = WR_COMPLETE_EN;

	*NFI_CON = SW_PROGSPARE_EN;
	*NFI_CMD = INPUT_DATA_CMD;					// Issue data input command
	while (*NFI_PSTA & STATUS_CMD);

	/* there is no read spare command for 2k page-size; utilize reset and address offset */
    if (D->flash_info.io_width == IO_ACCESS_8BIT)
	  *NFI_ADDRL = (PageIndex<<16)+2048;				// Byte address
	else
      *NFI_ADDRL = (PageIndex<<16)+(2048/2);			// Word address

	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = PageIndex >> 16;

	*NFI_ADDNOB = D->flash_info.address_cycle;	// no. of bytes for address
	while (*NFI_PSTA & STATUS_ADDR);

	*NFI_OPCON = BURST_WR;						// set burst write

	writefifo_2K((kal_uint32*)Data, NULL, ECC_WHOLE, 16);	// option:write data without dma

	while (!((status = read_status())&RDY_BUSY));
	*NFI_OPCON = 0;

	if (status&PASS_FAIL)
		return FS_DATA_ERROR;

	return FS_NO_ERROR;
}	/*  End of ProgramSpare_2K */


/*******************************************************************************/
int ReadSpare_2K_default(void * DriveData, DWORD PageIndex, BYTE * Data)	//need modification
{
	NAND_FLASH_DRV_DATA * D = DriveData;


	*NFI_CON = SW_PROGSPARE_EN;					// program spare area enable
	*NFI_CMD = RD_1ST_CMD;						// read spare command
	while (*NFI_PSTA & STATUS_CMD);

	/* there is no read spare command for 2k page-size; utilize reset and address offset */
    if (D->flash_info.io_width == IO_ACCESS_8BIT)
	  *NFI_ADDRL = (PageIndex<<16)+2048;				// Byte address
	else
      *NFI_ADDRL = (PageIndex<<16)+(2048/2);			// Word address

	if (D->flash_info.address_cycle == 5)
		*NFI_ADDRM = PageIndex >> 16;

	// set up start address, A7-A4 don't care, A3-A0 is the offset whthin the spare area
	*NFI_ADDNOB = D->fla

⌨️ 快捷键说明

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