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

📄 lld.c

📁 Spansion 公司(原AMD flash 部门 / 富士通 闪存部门) FLASH 访问的参考函数
💻 C
📖 第 1 页 / 共 3 页
字号:
		status_read_2 = FLASH_RD(base_addr, offset);
        status_read_3 = FLASH_RD(base_addr, offset);

		/* Any DQ6 toggles */
		dq6_toggles = ((status_read_1 ^ status_read_2) &        /* Toggles between read1 and read2 */ 
			           (status_read_2 ^ status_read_3) &        /* Toggles between read2 and read3 */
					   DQ6_MASK );                              /* Check for DQ6 only */      

		if (dq6_toggles)
		{			    					
			/* Checking WriteBuffer Abort condition: 
			   Check for all devices that have DQ6 toggling also have Write Buffer Abort DQ1 set */
			if (WriteBufferProgramming && 
				((DQ6_TGL_DQ1_MASK & status_read_1) == DQ6_TGL_DQ1_MASK) )
				return DEV_WRITE_BUFFER_ABORT;
			
			/* Checking Timeout condition: 
			   Check for all devices that have DQ6 toggling also have Time Out DQ5 set. */
			if ((DQ6_TGL_DQ5_MASK & status_read_1) == DQ6_TGL_DQ5_MASK )
			   return DEV_EXCEEDED_TIME_LIMITS;	
			
			/* No timeout, no WB error */
			return DEV_BUSY;
		}
		else   /* no DQ6 toggles on all devices */
		{
			/* Checking Erase Suspend condition */
			status_read_1 = FLASH_RD(base_addr, offset);
			status_read_2 = FLASH_RD(base_addr, offset);

			/* Checking Erase Suspend condition */
            if ( ((status_read_1 ^ status_read_2) & DQ2_MASK) == 0)     
			   return DEV_NOT_BUSY;         /* All devices DQ2 not toggling */

			if (((status_read_1 ^ status_read_2) & DQ2_MASK) == DQ2_MASK)   
			   return DEV_SUSPEND;          /* All devices DQ2 toggling */	
			else
			   return DEV_BUSY;             /* Wait for all devices DQ2 toggling */			
		}
	}
	else			
	{
		/*..................................................................
		Use Status Register Read command to read the status register. 
		This is for GL-R device only 
		...................................................................*/
#ifdef STATUS_REG
		volatile FLASHDATA status_reg; 

		wlld_StatusRegReadCmd( base_addr, offset );		  /* Issue status register read command */
		status_reg = FLASH_RD(base_addr, offset);         /* read the status register */

		if ( (status_reg & DEV_RDY_MASK) != DEV_RDY_MASK  ) /* Are all devices done bit 7 is 1 */
		  return DEV_BUSY ;

		if ( status_reg & DEV_ERASE_MASK )				    /* Any erase error */
		  return DEV_ERASE_ERROR;

		if ( status_reg & DEV_PROGRAM_MASK )				/* Any program error */
		  return DEV_PROGRAM_ERROR;

		if ( status_reg & DEV_SEC_LOCK_MASK )				/* Any sector lock error */
		  return DEV_SECTOR_LOCK;

		return DEV_NOT_BUSY ;
#endif
		return DEV_STATUS_UNKNOWN;                        /* should never get here */
	}
}

#endif


/******************************************************************************
* 
* lld_WriteBufferProgramOp - Performs a Write Buffer Programming Operation.
*
* Function programs a write-buffer overlay of addresses to data 
* passed via <data_buf>.
* Function issues all required commands and polls for completion.
*
* There are 4 main sections to the function:
*  Set-up and write command sequence
*  Determine number of locations to program and load buffer
*  Start operation with "Program Buffer to Flash" command
*  Poll for completion
*
* REQUIREMENTS:
*  Data in the buffer MUST be properly aligned with the Flash bus width.
*  No parameter checking is performed. 
*  The <word_count> variable must be properly initialized.  
*  Valid <byte_cnt> values: 
*   min = 1 byte (only valid when used with a single x8 Flash)
*   max = write buffer size in bytes * number of devices in parallel
      (e.g. 32-byte buffer per device, 2 x16 devices = 64 bytes)
*
* RETURNS: DEVSTATUS
*/
#ifndef REMOVE_WRITE_BUFFER_PROGRAMMING
DEVSTATUS lld_WriteBufferProgramOp
(
FLASHDATA *   base_addr,  /* device base address is system     */
ADDRESS   offset,     /* address offset from base address  */
WORDCOUNT word_count, /* number of words to program        */
FLASHDATA *data_buf   /* buffer containing data to program */
)
{       
  DEVSTATUS status;
  FLASHDATA write_data = 0;
  FLASHDATA read_data = 0;
  ADDRESS   last_loaded_addr;
  ADDRESS   current_offset;
  ADDRESS   end_offset;
  FLASHDATA wcount;

  /* Initialize variables */
  current_offset   = offset;
  end_offset       = offset + word_count - 1;
  last_loaded_addr = offset;

  /* don't try with a count of zero */
  if (!word_count) 
  {
    return(DEV_NOT_BUSY);
  }

  /* Issue Load Write Buffer Command Sequence */
  lld_WriteToBufferCmd(base_addr, offset);

  /* Write # of locations to program */
  wcount = (FLASHDATA)word_count - 1;
  wcount *= LLD_DEV_MULTIPLIER;

  FLASH_WR(base_addr, offset, wcount);

  /* Load Data into Buffer */
  while(current_offset <= end_offset)
  {
    /* Store last loaded address & data value (for polling) */
    last_loaded_addr = current_offset;
    write_data = *data_buf;

    /* Write Data */
    FLASH_WR(base_addr, current_offset++, *data_buf++);    
  }

  /* Issue Program Buffer to Flash command */
  lld_ProgramBufferToFlashCmd(base_addr, last_loaded_addr);
  
  status = lld_Poll(base_addr, last_loaded_addr, &write_data, 
                    &read_data, LLD_P_POLL_WRT_BUF_PGM);
  return(status);
}
#endif

