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

📄 fsinit.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /*-------------------------------------------------------------------*/
  semPend(vol->sem, WAIT_FOREVER);
  semPend(FlashSem, WAIT_FOREVER);
  Flash = vol;

  /*-------------------------------------------------------------------*/
  /* For mounted volumes clear out all the internal structures. Start  */
  /* with the cache.                                                   */
  /*-------------------------------------------------------------------*/
  sect_sz = (int)Flash->sect_sz;
  ReinitCache(&Flash->cache, sect_sz);

  /*-------------------------------------------------------------------*/
  /* Clear it's first files table, and if there are any left free them.*/
  /*-------------------------------------------------------------------*/
  FsReadCWD(&dummy, (void *)&curr_dir);
  for (i = 2; i < FNUM_ENT; ++i)
  {
    Flash->files_tbl->tbl[i].type = FEMPTY;

    /*-----------------------------------------------------------------*/
    /* If the current directory is this entry, set it to first entry   */
    /* in the table, the root directory.                               */
    /*-----------------------------------------------------------------*/
    if (curr_dir == &Flash->files_tbl->tbl[i])
    {
      ++Flash->files_tbl->tbl[0].entry.dir.cwds;
      FsSaveCWD(dummy, (ui32)&Flash->files_tbl->tbl[0]);
    }
  }
  Flash->files_tbl->free = FNUM_ENT - 2;

  /*-------------------------------------------------------------------*/
  /* Set the root dir's first entry to NULL.                           */
  /*-------------------------------------------------------------------*/
  Flash->files_tbl->tbl[0].entry.dir.first = NULL;

  /*-------------------------------------------------------------------*/
  /* Free all tables except for the first one.                         */
  /*-------------------------------------------------------------------*/
  for (temp_tbl = Flash->files_tbl->next_tbl; temp_tbl; )
  {
    /*-----------------------------------------------------------------*/
    /* If the current directory is in this table set it to first entry */
    /* for this volume, the root directory.                            */
    /*-----------------------------------------------------------------*/
    if (curr_dir >= &temp_tbl->tbl[0] &&
        curr_dir < &temp_tbl->tbl[FNUM_ENT])
    {
      ++Flash->files_tbl->tbl[0].entry.dir.cwds;
      FsSaveCWD(dummy, (ui32)&Flash->files_tbl->tbl[0]);
    }

    prev_tbl = temp_tbl;
    temp_tbl = temp_tbl->next_tbl;
    free(prev_tbl);
  }
  Flash->files_tbl->next_tbl = NULL;

  /*-------------------------------------------------------------------*/
  /* Update file tables size.                                          */
  /*-------------------------------------------------------------------*/
  Flash->tbls_size = (OFDIR_SZ + OFCOM_SZ + 1 +
                      strlen(Flash->files_tbl->tbl[0].entry.dir.name));
#if QUOTA_ENABLED
  if (Flash->quota_enabled)
    Flash->tbls_size += OFDIR_QUOTA_SZ;
#endif /* QUOTA_ENABLED */

  /*-------------------------------------------------------------------*/
  /* Set sect_tbl so that all valid blocks contain free sects.         */
  /*-------------------------------------------------------------------*/
  for (block = 0; block < Flash->num_blocks; ++block)
  {
    /*-----------------------------------------------------------------*/
    /* If valid block, mark all sectors as free.                       */
    /*-----------------------------------------------------------------*/
    if (!Flash->blocks[block].bad_block)
    {
      /*---------------------------------------------------------------*/
      /* Get first sector in block and link it with last sector in     */
      /* previous block, if such sector exists.                        */
      /*---------------------------------------------------------------*/
      sect = block * Flash->block_sects + Flash->hdr_sects;

      /*---------------------------------------------------------------*/
      /* Since all data sects in block will be free, clear used count. */
      /*---------------------------------------------------------------*/
      Flash->blocks[block].used_sects = 0;
      Flash->blocks[block].ctrl_block = FALSE;
      for (i = Flash->hdr_sects; i < Flash->block_sects; ++i, ++sect)
      {
        /*-------------------------------------------------------------*/
        /* If sector not free, mark it as dirty.                       */
        /*-------------------------------------------------------------*/
        if (Flash->sect_tbl[sect].prev != FFREE_SECT)
          Flash->sect_tbl[sect].prev = FDRTY_SECT;
      }
    }
  }

  /*-------------------------------------------------------------------*/
  /* There are no more used or ctrl sectors.                           */
  /*-------------------------------------------------------------------*/
  Flash->used_sects = 0;
  Flash->frst_ctrl_sect = Flash->last_ctrl_sect = (ui32)-1;
  Flash->free_ctrl_sect = (ui32)-1;
  Flash->ctrl_sects = Flash->ctrl_size = 0;

  /*-------------------------------------------------------------------*/
  /* Set all other variables related to volume.                        */
  /*-------------------------------------------------------------------*/
  Flash->total_free = FNUM_ENT - 2;
  Flash->total = FNUM_ENT;

