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

📄 nandflash.c

📁 对nand_flash的擦除、编程算法源码
💻 C
📖 第 1 页 / 共 2 页
字号:
		if(*targetP++ != 0xffffffff)
			return 0;
	
	return 1;
}

int Verification(ulong *targetP, ulong limit, ulong *srcAddr)
{
	ulong i;

//	sourceP = (ushort *)srcAddr;
	
	for(i=0; i<limit; i+=4, targetP++, srcAddr++)
		if(*targetP != *srcAddr) {
			return 0;
		}

	return 1;
}

int ReadChar(uchar *data, ulong targetAddr, ulong size)
{
	ulong i, len, flen, status;

	len = size;

	for (i=0; i<size; i+=PAGE_SIZE) {
		if(len > PAGE_SIZE)
			flen = PAGE_SIZE;
		else
			flen = len;	

		*ale_reg = targetAddr & 0x01FFFE00;
		*cle_reg = READ_DATA;

		while(*status_reg & READ_DATA) {
			*AutoKick_reg = 1;
			*AutoKick_reg = 0;
		}
			
		status = *status_reg;
		
		if( (status & FS_NAND_OP_ERR_MASK != 0) || 
			(status & FS_NAND_ECC_SELF_ERR_MASK != 0) || 
			(status & FS_NAND_READ_ECC_ERR_MASK != 0) )
				return 0;		
		
//		for(j=0; j<flen; j++, data++)
//			*data = *(data_reg+j);
		memcpy((void *)data, (void *)data_reg, flen);
		data += flen;

		len -= PAGE_SIZE;
		targetAddr += PAGE_SIZE;
		
		AutoKick();
	}

	return 1;
}

int WriteChar(uchar *data, ulong page_addr)
{
	ushort status;
 
	memcpy((void *)data_reg, (void *)data, PAGE_SIZE);

	*ale_reg = page_addr << 9;
	*cle_reg = PROGRAM_CMD;

	while(*status_reg & PROGRAM_CMD)
		AutoKick();
			
	status = *status_reg;
		
	if( (status & FS_NAND_OP_ERR_MASK != 0) || 
		(status & FS_NAND_OP_RESULT_MASK != 0) )
			return 0;		

	return 1;
}


void  ReadMem(void)
{
	uchar *srcP;

	srcP = (uchar *)Flash_Info.Buf;

	ReadChar(srcP, Flash_Info.TargetAddr, Flash_Info.Length);
	
    Flash_Info.Result = 1;
}

