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

📄 cfiflash.c

📁 Flash芯片的CFI驱动c语言源代码,对自升级的系统有帮助。
💻 C
📖 第 1 页 / 共 3 页
字号:
{
  flash_command(FLASH_ERESUME, sector, 0, 0);
  return (1);
}

/*********************************************************************/
/* flash_get_sector_size() is provided for cases in which the size   */
/* of a sector is required by a host application.  The sector size   */
/* (in bytes) is returned in the data location pointed to by the     */
/* 'size' parameter.                                                 */
/*********************************************************************/

byte flash_get_sector_size(byte sector, dword *size)
{
  *size = meminfo->sec[sector].size;
  return(1);
}

/*********************************************************************/
/* UNLOCK BYPASS FUNCTIONS                                           */
/*********************************************************************/
/* Unlock bypass mode is useful whenever the calling application     */
/* wished to program large amounts of data in minimal time.  Unlock  */
/* bypass mode remove half of the bus overhead required to program   */
/* a single word, from 4 cycles down to 2 cycles.  Programming of    */
/* individual bytes does not gain measurable benefit from unlock     */
/* bypass mode, but programming large strings can see a significant  */
/* decrease in required programming time.                            */
/*********************************************************************/

/*********************************************************************/
/* flash_ub() places the flash into unlock bypass mode.  This        */
/* is REQUIRED to be called before any of the other unlock bypass    */
/* commands will become valid (most will be ignored without first    */
/* calling this function.                                            */
/*********************************************************************/
 
byte flash_ub(byte sector)
{
  flash_command(FLASH_UB, sector, 0, 0);
  return(1);
}

/*********************************************************************/
/* flash_write_word_ub() programs a single word using unlock bypass  */
/* mode.  Note that the calling application will see little benefit  */
/* from programming single words using this mode (outlined above)    */
/*********************************************************************/

byte flash_write_word_ub(byte sector, word offset, word data)
{
  flash_command(FLASH_UBPROG, sector, offset, data);
  return (1);
}

/*********************************************************************/
/* flash_write_string_ub() behaves in the exact same manner as       */
/* flash_write_string() (outlined above), expect that it utilizes    */
/* the unlock bypass mode of the flash device.  This can remove      */
/* significant overhead from the bulk programming operation, and     */
/* when programming bulk data a sizeable performance increase can be */
/* observed.                                                         */
/*********************************************************************/

byte flash_write_string_ub(byte sector, word offset,
   			   byte *buffer, word numbytes)
{
  word value=0;

  if(numbytes == 0)
	 value = (word) strlen(buffer);
  else
	 value = numbytes;

  if (value & 0x0001)
	 value--; /* Need to make sure we don't overrun buffer */

  flash_write(sector, offset, buffer, value,TRUE);
  return (1);
}

/*********************************************************************/
/* flash_reset_ub() is required to remove the flash from unlock      */
/* bypass mode.  This is important, as other flash commands will be  */
/* ignored while the flash is in unlock bypass mode.                 */
/*********************************************************************/

byte flash_reset_ub(void)
{
  flash_command(FLASH_UBRESET,1,0,0);
  return(1);
}

/*********************************************************************/
/* Usefull funtion to return the number of sectors in the device.    */
/* Can be used for functions which need to loop among all the        */
/* sectors, or wish to know the number of the last sector.           */
/*********************************************************************/

void flash_get_numsectors(int *num)
{
  *num = meminfo->nsect;
}

/*********************************************************************/
/* flash_get_cfi() is the main CFI workhorse function.  Due to it's  */
/* complexity and size it need only be called once upon              */
/* initializing the flash system.  Once it is called, all operations */
/* are performed by looking at the meminfo structure.                */
/* All possible care was made to make this algorithm as efficient as */
/* possible.  90% of all operations are memory reads, and all        */
/* calculations are done using bit-shifts when possible              */
/*********************************************************************/

