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

📄 fsintrnl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*     Returns: 0 on success, -1 on failure                            */
/*                                                                     */
/***********************************************************************/
static int free_block(ui32 block, ui32 last_dirty, int *adjust_set,
                      int *modified)
{
  ui32 i, j, last_sect = (block + 1) * Flash->block_sects - 1;
  int do_erase, s, add_to_free_list = TRUE;

  /*-------------------------------------------------------------------*/
  /* Erase only good, non used, non control blocks.                    */
  /*-------------------------------------------------------------------*/
  if (!Flash->blocks[block].bad_block && !Flash->blocks[block].ctrl_block
      && Flash->blocks[block].used_sects == 0)
  {
    /*-----------------------------------------------------------------*/
    /* If last sector in block is free, only consider if it's beginning*/
    /* of free list and it has dirty sectors on it.                    */
    /*-----------------------------------------------------------------*/
    if (Flash->sect_tbl[last_sect].prev == FFREE_SECT)
    {
      /*---------------------------------------------------------------*/
      /* If first sector in block is free, skip block.                 */
      /*---------------------------------------------------------------*/
      if (Flash->sect_tbl[block * Flash->block_sects +
                          Flash->hdr_sects].prev == FFREE_SECT)
        return 0;

      /*---------------------------------------------------------------*/
      /* This block must be the beginning of the free list.            */
      /*---------------------------------------------------------------*/
      PfAssert(Flash->free_sect / Flash->block_sects == block);
      Flash->free_sect = block * Flash->block_sects + Flash->hdr_sects;
      add_to_free_list = FALSE;
    }

    /*-----------------------------------------------------------------*/
    /* First, free up all dirty sectors in block.                      */
    /*-----------------------------------------------------------------*/
    i = block * Flash->block_sects + Flash->hdr_sects;
    for (j = 0, do_erase = FALSE; j < Flash->block_sects; ++j)
      if (Flash->sect_tbl[i + j].prev == FDRTY_SECT)
      {
        ++Flash->free_sects;
        Flash->sect_tbl[i + j].prev = FFREE_SECT;
        Flash->sect_tbl[i + j].next = (ui16)(i + j + 1);
        do_erase = TRUE;
      }

    /*-----------------------------------------------------------------*/
    /* Erase block.                                                    */
    /*-----------------------------------------------------------------*/
    if (do_erase)
    {
      /*---------------------------------------------------------------*/
      /* If blocks from erase set are erased, readjust erase set.      */
      /*---------------------------------------------------------------*/
      for (s = 0; s < Flash->set_blocks; ++s)
        if (Flash->erase_set[s] == block)
          break;
      if (s < Flash->set_blocks)
      {
        Flash->erase_set[s] = -1;
        *adjust_set = TRUE;
      }

      *modified = TRUE;

      if (FlashEraseBlock(block))
        return -1;

      /*---------------------------------------------------------------*/
      /* If block is not bad, tie it to free list.                     */
      /*---------------------------------------------------------------*/
      if (!Flash->blocks[block].bad_block && add_to_free_list)
      {
        /*-------------------------------------------------------------*/
        /* Free sector needs to be updated if invalid.                 */
        /*-------------------------------------------------------------*/
        if (Flash->free_sect == (ui32)-1)
        {
          Flash->free_sect = i;
          Flash->last_free_sect = i + Flash->block_sects -
                                  Flash->hdr_sects - 1;
          Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;

          /*-----------------------------------------------------------*/
          /* Tie last dirty with new free so resume has contiguous list*/
          /*-----------------------------------------------------------*/
          if (last_dirty != (ui32)-1)
            Flash->sect_tbl[last_dirty].next = (ui16)Flash->free_sect;
        }

        /*-------------------------------------------------------------*/
        /* Add block to end of free list.                              */
        /*-------------------------------------------------------------*/
        else
        {
          PfAssert(Flash->free_sect / Flash->block_sects != block);
          PfAssert(Flash->sect_tbl[Flash->free_sect].prev == FFREE_SECT
                && Flash->sect_tbl[Flash->last_free_sect].prev ==
                   FFREE_SECT);
          Flash->sect_tbl[Flash->last_free_sect].next = (ui16)i;
          Flash->last_free_sect = i + Flash->block_sects -
                                  Flash->hdr_sects - 1;
          Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
        }
      }
    }
  }
  return 0;
}