/******************************************************************************
* 
* lld_ProgramOp - Performs a standard Programming Operation.
*
* Function programs a single location to the specified data.
* Function issues all required commands and polls for completion.
*
*
* RETURNS: DEVSTATUS
*/
#ifndef REMOVE_LLD_PROGRAM_OP
DEVSTATUS lld_ProgramOp
(
FLASHDATA * base_addr,      /* device base address is system */
ADDRESS offset,         /* address offset from base address */
FLASHDATA write_data    /* variable containing data to program */
)
{       
  FLASHDATA read_data = 0;
  DEVSTATUS status;

  lld_ProgramCmd(base_addr, offset, &write_data);
  
  status = lld_Poll(base_addr, offset, &write_data, &read_data, LLD_P_POLL_PGM);
  
  return(status);
}
#endif
/******************************************************************************
* 
* lld_SectorEraseOp - Performs a Sector Erase Operation
*
* Function erases the sector containing <base_addr> + <offset>.
* Function issues all required commands and polls for completion.
*
*
* RETURNS: DEVSTATUS
*
* ERRNO: 
*/
#ifndef REMOVE_LLD_SECTOR_ERASE_OP
DEVSTATUS lld_SectorEraseOp
(
FLASHDATA * base_addr,    /* device base address is system */
ADDRESS offset        /* address offset from base address */
)
{       
  FLASHDATA         expect_data = (FLASHDATA)0xFFFFFFFF;
  FLASHDATA         actual_data = 0;
  DEVSTATUS         status;

 
  lld_SectorEraseCmd(base_addr, offset);
  
  status = lld_Poll(base_addr, offset, &expect_data, &actual_data, LLD_P_POLL_SEC_ERS);
  
  return(status);
}
#endif
/******************************************************************************
* 
* lld_ChipEraseOp - Performs a Chip Erase Operation
*
* Function erases entire device located at <base_addr>.
* Function issues all required commands and polls for completion.
*
*
* RETURNS: DEVSTATUS
*/
#ifndef REMOVE_LLD_CHIP_ERASE_OP
DEVSTATUS lld_ChipEraseOp
(
FLASHDATA * base_addr   /* device base address in system */
)
{       
  DEVSTATUS status;
  FLASHDATA expect_data = (FLASHDATA)0xFFFFFFFF;
  FLASHDATA actual_data = 0;


  lld_ChipEraseCmd(base_addr);

  status = lld_Poll(base_addr, 0, &expect_data, &actual_data, LLD_P_POLL_CHIP_ERS);

  /* if an error during polling, write RESET command to device */
  if(status != DEV_NOT_BUSY) lld_ResetCmd(base_addr);

  return(status);
}
#endif
/******************************************************************************
* 
* DelayMilliseconds - Performs a delay.  If you have a better way,
*                     edit the macro DELAY_MS in lld_target_specific.h
*
* RETURNS: void
*
*/
#ifndef REMOVE_DELAY_MILLISECONDS
void DelayMilliseconds(int milliseconds)
{
  int i;

  for (i = 0; i < milliseconds; i++)
    DELAY_US(1000);
 
}
#endif
/******************************************************************************
* 
* DelayMicroseconds - Performs a delay.  If you have a better way,
*                     edit the macro DELAY_US in lld_target_specific.h
*
* RETURNS: void
*
*/
#ifndef REMOVE_DELAY_MICROSECONDS
void DelayMicroseconds(int microseconds)
{
  int volatile i, j;

  for (j = 0; j < microseconds; j++)
    for(i = 0; i < DELAY_1us; i++) i = i;
    
}
#endif
/******************************************************************************
* 
* lld_ReadOp - Read memory array operation
*
* RETURNS: data read
*
*/
#ifndef REMOVE_LLD_READ_OP
FLASHDATA lld_ReadOp
(
FLASHDATA * base_addr,    /* device base address is system */
ADDRESS offset        /* address offset from base address */
)
{
  FLASHDATA data;
  
  data = FLASH_RD(base_addr, offset);

  return(data);
}
#endif
/******************************************************************************
* 
* lld_GetDeviceId - Get device ID operation
*
* RETURNS: three byte ID in a single int
*
*/
#ifndef REMOVE_LLD_GET_DEVICE_ID
unsigned int lld_GetDeviceId
(
FLASHDATA * base_addr   /* device base address in system */
)
{
  unsigned int id;

  FLASH_WR(base_addr, LLD_UNLOCK_ADDR1, NOR_UNLOCK_DATA1);
  FLASH_WR(base_addr, LLD_UNLOCK_ADDR2, NOR_UNLOCK_DATA2);

  FLASH_WR(base_addr, LLD_UNLOCK_ADDR1, NOR_AUTOSELECT_CMD);

  id  = (unsigned int)(FLASH_RD(base_addr, 0x0001) & 0x000000FF) << 16;
  id |= (unsigned int)(FLASH_RD(base_addr, 0x000E) & 0x000000FF) <<  8;
  id |= (unsigned int)(FLASH_RD(base_addr, 0x000F) & 0x000000FF)      ;

  lld_ResetCmd(base_addr);
  
  return(id);
}
#endif
/******************************************************************************
* 
* lld_memcpy   This function attempts to mimic the standard memcpy
*              function for flash.  It segments the source data
*              into page size chunks for use by Write Buffer Programming.
*
* RETURNS: DEVSTATUS
*
*/
#ifndef REMOVE_WRITE_BUFFER_PROGRAMMING
DEVSTATUS lld_memcpy
(
FLASHDATA * base_addr,    /* device base address is system */
ADDRESS offset,           /* address offset from base address */
WORDCOUNT word_cnt,       /* number of words to program */
FLASHDATA *data_buf       /* buffer containing data to program */
)
{
  ADDRESS mask = LLD_BUFFER_SIZE - 1;
  WORDCOUNT intwc = word_cnt;
  DEVSTATUS status = DEV_NOT_BUSY;

  if (offset & mask)
  {
     /* program only as much as necessary, so pick the lower of the two numbers */
     if (word_cnt < (LLD_BUFFER_SIZE - (offset & mask)) ) 
        intwc = word_cnt; 
     else
        intwc = LLD_BUFFER_SIZE - (offset & mask);

     /* program the first few to get write buffer aligned */
     status = lld_WriteBufferProgramOp(base_addr, offset, intwc, data_buf);
     if (status != DEV_NOT_BUSY) 
     {
       return(status);
     }

     offset   += intwc; /* adjust pointers and counter */
     word_cnt -= intwc;
     data_buf += intwc;
     if (word_cnt == 0)
     {
       return(status);
     }
  }

  while(word_cnt >= LLD_BUFFER_SIZE) /* while big chunks to do */
  {
    status = lld_WriteBufferProgramOp(base_addr, offset, LLD_BUFFER_SIZE, data_buf);
    if (status != DEV_NOT_BUSY)
    {
      return(status);
    }

    offset   += LLD_BUFFER_SIZE; /* adjust pointers and counter */
    word_cnt -= LLD_BUFFER_SIZE;
    data_buf += LLD_BUFFER_SIZE;
  }
  if (word_cnt == 0)
  {
    return(status);
  }

  status = lld_WriteBufferProgramOp(base_addr, offset, word_cnt, data_buf);
  return(status);
}
#endif
/******************************************************************************
* 
* lld_ReadCfiWord - Read CFI word operation. 
*
* RETURNS: word read
*
*/
#ifndef REMOVE_LLD_READ_CFI_WORD
FLASHDATA lld_ReadCfiWord
(
FLASHDATA * base_addr,    /* device base address is system */
ADDRESS offset        /* address offset from base address */
)
{
  FLASHDATA data;

  FLASH_WR(base_addr, LLD_UNLOCK_ADDR1, NOR_CFI_QUERY_CMD);
  data  = FLASH_RD(base_addr, offset);
  lld_ResetCmd(base_addr);
  return(data);
}
#endif

⌨️ 快捷键说明

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