byte flash_get_cfi(struct cfi_query *query)
{
  word far *fwp; /* flash window */
  int volts=0, milli=0, temp=0, i=0;
  int num_secs=0, offset=0;

  flash_command(FLASH_RESET,0,0,0); /* Use sector 0 for all commands */
  flash_command(FLASH_CFIQUERY,0,0,0);

  fwp = (word *)get_flash_memptr(0);

  /* Initial house-cleaning */

  for(i=0; i < 8; i++) {
    query->erase_block[i].sector_size = 0;
    query->erase_block[i].num_sectors = 0;
  }

  query->query_string[0] = fwp[0x10];
  query->query_string[1] = fwp[0x11];
  query->query_string[2] = fwp[0x12];
  query->query_string[3] = '\0';

  /* If not 'QRY', then we dont have a CFI enabled device in the
	  socket */

  if( query->query_string[0] != 'Q' &&
    query->query_string[1] != 'R' &&
    query->query_string[2] != 'Y') {
    return(-1);
  }

  query->oem_command_set       = fwp[0x13];
  query->primary_table_address = fwp[0x15]; /* Important one! */
  query->alt_command_set       = fwp[0x17];
  query->alt_table_address     = fwp[0x19];

  /* We will do some bit translation to give the following values
	  numerical meaning in terms of C 'float' numbers */

  volts = ((fwp[0x1B] & 0xF0) >> 4);
  milli = (fwp[0x1B] & 0x0F);
  query->vcc_min = (float) (volts + ((float)milli/10));

  volts = ((fwp[0x1C] & 0xF0) >> 4);
  milli = (fwp[0x1C] & 0x0F);
  query->vcc_max = (float) (volts + ((float)milli/10));

  volts = ((fwp[0x1D] & 0xF0) >> 4);
  milli = (fwp[0x1D] & 0x0F);
  query->vpp_min = (float) (volts + ((float)milli/10));

  volts = ((fwp[0x1E] & 0xF0) >> 4);
  milli = (fwp[0x1E] & 0x0F);
  query->vpp_max = (float) (volts + ((float)milli/10));

  /* Let's not drag in the libm library to calculate powers
	  for something as simple as 2^(power)
	  Use a bit shift instead - it's faster */

  temp = fwp[0x1F];
  query->timeout_single_write = (1 << temp);

  temp = fwp[0x20];
  if (temp != 0x00)
    query->timeout_buffer_write = (1 << temp);
  else
    query->timeout_buffer_write = 0x00;

  temp = 0;
  temp = fwp[0x21];
  query->timeout_block_erase = (1 << temp);

  temp = fwp[0x22];
  if (temp != 0x00)
    query->timeout_chip_erase = (1 << temp);
  else
    query->timeout_chip_erase = 0x00;

  temp = fwp[0x23];
  query->max_timeout_single_write = (1 << temp) *
  query->timeout_single_write;

  temp = fwp[0x24];
  if (temp != 0x00)
    query->max_timeout_buffer_write = (1 << temp) *
    query->timeout_buffer_write;
  else
    query->max_timeout_buffer_write = 0x00;

  temp = fwp[0x25];
  query->max_timeout_block_erase = (1 << temp) *
  query->timeout_block_erase;

  temp = fwp[0x26];
  if (temp != 0x00)
    query->max_timeout_chip_erase = (1 << temp) *
    query->timeout_chip_erase;
  else
    query->max_timeout_chip_erase = 0x00;

  temp = fwp[0x27];
  query->device_size = (long) (((long)1) << temp);

  query->interface_description = fwp[0x28];

  temp = fwp[0x2A];
  if (temp != 0x00)
    query->max_multi_byte_write = (1 << temp);
  else
    query->max_multi_byte_write = 0;

  query->num_erase_blocks = fwp[0x2C];

  for(i=0; i < query->num_erase_blocks; i++) {
    query->erase_block[i].num_sectors = fwp[(0x2D+(4*i))];
    query->erase_block[i].num_sectors++;

    query->erase_block[i].sector_size = (long) 256 *
                        ( (long)256 * fwp[(0x30+(4*i))] +
	 	                fwp[(0x2F+(4*i))] );													 ( (long)256 * fwp[(0x30+(4*i))] +
																		fwp[(0x2F+(4*i))] );
  }

  /* Store primary table offset in variable for clarity */
  offset = query->primary_table_address;

  query->primary_extended_query[0] = fwp[(offset)];
  query->primary_extended_query[1] = fwp[(offset + 1)];
  query->primary_extended_query[2] = fwp[(offset + 2)];
  query->primary_extended_query[3] = '\0';

  if( query->primary_extended_query[0] != 'P' &&
    query->primary_extended_query[1] != 'R' &&
    query->primary_extended_query[2] != 'I') {
    return(2);
  }

  query->major_version = fwp[(offset + 3)];
  query->minor_version = fwp[(offset + 4)];

  query->sensitive_unlock      = (byte) (fwp[(offset+5)] & 0x0F);
  query->erase_suspend         = (byte) (fwp[(offset+6)] & 0x0F);
  query->sector_protect        = (byte) (fwp[(offset+7)] & 0x0F);
  query->sector_temp_unprotect = (byte) (fwp[(offset+8)] & 0x0F);
  query->protect_scheme        = (byte) (fwp[(offset+9)] & 0x0F);
  query->is_simultaneous       = (byte) (fwp[(offset+10)] & 0x0F);
  query->is_burst              = (byte) (fwp[(offset+11)] & 0x0F);
  query->is_page               = (byte) (fwp[(offset+12)] & 0x0F);

  return(1);
}




⌨️ 快捷键说明

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