/***********************************************************************/
/* check_flash: Ensure that the 'free' sectors are actually free, the  */
/*              'dirty' are dirty, count the number of dirty sectors   */
/*              and set free_sect                                      */
/*                                                                     */
/*      Output: modified = flag to due a sync if stat changes          */
/*       Input: fast_mount_check = check NOR/MLC for fast mount        */
/*                                                                     */
/*     Returns: FFS_NORMAL_POWER_UP on a normal shut down,             */
/*              FFS_SLOW_POWER_UP on an abnormal shut down,            */
/*              FFS_FAILED_POWER_UP on error                           */
/*                                                                     */
/***********************************************************************/
static int check_flash(int *modified, int fast_mount_check)
{
  ui32 i, j, sect, min_free_block, block;
  ui32 free_sects = Flash->free_sects, last_dirty = (ui32)-1;
  int adjust_set = FALSE;

  PfAssert(Flash->sect_tbl[Flash->free_sect].prev == FFREE_SECT &&
           Flash->last_free_sect % Flash->block_sects ==
           Flash->block_sects - 1);

  /*-------------------------------------------------------------------*/
  /* For NAND/MLC assume it's fast mount and adjust later.             */
  /*-------------------------------------------------------------------*/
  Flash->fast_mount = (Flash->type != FFS_NOR);

  /*-------------------------------------------------------------------*/
  /* Count the used sectors.                                           */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < Flash->num_sects; ++i)
    if (used_sect(i))
    {
      ++Flash->used_sects;
      ++Flash->blocks[i / Flash->block_sects].used_sects;
    }

  /*-------------------------------------------------------------------*/
  /* Take the ctrl sectors out of the used sectors block counts.       */
  /*-------------------------------------------------------------------*/
  for (i = Flash->frst_ctrl_sect; i != FLAST_SECT;
       i = Flash->sect_tbl[i].next)
  {
    --Flash->blocks[i / Flash->block_sects].used_sects;
    --Flash->used_sects;
  }

  /*-------------------------------------------------------------------*/
  /* Read the fast mount flag for NOR.                                 */
  /*-------------------------------------------------------------------*/
  if (Flash->type == FFS_NOR)
  {
    /*-----------------------------------------------------------------*/
    /* Check the fast mount flag.                                      */
    /*-----------------------------------------------------------------*/
    if (fast_mount_check)
    {
      if (Flash->read_sector(Flash->tmp_sect, Flash->last_ctrl_sect))
      {
        set_errno(EIO);
        return FFS_FAILED_POWER_UP;
      }
      Flash->fast_mount = (Flash->tmp_sect[Flash->sect_sz - 1] ==
                           FAST_MOUNT);
    }

    /*-----------------------------------------------------------------*/
    /* Rebuild the erase set at the time of power off.                 */
    /*-----------------------------------------------------------------*/
    FlashCountAndChoose(SKIP_CHECK_RECYCLE);
  }

  /*-------------------------------------------------------------------*/
  /* Check for fast mount.                                             */
  /*-------------------------------------------------------------------*/
  if (Flash->type != FFS_NOR || !Flash->fast_mount)
  {
    /*-----------------------------------------------------------------*/
    /* A fast mount happens when all the sectors past frst_free_ctrl   */
    /* sector in same block are free, the first FOPEN_MAX sectors on   */
    /* free list are free(cache size) plus the next block worth of     */
    /* sectors is free (it could have been selected for control info   */
    /* and we got cut off).                                            */
    /*-----------------------------------------------------------------*/
    if (Flash->free_ctrl_sect != (ui32)-1)
      for (i = Flash->free_ctrl_sect; i % Flash->block_sects; ++i)
      {
        if (!Flash->empty_sect(i))
        {
          Flash->fast_mount = FALSE;
          Flash->free_ctrl_sect = (ui32)-1;
        }
        else if (Flash->free_ctrl_sect == (ui32)-1)
          Flash->free_ctrl_sect = i;
      }

    /*-----------------------------------------------------------------*/
    /* Now check all the free list, skipping sectors if fast mount.    */
    /*-----------------------------------------------------------------*/
    Flash->free_sects = 0;
    for (i = Flash->free_sect; i != FLAST_SECT;)
    {
      PfAssert(i < Flash->num_sects &&
               Flash->sect_tbl[i].prev == FFREE_SECT);

      /*---------------------------------------------------------------*/
      /* If known a priori or verified, count sector as free. First    */
      /* cache size worth of sectors plus next block worth of sectors  */
      /* are always checked.                                           */
      /*---------------------------------------------------------------*/
      if ((Flash->fast_mount &&
           Flash->free_sects > FOPEN_MAX + Flash->block_sects + 1) ||
          Flash->empty_sect(i))
      {
        ++Flash->free_sects;
        Flash->last_free_sect = i;
      }

      /*---------------------------------------------------------------*/
      /* Else mark sector as dirty.                                    */
      /*---------------------------------------------------------------*/
      else
      {
        Flash->fast_mount = FALSE;
        Flash->sect_tbl[i].prev = FDRTY_SECT;
        last_dirty = i;
      }

      /*---------------------------------------------------------------*/
      /* Move to next free sector.                                     */
      /*---------------------------------------------------------------*/
      i = Flash->sect_tbl[i].next;
    }
  }

  /*-------------------------------------------------------------------*/
  /* For fast mount NOR, set last free sector pointer.                 */
  /*-------------------------------------------------------------------*/
  else
    for (i = Flash->free_sect, Flash->free_sects = 0;;)
    {
      ++Flash->free_sects;
      if (Flash->sect_tbl[i].next == FLAST_SECT)
      {
        Flash->last_free_sect = i;
        break;
      }
      else
        i = Flash->sect_tbl[i].next;
    }

  /*-------------------------------------------------------------------*/
  /* If there were dirty sectors, invalidate all free sectors that     */
  /* preceeded the last dirty sector in list.                          */
  /*-------------------------------------------------------------------*/
  if (last_dirty != (ui32)-1)
  {
    for (i = Flash->free_sect; i != last_dirty;
         i = Flash->sect_tbl[i].next)
      if (Flash->sect_tbl[i].prev == FFREE_SECT)
      {
        --Flash->free_sects;
        Flash->sect_tbl[i].prev = FDRTY_SECT;
      }

    /*-----------------------------------------------

⌨️ 快捷键说明

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