void InitFlash(void)
{
	ulong status;  

	/* Reset NAND flash memory */
	*cle_reg = RESET_CMD;

	/* Software reset the controller. */
	*cle_reg = RESET_CTRL;

	/* Reset NAND flash memory */
	*cle_reg = RESET_CMD;

	/* Configure NAND flash */
  	*flash_cfg_reg = FS_NAND_CNFG_VAL;

	/* Wait for completion. */
	while(*status_reg & PROGRAM_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	/* Do a id check. */
	*cle_reg = ID_CMD;
	
	/* Wait for completion. */
	while(*status_reg & ID_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	/* Do a status check */
	*cle_reg = STATUS_CMD;
	
	/* Wait for completion. */
	while(*status_reg & STATUS_CMD)
	{
		*AutoKick_reg = 1;
		*AutoKick_reg = 0;
	}	
	
	crc = CRC_30_STEP_SEED;
	image_size = 0;
	LastAddr = 0;
	
	status = *status_reg;
	
	BIB_Block_No = 1;
	while(!Bad_Block_Check(BIB_Block_No) && (BIB_Block_No < BLOCK_COUNT))
		BIB_Block_No++;
	
	Current_Block_No = BIB_Block_No;
	Current_Page_No = Current_Block_No*PAGE_CNT;
	
} 

void AutoKick(void)
{
	*AutoKick_reg = 1;
	*AutoKick_reg = 0;
}

ulong crc_30_step
(
  ulong seed,
    /* Either the result of a previous crc_30_step() or CRC_16_STEP_SEED
    ** the first time the routine is called.  Note that the input is
    ** inverted prior to use, to counteract the inversion applied when
    ** it was returned as a result of the previous step.
    */

  uchar *buf_ptr,
    /* Pointer to bytes containing the data to CRC.  The bit stream starts
    ** in the MS bit of the first uchar.
    */

  ushort len
    /* Number of data bits to calculate the CRC over */
)
{
  ulong data, crc_30;

  /* Generate a CRC-30 by looking up the transformation in a table and
  ** XOR-ing it into the CRC, one uchar at a time.
  */
  for (crc_30 = ~seed & 0x3FFFFFFF; len >= 8; len -= 8, buf_ptr++) {
    crc_30 = crc30_table[ ((crc_30 >> (30 - 8)) ^ *buf_ptr) & 0xff ]
                ^ (crc_30 << 8);
  }

  /* Finish calculating the CRC over the trailing data bits
  **
  ** XOR the MS bit of data with the MS bit of the CRC.
  ** Shift the CRC and data left 1 bit.
  ** If the XOR result is 1, XOR the generating polynomial in with the CRC.
  */
  if (len != 0) {

    data = ((ulong) (*buf_ptr)) << (30-8); /* Align data MSB with CRC MSB */

    while (len-- != 0) {
      if ( ((crc_30 ^ data) & (1L << 29)) != 0 ) {       /* Is MSB of XOR a 1 */

        crc_30 <<= 1;                   /* Left shift CRC          */
        crc_30 ^= CRC_30_POLYNOMIAL;    /* XOR polynomial into CRC */

      } else {

        crc_30 <<= 1;                   /* Left shift CRC          */

      }

      data <<= 1;                       /* Left shift data         */
    }
  }

  crc_30 = ~crc_30;                     /* 1's complement the CRC     */

  return( crc_30 & 0x3FFFFFFF );        /* mask the result to 30 bits */

} /* end of crc_30_calc */


#ifdef SAMSUNG
// Samsung nand flash
int Bad_Block_Check(ulong block)
{
  ulong page_address, status, spare_byte;
  ulong page_no =0;
  int block_size_shift;
  ushort no_of_shifts = 1;
  ushort no_pages_to_check;

  block_size_shift = PAGE_CNT;
  while( block_size_shift != 2 )
  {
    block_size_shift = block_size_shift >> 1;
    no_of_shifts++;
  }

  /* Set the first page number */
  page_no = block << no_of_shifts;

  /* Check the first two pages of the samsung block */
  for( no_pages_to_check=0; no_pages_to_check < 2 ; no_pages_to_check++ )
  {

    /* Read the 6th spare byte */
    page_address = (page_no << 9) + 5;

	*ale_reg = page_address;
	*cle_reg = READ_FLAG;

	while(*status_reg & READ_FLAG) ;
		
	status = *status_reg;
	
	if(status & FS_NAND_OP_ERR_MASK)
		return 0;		
		
	spare_byte = *spare_data_reg;

	*AutoKick_reg = 1;
	*AutoKick_reg = 0;

    if( (spare_byte & 0xFF ) != 0xFF )
    {
      return 0;
    }

    /* Check the second page in the block */
    page_no++;

  }

  /* After the spare byte is read the nand device needs to be
     reset before any other operation is performed */

  /* Software reset the controller. */
  *cle_reg = RESET_CTRL;

  /* Reset NAND flash memory */
  *cle_reg = RESET_CMD;

  /* Configure NAND flash */
  *flash_cfg_reg = FS_NAND_CNFG_VAL;

  /* Wait for completion. */
  while(*status_reg & PROGRAM_CMD)
    ;

  /* Do a id check. */
  *cle_reg = ID_CMD;

  /* Wait for completion. */
  while(*status_reg & ID_CMD)
    ;

  return 1;

} /* End of samsung_nand_bad_block_check */ 
#endif


#ifdef TOSHIBA
int Bad_Block_Check(ulong block)
{

  int i;
  ulong page_address, status, page_no, first_page_no;
  ulong sram_buffer=0x0;
  int block_size_shift;
  ushort no_of_shifts = 1;
  int block_size=PAGE_CNT;
  int page_size=PAGE_SIZE;
  ulong ecc;

  block_size_shift=PAGE_CNT;
  while ( block_size_shift != 2 )
  {
    block_size_shift = block_size_shift >> 1;
    no_of_shifts++;
  }

  /*Reset sram memory */
  for (i = 0; i < page_size/4; i++)
  	*(data_reg + i) = 0;

  /* Set the first page number */
  first_page_no = block << no_of_shifts;

  for (  page_no = first_page_no ; page_no < first_page_no+block_size ; page_no++ )
  {
    page_address = page_no << 9;

    *ale_reg = page_address;

    *cle_reg = READ_DATA;

    status = *status_reg;

    while ( status & READ_DATA != 0)
    {
      status = *status_reg;
    }

    status = *status_reg;
    if ( (status & FS_NAND_OP_ERR_MASK != 0) ||
         (status & FS_NAND_ECC_SELF_ERR_MASK != 0) || 
         (status & FS_NAND_READ_ECC_ERR_MASK != 0) )
    {
      return 0;
    }

    /* TESTING ecc malfunction !!*/
    ecc = *ecc_read_reg;   
    if ( ((ecc & FS_NAND_READ_ECC_ERR_MASK)  != 0) || ((ecc & FS_NAND_ECC_UC_ERR_MASK) != 0 ))
    {
      /*printf("fs_nand_common_fnc: fs_nand_read_page - error bad ecc 0: 0x%08x", ecc);*/
	  status = *status_reg;
      if ( (status & FS_NAND_OP_ERR_MASK != 0) ||
           (status & FS_NAND_ECC_SELF_ERR_MASK != 0) || 
           (status & FS_NAND_READ_ECC_ERR_MASK != 0) )
      {
        /* printf("ecc was bad and status was also bad\n");*/
      }
    }

    /* Reading the sram buffer in chunks of 4 bytes */
    for (i = 0; i < page_size/4; i++)
    {
      sram_buffer = *(data_reg + i);
      if ( (sram_buffer & 0xFFFFFFFF ) != 0xFFFFFFFF )
        return 0;
      sram_buffer=0x0;
    }

  } 

  return 1;

} /* End of toshiba_nand_bad_block_check */

#endif

⌨️ 快捷键说明

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