#if QUOTA_ENABLED
  /*-------------------------------------------------------------------*/
  /* Reset root quota values if volume uses quotas.                    */
  /*-------------------------------------------------------------------*/
  if (Flash->quota_enabled)
  {
    FDIR_T *dir_t = &Flash->files_tbl->tbl[0].entry.dir;
    dir_t->min_q = 0;
    dir_t->free_below = 0;
    dir_t->res_below = 0;
    dir_t->used = strlen(dir_t->name) + 1 + OFDIR_SZ + OFDIR_QUOTA_SZ +
                  OFCOM_SZ;
    dir_t->free = dir_t->max_q - dir_t->used;
  }
#endif /* QUOTA_ENABLED */

  /*-------------------------------------------------------------------*/
  /* Do a sync now to save the state of the system.                    */
  /*-------------------------------------------------------------------*/
  if (FlashSync(DO_SYNC) != NULL)
  {
    semPost(FlashSem);
    semPost(vol->sem);
    return -1;
  }

  /*-------------------------------------------------------------------*/
  /* Erase all sectors that need erasing.                              */
  /*-------------------------------------------------------------------*/
  if (FlashClean())
  {
    semPost(FlashSem);
    semPost(vol->sem);
    return -1;
  }

  /*-------------------------------------------------------------------*/
  /* Release access to flash file system and this volume.              */
  /*-------------------------------------------------------------------*/
  semPost(FlashSem);
  semPost(vol->sem);
  return 0;
}

/***********************************************************************/
/* next_free_block: Chooses the smallest wear count block              */
/*                                                                     */
/*     Returns: Smallest block, or -1 if no such block exists          */
/*                                                                     */
/***********************************************************************/
static int next_free_block(void)
{
  int block, nxt_free_blck = -1;

  /*-------------------------------------------------------------------*/
  /* Look through all blocks for one with smallest wear count.         */
  /*-------------------------------------------------------------------*/
  for (block = 0; block < Flash->num_blocks; ++block)
    if (!(Flash->blocks[block].bad_block ||
          Flash->blocks[block].ctrl_block))
    {
      if (nxt_free_blck == -1 || Flash->blocks[block].wear_count <
          Flash->blocks[nxt_free_blck].wear_count)
        nxt_free_blck = block;
    }

  /*-------------------------------------------------------------------*/
  /* If such a block found, temporarily mark its ctrl_block so it's    */
  /* not counted next time around.                                     */
  /*-------------------------------------------------------------------*/
  if (nxt_free_blck != -1)
    Flash->blocks[nxt_free_blck].ctrl_block = TRUE;

  return nxt_free_blck;
}

