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

📄 fsintrnl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  }

  /*-------------------------------------------------------------------*/
  /* Return if the set size did not increase.                          */
  /*-------------------------------------------------------------------*/
  if (set_increase == FALSE)
    return;

  /*-------------------------------------------------------------------*/
  /* If volume is full or adjust erase not set, don't increment.       */
  /*-------------------------------------------------------------------*/
  if ((Flash->files_tbl->tbl[1].entry.comm.one_past_last.offset ||
       !adjust_erase))
  {
    Flash->set_blocks = old_size;
    return;
  }

  /*-------------------------------------------------------------------*/
  /* Try to fill -1 slots with block numbers.                          */
  /*-------------------------------------------------------------------*/
  s_optimal = (Flash->set_blocks + 1) * 3 / 4;
  for (s = 0; s < Flash->set_blocks; ++s)
    if (!check_recycle || Flash->erase_set[s] == -1)
    {
      /*---------------------------------------------------------------*/
      /* Choose the best block among the non-free ones.                */
      /*---------------------------------------------------------------*/
      for (b = 0, max_f = -1; b < Flash->num_blocks; ++b)
      {
        /*-------------------------------------------------------------*/
        /* If block is not bad, ctrl and has no free sects, candidate  */
        /*-------------------------------------------------------------*/
        if (!Flash->blocks[b].bad_block &&
            !Flash->blocks[b].ctrl_block &&
            Flash->sect_tbl[(b + 1) * Flash->block_sects - 1].prev !=
            FFREE_SECT)
        {
          /*-----------------------------------------------------------*/
          /* Sanity check.                                             */
          /*-----------------------------------------------------------*/
          PfAssert(Flash->high_wear >= Flash->blocks[b].wear_count);

          /*-----------------------------------------------------------*/
          /* Check that block is not in erase set.                     */
          /*-----------------------------------------------------------*/
          for (s1 = 0; s1 < Flash->set_blocks; ++s1)
            if (Flash->erase_set[s1] == b)
              break;

          if (s1 == Flash->set_blocks)
          {
            /*---------------------------------------------------------*/
            /* Compute the selector.                                   */
            /*---------------------------------------------------------*/
            if (s < s_optimal)
              f_b = (int)(16 * (Flash->block_sects -
                          Flash->blocks[b].used_sects) +
                    (Flash->high_wear - Flash->blocks[b].wear_count));
            else
              f_b = (int)(Flash->high_wear -Flash->blocks[b].wear_count);

            /*---------------------------------------------------------*/
            /* If better candidate, remember it.                       */
            /*---------------------------------------------------------*/
            if (max_f < f_b)
            {
              max_f = f_b;
              max_b = b;
            }
          }
        }
      }

      /*---------------------------------------------------------------*/
      /* If no more replacement blocks, stop.                          */
      /*---------------------------------------------------------------*/
      if (max_f == -1)
        break;

      /*---------------------------------------------------------------*/
      /* Add block to erase set. If recycle not possible afterwards,   */
      /* take block out and stop.                                      */
      /*---------------------------------------------------------------*/
      Flash->erase_set[s] = max_b;
      if (check_recycle && recycle_not_possible())
      {
        Flash->erase_set[s] = -1;
        break;
      }
    }

  /*-------------------------------------------------------------------*/
  /* If there are still -1 entries in erase set, readjust set size.    */
  /*-------------------------------------------------------------------*/
  while (Flash->erase_set[Flash->set_blocks - 1] == -1 &&
         Flash->set_blocks > 1)
    --Flash->set_blocks;
  PfAssert(Flash->set_blocks >= old_size);
}

