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

📄 flash_nor.c

📁 Flash的驱动程序。包括市面上常见的Nor Flash和Nand Flash.基本上所有的Flash只需要简单修改就可以移植到其他应用。
💻 C
📖 第 1 页 / 共 2 页
字号:
/********************************************************************** * flash_nor.c * * NOR device level operations * * This file implements wrappers for device specific functions on * NOR flash parts.   * * Copyright (C) 2004-2006 Qualcomm, Inc. * **********************************************************************//*===========================================================================                        EDIT HISTORY FOR MODULE  This section contains comments describing changes made to the module.  Notice that changes are listed in reverse chronological order.  $Header: //depot/asic/msmshared/drivers/flash/MSM_FLASH.01.04/flash_nor.c#3 $ $DateTime: 2006/05/16 22:40:13 $ $Author: dhamimp $when         who     what, where, why--------     ---     ----------------------------------------------------------2005-12-05   dp      NOR Flash Driver Unification2006-01-27   dp      Added Intel MLC support2004-10-21   drh     Clean up warning message2004-07-20   drh     Remove MSM6050 conditional.  All MSM platforms support                     this code now.2004-02-23   drh     Support partition tables.                     Move MSM specific device bases table to flash_msm.c.2004-02-21   drh     Came from services/efs/fs_nor_device.c===========================================================================*//**************************************************************** * Include Files ***************************************************************/#include "flash.h"#include "flash_nor.h"#include "err.h"#include "comdef.h"#include "msg.h"#include "rex.h"#include "task.h"#include <string.h>uint16 fs_dev_max_sleep_counter=100;uint16 fs_dev_max_sleep_duration=50;#undef FSND_DEBUG/*lint -e613 -e668 upper layers already check for null pointers *///lint -e526 Don't warn about undefined extern symbols/**************************************************************** * Function Prototypes ***************************************************************/#ifdef FSND_DEBUGextern int printf(const char *fmt,...);#endif/* forward function prototype declarations */int fs_nor_device_bad_block_check(fs_device_t self, block_id block);int fs_nor_device_mark_block_bad(fs_device_t self, block_id block);char * fs_nor_device_name(fs_device_t self);uint32 fs_nor_device_block_count(fs_device_t self);uint32 fs_nor_device_block_size(fs_device_t self);uint32 fs_nor_device_page_size(fs_device_t self);int fs_nor_device_write_page (fs_device_t self, page_id page, void *data);int fs_nor_device_write_partial_page (fs_device_t self, page_id page,      void *data, int offset, int length);boolean fsi_ram_probe (void);int fs_nor_device_erase_block (fs_device_t self, block_id block);void *fs_nor_device_read_ptr (fs_device_t self, page_id page);int fs_nor_device_read_page (fs_device_t self, page_id page, void *data);int fs_nor_device_is_page_erased (fs_device_t self, page_id page);int fs_nor_device_start_erase_block (fs_device_t self, block_id block);int fs_nor_device_suspend_erase (fs_device_t self);int fs_nor_device_resume_erase (fs_device_t self);int fs_nor_device_erase_block_status(fs_device_t self);void cache_mmu_disable(void);void cache_mmu_re_enable(void);  /**************************************************************** * MACROS ***************************************************************//* On processors with CPU instruction cacheing, we must disable * cacheing during probe.  These macros make the code much * cleaner due to the conditional nature of the operation. */#define CACHE_DISABLE()  cache_mmu_disable()#define CACHE_REENABLE()  cache_mmu_re_enable()/**************************************************************** * Global Data ***************************************************************/static fs_device_write_style_t  fs_nor_device_get_write_style (fs_device_t dev);/* Array containing fs_device_data structure definitions for all the * nor devices currently supported */struct fs_device_data nor_devices_array[] = {  {    fs_nor_device_name,    0,                                 /* Maker ID */    0,                                 /* Device ID */    fs_nor_device_block_count,    fs_nor_device_block_size,    fs_nor_device_page_size,    0,                                 /* Total page size */    fs_nor_device_bad_block_check,    fs_nor_device_mark_block_bad,    fs_nor_device_write_page,    fs_nor_device_erase_block,    fs_nor_device_read_ptr,    fs_nor_device_read_page,    fs_nor_device_is_page_erased,    fs_nor_device_write_partial_page,    fs_nor_device_start_erase_block,    fs_nor_device_suspend_erase,    fs_nor_device_resume_erase,    fs_nor_device_erase_block_status,    0,                                 /* Is block erased */    0,                                 /* Read spare bytes */    0,                                 /* Read multiple pages */    0,                                 /* Copy page */    0,                                 /* Lock Unlock Locktight */        0,                                 /* open partition */    0,                                 /* partition table read */    0,                                 /* partition table write */    0,                                 /* set ECC state */    fs_nor_device_get_write_style,  }};/* Make sure that if EFS1 is compiled in, we do not duplicate these *//* Device base address. */volatile word *fs_dev_base;/* Which flash component did we detect. */fsi_nor_device *nor_device = NULL;fsi_erase_state_type fsi_erase_state;/* Most components need an address to check status of, or continue an   erase. */dword fsi_erase_location;static uint32 nv_byte_offset;static uint32 last_page_id;/**************************************************************** * Functions ***************************************************************//***********************************************************************FUNCTION      fs_nor_device_probeDESCRIPTION   This functions helps probe and identify the memory device              to see if it is one of the known nor devices. For every              nor device defnied in the array nor_devices_array the               probe_device function is called until the device is              successfully identified.DEPENDENCIES  NoneRETURN VALUE  fs_device_data structure pointer fs_device_t if the               nor device was identified successfully else FS_NO_DEVICE **********************************************************************/fs_device_tfs_nor_device_probe (void){  int i = 0;  uint32 block_count;  uint32 pages_in_block;  fs_device_t self;  ProbeTbl_t prPtr;    nor_device = NULL;  last_page_id = 0;    /* Cacheing of flash must be disabled during probe   * or flash will look like RAM and no flash will   * be found.   */  CACHE_DISABLE();  /* Probe at each of the possible addresses for flash 0   * using the MSM specific table provided from flash_msm.c  */  prPtr = probe_info_data_flash;    while ( nor_device == NULL ) {    fs_dev_base = prPtr->probe_addr;    if (fsi_ram_probe() == FALSE)      nor_device = prPtr->probe_fcn(fs_dev_base);#ifdef SHADOW_MODE    else    {      extern const fsi_nor_device RAM_NOR;      nor_device = (fsi_nor_device *)&RAM_NOR;    }#endif    i++;    prPtr++;    /* Do not go past the end of the array */    if ( i >= probe_info_size ) {      break;    }  }  if (nor_device == NULL)  {    CACHE_REENABLE();    return FS_NO_DEVICE;  }  /*  Call device's configure function.  On some flash parts,   *  this will unlock the sectors for programming, on others   *  it is merely a stub.   */  if ((*nor_device->ops->configure) (nor_device, fs_dev_base) != FLASH_SUCCESS)  {    CACHE_REENABLE();    return FS_NO_DEVICE;  }  nv_byte_offset = (uint32)&fs_dev_base[(nor_device->efs_info.efs_boffset >> 1)];#ifdef FSND_DEBUG  printf("\tnorprobe: Flash Base address 0x%x\n", FLASH_BASE);  printf("\tnorprobe: fs_dev_base 0x%x\n", fs_dev_base);  printf("\tnorprobe: NV byte offset 0x%x\n", nor_device->efs_info.efs_boffset);  printf("\tnorprobe: NV byte size 0x%x\n", nor_device->efs_info.efs_bsize);  printf("\tnorprobe: NV absolute start address 0x%x\n", nv_byte_offset);  printf("\tnorprobe: %s device\n", (char *)nor_device->name);#endif  self = (fs_device_t)&nor_devices_array[0];  block_count = self->block_count(self);  pages_in_block = self->block_size(self);  last_page_id = (block_count * pages_in_block) - 1;  CACHE_REENABLE();  return self;} /* End of fs_nor_device_probe *//***********************************************************************FUNCTION      fs_nor_device_write_pageDESCRIPTION   This functions writes a page data into the given page               on the deviceDEPENDENCIES  NoneRETURN VALUE  FS_DEVICE_DONE if write was successful else FS_DEVICE_FAIL**********************************************************************/intfs_nor_device_write_page (fs_device_t self, page_id page, void *data){  int length = self->page_size (self); //lint !e713 no loss of precision.#ifdef FSND_DEBUG  printf("\twrite: page 0x%x\n", page);#endif  return fs_nor_device_write_partial_page (self, page, data, 0, length);} /* End of fs_nor_device_write_page *//***********************************************************************FUNCTION      fs_nor_device_erase_blockiDESCRIPTION   This function erases the contents of the given block DEPENDENCIES  NoneRETURN VALUE  FS_DEVICE_DONE if erase was successful else FS_DEVICE_FAIL**********************************************************************/static intfs_nor_device_erase_blocki (uint32 block_addr){  flash_status status;  uint16 sleepcounter=0;  rex_timer_type  fs_dev_tout_timer;  rex_tcb_type      * my_tcb;  /* Determine if we have to check if an erase has terminated or     not. */  switch (fsi_erase_state)  {  case FSI_READ_MODE:    break;                                   /* Easy. */  case FSI_ERASING:    /* Must check to see if this erase is still running. */    ERR_FATAL ("not yet written 123", 0, 0, 0);    break;  case FSI_ERASE_SUSPENDED:    MSG_MED ("flash_nor: Attempt to start erase while erase is suspended",             0, 0, 0);    return FS_FAIL_S;  }  /* If we made it here, then the component is now sitting in read     mode.  Our offset is in bytes from the beginning of EFS, get a     pointer to the real data. */  fsi_erase_location = (nor_device->efs_info.efs_boffset >> 1) + (block_addr >> 1);    status = (*nor_device->ops->erase_start) (&fs_dev_base[(nor_device->efs_info.efs_boffset >> 1)],  	                                  (dword)block_addr);   if (status != FLASH_SUCCESS)    return FS_DEVICE_FAIL;  fsi_erase_state = FSI_ERASING;  do  {     sleepcounter++;    if(sleepcounter > fs_dev_max_sleep_counter)    {       my_tcb = rex_self();       rex_def_timer (&fs_dev_tout_timer, my_tcb, FS_OP_COMPLETE_SIG);       rex_timed_wait (FS_OP_COMPLETE_SIG, &fs_dev_tout_timer, fs_dev_max_sleep_duration);       sleepcounter=0;    }    status = (*nor_device->ops->erase_status)(&fs_dev_base[fsi_erase_location]);  } while (status != FLASH_SUCCESS);  fsi_erase_state = FSI_READ_MODE;    return FS_DEVICE_DONE;} /* End of fs_nor_device_erase_block *//***********************************************************************FUNCTION      fs_nor_device_erase_blockDESCRIPTION   This function is a wrapper for the actual erase block              and handles the special case of the last block, which              is actually several blocks.DEPENDENCIES  NoneRETURN VALUE  FS_DEVICE_DONE if erase was successful else FS_DEVICE_FAIL**********************************************************************/intfs_nor_device_erase_block (fs_device_t self, block_id block){  int status;  uint32 block_address;  int block_size_shift;  uint16 no_of_shifts = 1;  uint32 block_count = self->block_count(self);  /*uint32 last_block = block_count - 1;  uint32 small_block_count;  uint32 small_block_bytes;  int i;*/  /* bail out early if block is invalid */  if (block >= block_count)  {    return FS_DEVICE_FAIL;  }  block_size_shift = self->block_size (self);  while (block_size_shift != 2)  {    block_size_shift >>= 1;    no_of_shifts++;  }  /* Set the block address */  block_address = block << (FS_NOR_PAGE_ADDR_BITS + no_of_shifts);#ifdef FSND_DEBUG  printf("\terase: block address 0x%x\n", block_address);  printf("\terase: absolute address 0x%x\n",          (block_address + (nv_byte_offset)));#endif  status = fs_nor_device_erase_blocki(block_address);  if (status != FS_DEVICE_DONE)    return FS_DEVICE_FAIL; /* special code for handling of erase of     last block presently commented out to improve     EFS2 performance */  /* Call the internal function that does erase and wait for each   * block as necessary.  Account for the fact that the last "block"   * is really several blocks masquerading as one block to the    * public interface */   /*if (block != last_block)  {    status = fs_nor_device_erase_blocki(block_address);    if (status != FS_DEVICE_DONE)      return FS_DEVICE_FAIL;  }  else  {    small_block_count = nor_device->info.small_block_count;    small_block_bytes = nor_device->info.small_block_bytes;    for (i=0; i<small_block_count; i++)    {      status = fs_nor_device_erase_blocki(block_address);      if (status != FS_DEVICE_DONE)        return FS_DEVICE_FAIL;                  block_address += small_block_bytes;    }  }*/  /* End of special code for handling of last block */      return FS_DEVICE_DONE;} /* End of fs_nor_device_erase_block */  /***********************************************************************FUNCTION      fs_nor_device_is_page_erasedDESCRIPTION   This function checks if every byte of a given page is              erased DEPENDENCIES  NoneRETURN VALUE  TRUE if page is erased              FALSE if page is not erased, or any error occurs during                    checking**********************************************************************/intfs_nor_device_is_page_erased (fs_device_t self, page_id page){  uint32 page_address;  byte *rdptr;  uint32 page_size = self->page_size (self);  uint32 i;  page_address = page << FS_NOR_PAGE_ADDR_BITS;  /* Verify that the requested page is in range. */  if ((page_address + page_size) > (nor_device->efs_info.efs_bsize))  {    return FALSE;  }  /* get the address to the beginning of NV into a byte pointer   * and the add the page offset to it to come up with the   * page address   */  rdptr = (byte *) &fs_dev_base[(nor_device->efs_info.efs_boffset >> 1)];  rdptr += page_address;#ifdef FSND_DEBUG  printf("\tis_page_erased: absolute address 0x%x\n", rdptr);#endif  for (i=0; i<page_size; i++)  {    if (rdptr[i] != 0xFF)      return FALSE;  }  return TRUE;} /* END fs_nor_device_is_page_erased *//***********************************************************************FUNCTION      fs_nor_device_read_ptrDESCRIPTION   This function returns an address pointer to a page.DEPENDENCIES  NoneRETURN VALUE  Pointer to the page beginningSIDE EFFECTS  None**********************************************************************/void *fs_nor_device_read_ptr (fs_device_t self, page_id page)

⌨️ 快捷键说明

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