/***********************************************************************/
/* set_first_free: Readjust free list and clean blocks that held old   */
/*              ctrl info                                              */
/*                                                                     */
/*     Returns: 0 on success, -1 on error                              */
/*                                                                     */
/***********************************************************************/
static int set_first_free(void)
{
  int old_1st_ctrl_block = -1, old_2nd_ctrl_block = -1;
  int frst_free_block = -1, block, status;
  ui32 addr, hdr, sect, i;
  FlashGlob *vol;

  /*-------------------------------------------------------------------*/
  /* Find the block with lowest wear count that has no ctrl info.      */
  /*-------------------------------------------------------------------*/
  for (block = 0; block < Flash->num_blocks; ++block)
    if (!(Flash->blocks[block].bad_block ||
          Flash->blocks[block].ctrl_block))
    {
      if (frst_free_block == -1 || Flash->blocks[block].wear_count <
          Flash->blocks[frst_free_block].wear_count)
        frst_free_block = block;
    }

  /*-------------------------------------------------------------------*/
  /* Mark all dirty/ctrl sectors as free.                              */
  /*-------------------------------------------------------------------*/
  for (block = 0; block < Flash->num_blocks; ++block)
  {
    if (!Flash->blocks[block].bad_block)
    {
      /*---------------------------------------------------------------*/
      /* If this is a control block, remember it.                      */
      /*---------------------------------------------------------------*/
      if (Flash->blocks[block].ctrl_block)
      {
        Flash->blocks[block].ctrl_block = FALSE;
        if (old_1st_ctrl_block == -1)
          old_1st_ctrl_block = block;
        else
        {
          PfAssert(old_2nd_ctrl_block == -1);
          old_2nd_ctrl_block = block;
        }
      }

      /*---------------------------------------------------------------*/
      /* Bump up the wear count.                                       */
      /*---------------------------------------------------------------*/
      Flash->blocks[block].wear_count += 1;
      if (Flash->high_wear < Flash->blocks[block].wear_count)
        Flash->high_wear = Flash->blocks[block].wear_count;

      /*---------------------------------------------------------------*/
      /* Make sure all sectors are free.                               */
      /*---------------------------------------------------------------*/
      sect = block * Flash->block_sects + Flash->hdr_sects;
      for (i = Flash->hdr_sects; i < Flash->block_sects; ++i, ++sect)
      {
        if (Flash->sect_tbl[sect].prev != FFREE_SECT)
        {
          Flash->sect_tbl[sect].prev = FFREE_SECT;
          ++Flash->free_sects;
        }
        Flash->sect_tbl[sect].next = (ui16)(sect + 1);
      }
    }
  }

  /*-------------------------------------------------------------------*/
  /* There are no more ctrl sectors.                                   */
  /*-------------------------------------------------------------------*/
  Flash->frst_ctrl_sect = Flash->last_ctrl_sect = (ui32)-1;
  Flash->ctrl_sects = Flash->ctrl_size = 0;
  Flash->free_ctrl_sect = (ui32)-1;

  /*-------------------------------------------------------------------*/
  /* Readjust free sector list. When rearranging free list, place      */
  /* blocks in ascending order of wear count and set the next erasable */
  /* set.                                                              */
  /*-------------------------------------------------------------------*/
  Flash->free_sect = frst_free_block * Flash->block_sects +
                     Flash->hdr_sects;
  Flash->last_free_sect = (frst_free_block + 1) * Flash->block_sects - 1;
  Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
  Flash->blocks[frst_free_block].ctrl_block = TRUE;
  for (i = 1;; ++i)
  {
    /*-----------------------------------------------------------------*/
    /* Choose next block to append to free list based on wear count.   */
    /*-----------------------------------------------------------------*/
    block = next_free_block();
    if (block == -1)
      break;

    /*-----------------------------------------------------------------*/
    /* Append next block to free list.                                 */
    /*-----------------------------------------------------------------*/
    Flash->sect_tbl[Flash->last_free_sect].next =
                   (ui16)(block * Flash->block_sects + Flash->hdr_sects);
    Flash->last_free_sect = (block + 1) * Flash->block_sects - 1;
    Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
  }

  /*-------------------------------------------------------------------*/
  /* Reset the erase set.                                              */
  /*-------------------------------------------------------------------*/
  Flash->set_blocks = 1;

⌨️ 快捷键说明

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