/***********************************************************************/
/* recycle_finish: Perform end of recycle - update sector table,       */
/*              write ctrl info, update sig bytes and wear count       */
/*                                                                     */
/*      Inputs: check_full = flag to check for volume full             */
/*              write_ctrl = flag to write ctrl                        */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure                            */
/*                                                                     */
/***********************************************************************/
static int recycle_finish(int check_full, int write_ctrl)
{
  ui32 s, sect, i, old_set_size = Flash->set_blocks;

#if TIMING
clock_t sample = clock();
#endif

  /*-------------------------------------------------------------------*/
  /* Perform a sync now to save everything before erasing block if a   */
  /* sync is required. A sync is required on the last recycle in a     */
  /* contiguous set of recycles.                                       */
  /*-------------------------------------------------------------------*/
  if (write_ctrl && FlashWrCtrl(SKIP_ADJUST_ERASE))
    return -1;
#if TIMING
RecWrCtrl += (clock() - sample);
#endif

  /*-------------------------------------------------------------------*/
  /* Set all sectors in erase set back to free.                        */
  /*-------------------------------------------------------------------*/
  for (s = 0; s < Flash->set_blocks; ++s)
    if (Flash->erase_set[s] != -1)
    {
      PfAssert(!Flash->blocks[Flash->erase_set[s]].ctrl_block);
      sect = Flash->erase_set[s] * Flash->block_sects;
      Flash->sect_tbl[Flash->last_free_sect].next =
                                         (ui16)(sect + Flash->hdr_sects);
      for (i = 0; i < Flash->block_sects; ++i, ++sect)
      {
        if (Flash->sect_tbl[sect].prev == FDRTY_SECT)
        {
          ++Flash->free_sects;
          Flash->sect_tbl[sect].prev = FFREE_SECT;
          Flash->sect_tbl[sect].next = (ui16)(sect + 1);
        }
        else if (Flash->type == FFS_NOR)
        {
          PfAssert(Flash->sect_tbl[i].prev == FHDER_SECT);
        }
        else
        {
          PfAssert(FALSE); /*lint !e644 !e506 !e774 */
        }
      }
      Flash->last_free_sect = sect - 1;
      Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
    }

  /*-------------------------------------------------------------------*/
  /* Do the last part of recycle: erase block, write signature bytes,  */
  /* and modify wear count, and check for volume full if needed.       */
  /*-------------------------------------------------------------------*/
  if (erase_set((int)old_set_size) || (check_full && !FlashRoom(0)))
    return -1;

  /*-------------------------------------------------------------------*/
  /* Choose the next erase set.                                        */
  /*-------------------------------------------------------------------*/
  FlashChooseEraseSet(USE_WEAR);
  for (;;)
  {
    /*-----------------------------------------------------------------*/
    /* If recycles can proceed, we have a valid erase set.             */
    /*-----------------------------------------------------------------*/
    if (!recycle_not_possible())
      break;

    /*-----------------------------------------------------------------*/
    /* Attempt to select an erase set without looking at wear count.   */
    /*-----------------------------------------------------------------*/
    FlashChooseEraseSet(IGNORE_WEAR);

    /*-----------------------------------------------------------------*/
    /* If recycles can proceed, we have a valid erase set.             */
    /*-----------------------------------------------------------------*/
    if (Flash->set_blocks == 1 || !recycle_not_possible())
      break;

    /*-----------------------------------------------------------------*/
    /* Shrink the erase set by one block.                              */
    /*-----------------------------------------------------------------*/
    Flash->erase_set[--Flash->set_blocks] = -1;
  }

  /*-------------------------------------------------------------------*/
  /* Remember if control info was written.                             */
  /*-------------------------------------------------------------------*/
  Flash->wr_ctrl = write_ctrl;

#if TIMING
++RecCount;
#endif
  return 0;
}

/***********************************************************************/
/* mark_ctrl_info: Clear header bit to mark recent control information */
/*                                                                     */
/*       Input: sector = start of most recent control information      */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure                            */
/*                                                                     */
/***********************************************************************/
static int mark_ctrl_info(uint sector)
{
  uint byte_off, sect_off;
  ui32 hdr_start, byte_addr;
  FlashGlob *vol;
  int status;

  /*-------------------------------------------------------------------*/
  /* The sector cannot be a header sector.                             */
  /*-------------------------------------------------------------------*/
  PfAssert((sector % Flash->block_sects) >= Flash->hdr_sects);

  /*-------------------------------------------------------------------*/
  /* Get pointer to the beginning of the header.                       */
  /*-------------------------------------------------------------------*/
  sect_off = sector % Flash->block_sects;
  hdr_start = sector - sect_off;

  /*-------------------------------------------------------------------*/
  /* Figure out how far from the beginning of the header we are.       */
  /*-------------------------------------------------------------------*/
  byte_off = sect_off / 8;
  PfAssert(byte_off < Flash->hdr_sects * Flash->sect_sz);

  /*-------------------------------------------------------------------*/
  /* Calculate address of byte to write.                               */
  /*-------------------------------------------------------------------*/
  byte_addr = Flash->mem_base + hdr_start * Flash->sect_sz + byte_off;

  /*-------------------------------------------------------------------*/
  /* Release exclusive access to the flash file system.                */
  /*-------------------------------------------------------------------*/
  vol = Flash;
  semPost(FlashSem);

  /*-------------------------------------------------------------------*/
  /* Mark location of most recent control information.                 */
  /*-------------------------------------------------------------------*/
  status = vol->driver.nor.write_byte(byte_addr,
                                      (ui8)~(1 << (7 - sect_off % 8)),
                                      vol->vol);

  /*-------------------------------------------------------------------*/
  /* Acquire exclusive access to the flash file system.                */
  /*-------------------------------------------------------------------*/
  semPend(FlashSem, WAIT_FOREVER);
  Flash = vol;

  if (status)
  {
    set_errno(EIO);
    return -1;
  }

  return 0;
}

/***********************************************************************/
/* get_next_used_sector: Look for the next non_dirty_sector            */
/*                                                                     */
/*      Inputs: sector = sector past which to find used sector         */
/*              sp = index in erase_set to current block               */
/*                                                                     */
/*     Returns: Pointer to the next sector, or -1 when done            */
/*                                                                     */
/***********************************************************************/
static uint get_next_used_sector(uint sector, int *sp)
{

⌨️ 快捷键说明

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