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

📄 bl_nfi.c

📁 ARM Bootloader程序
💻 C
📖 第 1 页 / 共 2 页
字号:
	      *NFI_ADDRM = addr2;
	   *NFI_ADDNOB = addr_no;	           // number of bytes for address	   
	   while (*NFI_PSTA & STATUS_ADDR);	   
	}
	else
	{
	   *NFI_CMD = RD_1ST_CMD;	           // Issue data input command
	   while (*NFI_PSTA & STATUS_CMD);	   
	   *NFI_ADDRL = addr1;
	   if ( addr_no>4 )
	      *NFI_ADDRM = addr2;
	   *NFI_ADDNOB = addr_no;	           // no. of bytes for address	
	   while (*NFI_PSTA & STATUS_ADDR);	   
	   *NFI_CMD = RD_2ND_CYCLE_CMD;
	   while (*NFI_PSTA & STATUS_CMD);	   
	}

   *NFI_OPCON = BURST_RD | NOB_DWORD;    // set burst read
   
   while( *NFI_PSTA & STATUS_DATAR );
   
   NFI_Wait_Ready(timeout);
   
   if ( timeout==0 )
      return KAL_FALSE;

   // Activating DMA transfer
   if ( ECC )
      *NFI_CON = (DMA_RD_EN | AUTOECC_DEC_EN);
   else
      *NFI_CON = DMA_RD_EN;
   
   *(volatile kal_uint32 *)(0x80030118) = 0x0000;
   *(volatile kal_uint32 *)(0x80030100) = (kal_uint32)NFI_DATAR;
   *(volatile kal_uint32 *)(0x80030104) = (kal_uint32)destination;
   *(volatile kal_uint32 *)(0x80030110) = length>>2;
   *(volatile kal_uint32 *)(0x80030114) = 0x00f4001a;
   *(volatile kal_uint32 *)(0x80030128) = 0;
   *(volatile kal_uint32 *)(0x80030118) = 0x8000;
   
   timeout = 0xfff;
   
   while ( ((*(volatile kal_uint32 *)(0x80030000)&0x03)==0x01) && (timeout--) ); 
   
   if ( timeout==0 )
	   return DMA_TRANSFER_DATA_TIMEOUT;
         
//   while (!(*NFI_FIFOCON & RD_EMPTY_MASK) || (*NFI_PSTA & STATUS_DATAR));
   while (*NFI_PSTA & STATUS_BUSY);   

   if ( ECC )
   {
		if ( parity==NULL )
			return NFI_ZERO_POINTER;
		 
		if ( pageSize<1024 )
		{
			parity_ptr[0] = *NFI_PAR6;
			parity_ptr[0] |= (*NFI_PAR7) << 16;         
		}
		else
		{
			parity_ptr[0] = *NFI_PAR0;
			parity_ptr[0] |= (*NFI_PAR1) << 16;
			parity_ptr[1] = *NFI_PAR2;
			parity_ptr[1] |= (*NFI_PAR3) << 16;
			parity_ptr[2] = *NFI_PAR4;
			parity_ptr[2] |= (*NFI_PAR5) << 16;
			parity_ptr[3] = *NFI_PAR6;
			parity_ptr[3] |= (*NFI_PAR7) << 16;
		}         
   }
   
   // Caution: This line must not omitted!
   *NFI_OPCON = 0x0;
   
   if ( timeout )
	   return NFI_SUCCESS;
	else 
	   return NFI_READ_DATA_TIMEOUT;
}

