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

📄 flash_nor_spansion.c

📁 Flash的驱动程序。包括市面上常见的Nor Flash和Nand Flash.基本上所有的Flash只需要简单修改就可以移植到其他应用。
💻 C
📖 第 1 页 / 共 2 页
字号:
      /* Sometimes, the parts don't return status correctly the first         time.  A normally completed erase should read with the value         of 0xFFFF.  If this isn't what we got, try to read the status         register again. */      if (tmp != 0xFFFF) {        retry_count++;        if (retry_count < 5)          goto retry;        /* The device is not giving us meaningful status.  This seems to         * happen (rarely) once in a while.  About the only thing to do         * here, is start the erase back up again, and wait for it to         * finish. */        *eraseaddr = 0x30;        /* The bit toggling seems to break until the erase itself finish         * The only way that gives us to determine when the erase is don         * is that the value 0xFFFF will appear.  This comes in about 5m         * after the erase itself finishes.  If something is really wron         * and the erase doesn't ever finish, the dog will eventually ha         * to kick in. */        do {          tmp = FSI_AMD_PEEK (eraseaddr);        } while (tmp != 0xFFFF);        result = FLASH_SUCCESS;        done = 1;        break;      }      *eraseaddr = 0xF0;      result = FLASH_SUCCESS;      done = 1;      break;    }  }  return result;}/*===========================================================================FUNCTION FSI_SPANSION_RESUMEDESCRIPTION  Resume a suspended erase.DEPENDENCIES  The fsi_spansion_suspend must have sucessfully suspended the device.RETURN VALUE  FLASH_SUCCESS             - The erase has been resumed.SIDE EFFECTS  None===========================================================================*/LOCAL flash_statusfsi_spansion_resume (flash_ptr_type eraseaddr){  /* Issue the resume command. */#ifdef FEATURE_EFS_AMD_SUSPEND_FETCH_BUG  INTLOCK ();  FSI_AMD_POKE (eraseaddr, 0x30);  INTFREE ();#else  *eraseaddr = 0x30;#endif  clk_busy_wait(4);  return FLASH_SUCCESS;}/* fsi_and_resume *//*===========================================================================FUNCTION FSI_SPANSION_CONFIGUREDESCRIPTION  Do any necessary initializtion.DEPENDENCIES  Must be done before any operations are carried out on the flash hardware.RETURN VALUE  FLASH_SUCCESS             - SuccessSIDE EFFECTS  None===========================================================================*/LOCAL flash_statusfsi_spansion_configure (fsi_nor_device * nor_device, flash_ptr_type baseaddr){  word i;  flash_status status;  status = flash_geometry_init(nor_device, baseaddr);  /* Initialize the erased value array for quick erase compares. */  for (i = 0; i < ERASE_VERIFY_BLK; i++)  {    erase_verify_buf[i] = (uint8)0xFF;  }  /* just a stub for devices that need no configuration */  return status;}/*===========================================================================FUNCTION FSI_SPANSION_WRITEDESCRIPTION  Write a block of byte to Spansion flash part.DEPENDENCIES  The device must not be in  erasing state.RETURN VALUE  FLASH_SUCCESS      -  If write completed normally  FLASH_FAILURE      -  If write operation failed  FLASH_TIMEOUT      -  If write operation timed out  SIDE EFFECTS  None===========================================================================*/LOCAL flash_statusfsi_spansion_write (byte *buffer,               flash_ptr_type baseaddr,               dword offset,               dword count){  flash_status status = FLASH_SUCCESS;  dword inbuff_offset=0;  word num_to_copy, num_written = 0;#ifdef FLASH_CHECK  dword size = count;  byte *source = buffer;#endif  /*----------------------------------------------------------------*/  /* Use the byte write */  if(count < SPANSION_BUFFER_WRITE_SIZE)  {    status = fsi_spansion_byte_write( buffer,baseaddr,offset,count);    return status;  }  KICK_DOG_AND_CHECK_DATA();  /* Check for the offset is not at the buffer boundary */  inbuff_offset = offset % SPANSION_BUFFER_WRITE_SIZE;  if(inbuff_offset)  {    status =fsi_spansion_byte_write( buffer,baseaddr,offset,                                  (SPANSION_BUFFER_WRITE_SIZE -inbuff_offset));    num_written += (SPANSION_BUFFER_WRITE_SIZE -inbuff_offset);    KICK_DOG_AND_CHECK_DATA();  }  if(status == FLASH_SUCCESS)  {    while(num_written < count)    {      num_to_copy = MIN(count-num_written, SPANSION_BUFFER_WRITE_SIZE);      if(num_to_copy < SPANSION_BUFFER_WRITE_SIZE)      {        status = fsi_spansion_byte_write( buffer+num_written,baseaddr,offset+                                          num_written,num_to_copy);      }      else      {        KICK_DOG_AND_CHECK_DATA();        status =fsi_spansion_buffer_write(buffer+num_written,baseaddr,offset+                                          num_written,num_to_copy);      }      num_written += num_to_copy;      if(status != FLASH_SUCCESS)      {        return status;      }    }  }#ifdef FLASH_CHECK  {  	dword i;    volatile byte *part_base = ((volatile byte *) baseaddr + offset);      	for (i = 0; i < size; i++)  	{  	  if(part_base[i] != source[i])        ERR_FATAL("Write verify failed",0,0,0);      if ((i % 16)==0)  	    KICK_DOG_AND_CHECK_DATA();  	}  }#endif  return status;}/* fsi_spansion_write *//*===========================================================================FUNCTION FSI_SPANSION_BUFFER_WRITEDESCRIPTION  Write a block of bytes to an SPANSION part.DEPENDENCIES  The device must not be in erasing state.RETURN VALUE  FLASH_SUCCESS      -  If write completed normally  FLASH_TIMEOUT      -  If write operation timed outSIDE EFFECTS  None===========================================================================*/LOCAL flash_statusfsi_spansion_buffer_write (byte *buffer,               flash_ptr_type baseaddr,               dword offset,               dword count){  flash_status status = FLASH_SUCCESS;  dword word_addr;  byte *buf_ptr = buffer;  dword wcount,word_val=0,i;  volatile byte *part_base;  volatile word *wptr,*current_wptr=0;  byte timeout_cnt=0;  volatile word tmp;  /*----------------------------------------------------------------*/  KICK_DOG_AND_CHECK_DATA();  if(!count){      return FLASH_SUCCESS;  }  if(offset)  {     word_addr = offset/2;  }  else  {     word_addr = offset;  }  part_base = ((volatile byte *) baseaddr + offset);  /* Do word operations. */  wptr = (volatile word *) part_base;  /*========================================================   *   * Write buffer programming command sequences   *   *   * 1. Issue the unlock command 1   Addr: 0x555  Data: 0x00AA   *   * 2. Issue the unlock command 2   Addr: 0x2AA  Data: 0x0055   *   * 3. Write the buffer load   *       Addr:  starting address   Data: 0x0025   *   * 4. Specify the number of program Location   *       Addr:  Starting addresss     Data: word len   *   * 5. Load 1st data word   *        Addr:  Starting Address     Data: program data   *   * 6. Load next data word   *        Addr: Write buffer location Data: program data   *   * 7. ......   *   * 8. Load last data word   *       Addr: Write buffer location  Data: program data   *   * 9. Write buffer program confirm.  This command must follow the last   *     write buffer location loaded, or the operation will ABORT.   *       Addr: Sector Address         Data: 0x0029   *   *==================================================================*/  /* Commands to unlock the device */  *(baseaddr + 0x0555L) = 0x00AA;  *(baseaddr + 0x02AAL) = 0x0055;  /* Command to do the buffer write */  *(baseaddr + word_addr)           = 0x0025;  /* Load the len of the buffer to the starting address */  wcount = (count/2) -1;  *(baseaddr + word_addr)           = wcount;  /* Write to the buffer */  for(i=0;i<(count/2);i++)  {    /* Put together the next word to write to Flash. */    word_val  = (buf_ptr[1] << 8) | buf_ptr[0];    *wptr = word_val;     //lint !e734 will never exceed 2 bytes    current_wptr = wptr;    wptr++;    buf_ptr+=2;  }  /* Write buffer program confirm */  *current_wptr  = 0x29;       //lint !e794 this pointer will have ptr assigned   clk_busy_wait(4);   /* Wait for the write. */  while (1)    //lint !e716 while(1) has break and return..  {    tmp = *current_wptr;   //lint !e794 current_wptr will have ptr assigned      /* Exit when finished. */    if ((tmp & FS_AMD_DQ7) != (word_val & FS_AMD_DQ7))    {      if ((tmp & FS_AMD_DQ5) != 0)      {        timeout_cnt++;          if(timeout_cnt >= SPANSION_MAX_TIMEOUT_CNT)        {          *(baseaddr + 0x555) = 0xAA;          *(baseaddr + 0x2AA) = 0x55;          *(baseaddr + 0x555) = 0xF0;          return FLASH_TIMEOUT;        }      }    }    else    {      break;    }  }/* while */  KICK_DOG_AND_CHECK_DATA();  return status;}/*===========================================================================FUNCTION FSI_SPANSION_BYTE_WRITEDESCRIPTION  Write a block of bytes to an SPANSION part.DEPENDENCIES  The fs_dev_init must have been called.  The device must not be in  erasing state.RETURN VALUE  FLASH_SUCCESS      -  If write completed normally  FLASH_TIMEOUT      -  If write operation timed outSIDE EFFECTS  None===========================================================================*/LOCAL flash_statusfsi_spansion_byte_write (byte *buffer,               flash_ptr_type baseaddr,               dword offset,               dword count){  volatile byte *part_base, *bptr;  volatile word *wptr, *check_ptr;  word value;  word tmp;  byte timeout_cnt=0;    /*---------------------------------------------------------------*/  KICK_DOG_AND_CHECK_DATA();  /* Base address of operation. */  part_base = ((volatile byte *) baseaddr + offset);  check_ptr = (volatile word *) ((dword) part_base & ~1);  (void)check_ptr; // is this pointer and assignment above really needed...??!!  /* Determine if the block is aligned or not. */  if (((dword) buffer & 1) == 0      && (offset & 1) == 0      && (count & 1) == 0)  {    /* Do word operations. */    wptr = (volatile word *) part_base;    /* Since we're already aligned, we could compare with 0, but the       1 will be needed for future optimizations. */    while (count > 1)    {      value = *((word *) buffer);      *(baseaddr + 0x555) = 0xAA;      *(baseaddr + 0x2AA) = 0x55;      *(baseaddr + 0x555) = 0xA0;      *wptr = value;      /* Wait 4 micro second before check for status.         Per Spansion recommendation */      clk_busy_wait(4);          /* Wait for the write. */      while (1)    //lint !e716 while(1) has break and return..      {        tmp = *wptr;         /* Exit when finished. */        if ((tmp & FS_AMD_DQ7) != (value & FS_AMD_DQ7))        {            if ((tmp & FS_AMD_DQ5) != 0)          {            timeout_cnt++;            if(timeout_cnt >= SPANSION_MAX_TIMEOUT_CNT)            {              *wptr = 0xF0;              return FLASH_TIMEOUT;            }           }        }        else        {          break;        }      }      buffer += 2;      wptr   += 1;      count  -= 2;    }  }  else  {    /* Do byte operations. */    bptr = part_base;    while (count > 0)    {      value = *buffer;      /* The command accesses need to be word oriented or the data         will be placed on the wrong data lines.  Compute a word         pointer from the byte pointer that is always at an even         address. */      wptr = ((volatile word *) ((dword) bptr & ~1));      /* Get old value. */      tmp = *wptr;      *(baseaddr + 0x555) = 0xAA;      *(baseaddr + 0x2AA) = 0x55;      *(baseaddr + 0x555) = 0xA0;      /* Assumes little endian. */      if (((dword) bptr & 1) == 0)        value = tmp & (value | 0xFF00);      else        value = tmp & ((value << 8) | 0x00FF);      *wptr = value;       /* Wait 4 micro second before check for status.         Per Spansion recommendation */      clk_busy_wait(4);      /* Wait for the write. */      while (1)    //lint !e716 while(1) has break and return..      {        tmp = *wptr;          /* Exit when finished. */        if ((tmp & FS_AMD_DQ7) != (value & FS_AMD_DQ7))        {            if ((tmp & FS_AMD_DQ5) != 0)          {            timeout_cnt++;            if(timeout_cnt >= SPANSION_MAX_TIMEOUT_CNT)            {              *(baseaddr + 0x0) = 0xF0;              return FLASH_TIMEOUT;            }          }        }        else        {          break;        }      }      buffer += 1;      bptr   += 1;      count  -= 1;    }  }  KICK_DOG_AND_CHECK_DATA();  return FLASH_SUCCESS;}

⌨️ 快捷键说明

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