/**********************************************************
Description : NFI_SpareRead
Input       : .......
Output      : _RET_CODE
Remark      : Must be spare area aligned
***********************************************************/
_RET_CODE NFI_SpareRead(kal_uint32 *spare, kal_uint16 addr_no, kal_uint32 addr1, \
                        kal_uint16 addr2, kal_uint16 pageSize, kal_uint16 IO)
{
	kal_int16 timeout=0xfff, size, i;
	  
	*NFI_OPCON = 0x00;
	*NFI_CON = 0x00;        
	*NFI_FIFOCON = 0x30;                  // Flushing FIFO

	if ( pageSize<1024 )
	{
		size = 16;
		*NFI_CON = SW_PROGSPARE_EN;        // program/read spare area enable
		*NFI_CMD = RD_SPARE_CMD;			  // reading spare command	   
		while (*NFI_PSTA & STATUS_CMD);	  
		*NFI_ADDRL = (addr1&0xffffff00);	 
		*NFI_ADDRM = 0;
		*NFI_ADDNOB = addr_no;             // number of bytes for address
		while (*NFI_PSTA & STATUS_ADDR);	 
	}
	else
	{
		size = 64;
		*NFI_CON = SW_PROGSPARE_EN;        // program spare area enable
		*NFI_CMD = RD_1ST_CMD;             // read spare command
		while (*NFI_PSTA & STATUS_CMD);	  
		if ( IO==IO_16BITS )
		{
			// addr1 >>= 1;	   
			addr1 = addr1 + (2048/2);
		}
		else 
		{
			addr1 = addr1 + 2048;
		}
		*NFI_ADDRL = addr1;
		if ( addr_no>4 )
			*NFI_ADDRM = addr2;
		*NFI_ADDNOB = addr_no;             // 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 | NOB_WORD;     // set burst read	
	*NFI_OPCON = BURST_RD | NOB_DWORD;     // set burst read	

	while( *NFI_PSTA & STATUS_DATAR );

	NFI_Wait_Ready(timeout);

	if ( timeout==0 )
	  return NFI_READ_SPARE_TIMEOUT;


	/*   *NFI_CON |= DMA_RD_EN;
	*(volatile kal_uint32 *)(0x80030118) = 0x0000;
	*(volatile kal_uint32 *)(0x80030100) = (kal_uint32)NFI_DATAR;
	*(volatile kal_uint32 *)(0x80030104) = (kal_uint32)spare;
	*(volatile kal_uint32 *)(0x80030110) = size>>2;
	*(volatile kal_uint32 *)(0x80030114) = 0x00f4001a;
	*(volatile kal_uint32 *)(0x80030128) = 0;
	*(volatile kal_uint32 *)(0x80030118) = 0x8000;

	timeout = 0xfff;

	while ( ((*(volatile kal_uint32 *)(0x80030000)&0x03)==0x01) && (timeout--) ); */


	for (i=0; i<(size/4); i++)
	{
		while ((*NFI_FIFOCON & RD_EMPTY_MASK));
		spare[i] = *NFI_DATAR;
	}   

/*	dbg_print("Spare area = ");
	for(i=0; i<(size/4); i++) {
	     dbg_print("%x ", spare[i]);
	}
	dbg_print("\n\r");*/


	//   while (*NFI_PSTA & STATUS_DATAR);
	// Caution: This line must not omitted!
	*NFI_OPCON = 0x0;
	while (*NFI_PSTA & STATUS_BUSY);   

	if ( timeout )
	   return NFI_SUCCESS;
	else 
	   return DMA_TRANSFER_SPARE_TIMEOUT;
}

/**********************************************************
Description : NFI_ParityCheck
Input       : .......
Output      : _RET_CODE
Remark      : Must be page alignment.
***********************************************************/
_RET_CODE NFI_ParityCheck(kal_uint32 *destination, kal_uint32 *parity, kal_uint16 addr_no, \
                          kal_uint32 addr1, kal_uint16 addr2, kal_uint16 pageSize, kal_uint16 IO, \
                          kal_uint32 blockSize)
{
   _RET_CODE  status;
   kal_uint32 spare[64>>2];
   
   status = NFI_SpareRead(&spare[0], addr_no, addr1, addr2, pageSize, IO);
   
   if ( status!=NFI_SUCCESS )
      return status;
  
   if ( pageSize<1024 )
      status = NUTL_ECC_Correction(destination, parity, &spare[0], 512, blockSize);
   else
      status = NUTL_ECC_Correction(destination, parity, &spare[0], 2048, blockSize);
   
   return status;
}
                  
/**********************************************************
Description : NFI_CheckGoodBlock
Input       : NFI_MENU, baseaddr must be page alignment
Output      : U32 return data
              512B/page, 8-bits interface, 0x????FF??
              otherwise, 0x????FFFF or 0x??????FF
              for good page
              2: Read error
***********************************************************/ 
static kal_uint32 NFI_CheckGoodBlock(NFI_MENU *input, kal_uint32 addr1, kal_uint16 addr2)
{
   kal_uint32 rb_data[4];
   kal_int16  timeout=0xfff, size;
   
   rb_data[0]= 0;
   rb_data[1]= 0;
   rb_data[2]= 0;
   rb_data[3]= 0;
   
   *NFI_OPCON = 0x00;
   *NFI_CON = 0x00;        
   *NFI_FIFOCON = 0x30;                  // Flushing FIFO
   
   if ( input->pageSize<1024 )
   {
      *NFI_CON = SW_PROGSPARE_EN;        // program/read spare area enable
	   *NFI_CMD = RD_SPARE_CMD;			  // reading spare command	   
	   while (*NFI_PSTA & STATUS_CMD);	  
	   *NFI_ADDRL = (addr1&0xffffff00);	 
	   *NFI_ADDRM = 0;
	   *NFI_ADDNOB = input->addressCycle; // number of bytes for address
	   while (*NFI_PSTA & STATUS_ADDR);	 
	}
	else
	{
	   *NFI_CON = SW_PROGSPARE_EN;        // program spare area enable
	   *NFI_CMD = RD_1ST_CMD;             // read spare command
	   while (*NFI_PSTA & STATUS_CMD);	  
	   if ( input->IOInterface == IO_8BITS )
	      *NFI_ADDRL = addr1 + 2048;
	   else
	      *NFI_ADDRL = addr1 + 1024;
	   if ( input->addressCycle>4 )
	      *NFI_ADDRM = addr2;
	   *NFI_ADDNOB = input->addressCycle; // 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 | NOB_WORD;  // set burst read	
	
	while( *NFI_PSTA & STATUS_DATAR );
	
   NFI_Wait_Ready(timeout);
   
   if ( timeout==0 )
      return 2;
   
   size = 0;
   timeout=0xfff;
   
   while ( (size<4) && timeout>0 )
 	{
	   if ( !(*NFI_FIFOCON&RD_EMPTY_MASK) )
	   {
         rb_data[size] = *NFI_DATAR;
         size ++;
      }
      else 
         timeout--;
   }
   
   if ( timeout<=0 )
      return 2;
      
   // Caution: This line must not omitted!
   *NFI_OPCON = 0x0;
      
   if ( input->pageSize<1024 )
   {
      if ( input->IOInterface == IO_8BITS )
         return ( (kal_uint32)((rb_data[1]&0xff00)>>8) );
      else
         return ( ((kal_uint32)(rb_data[0]&0xff) | (rb_data[1]&0xff00)) );
   }
   else
   {
      if ( input->IOInterface == IO_8BITS )
         return ( (kal_uint32)(rb_data[0]&0xff) );
      else
         return ( (kal_uint32)(rb_data[0]&0xffff) );
   }
}


/**********************************************************
Description : NFIReconfigure
Input       : NO
Output      : NO
***********************************************************/
void NFIReconfigure(void)
{
	*NFI_FIFOCON = 0x30;                  // Flushing FIFO
	*NFI_OPCON = 0x00;
	*NFI_CON = 0x00;     
	// Force 512Bytes ECC block size for both 2KB and 512B NAND-flash
	*NFI_PAGEFMT |= 0x20;
	*NFI_ACCCON = 0x7FF;
}


/**********************************************************
Description : GoodBlockChecking
Input       : NFI_MENU, NFIReadPtr must be page alignment
Output      : TRUE, good block, FALSE, bad block
***********************************************************/
kal_bool GoodBlockChecking(NFI_MENU *input, kal_uint32 addr1, kal_uint16 addr2)
{
   kal_uint32 marking, i;
      
   for (i=0; i<2; i++)
   {
      // Read the bad block marking from the first page
      marking = NFI_CheckGoodBlock(input, addr1, addr2);
      if ( (marking!=0xff) && (marking!=0xffff) )
         return KAL_FALSE;
      addr1 = addr1 + (1<<input->pageShift);
   }
         
   return KAL_TRUE;
}

⌨️ 快捷键说明

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