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

📄 fsintrnl.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
                    (Flash->high_wear - Flash->blocks[b].wear_count));
        if (Flash->high_wear >= Flash->blocks[b].wear_count + MAX_WDELTA)
          f_b += 65536;

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

    /*-----------------------------------------------------------------*/
    /* If candidate block found, place it in set.                      */
    /*-----------------------------------------------------------------*/
    if (max_f != -1)
    {
      Flash->erase_set[i] = max_b; /*lint !e644 */

      /*---------------------------------------------------------------*/
      /* Temporarily mark block as bad so it's not selected next time  */
      /* around.                                                       */
      /*---------------------------------------------------------------*/
      Flash->blocks[max_b].bad_block = TRUE;
    }

    /*-----------------------------------------------------------------*/
    /* Else stop and start using free blocks.                          */
    /*-----------------------------------------------------------------*/
    else
      break;
  }

  /*-------------------------------------------------------------------*/
  /* If not enough non-free blocks to fill set, use free blocks.       */
  /*-------------------------------------------------------------------*/
  for (; i < Flash->set_blocks; ++i)
  {
    /*-----------------------------------------------------------------*/
    /* Select the first free block and get the last sector in block.   */
    /*-----------------------------------------------------------------*/
    free_blck = Flash->free_sect / Flash->block_sects;
    last_in_free_block = (free_blck + 1) * Flash->block_sects - 1;
    PfAssert(Flash->sect_tbl[last_in_free_block].prev == FFREE_SECT);

    /*-----------------------------------------------------------------*/
    /* Put the block on the erase set.                                 */
    /*-----------------------------------------------------------------*/
    Flash->erase_set[i] = (int)free_blck;

    /*-----------------------------------------------------------------*/
    /* Advance free sector to next free block.                         */
    /*-----------------------------------------------------------------*/
    PfAssert(Flash->sect_tbl[last_in_free_block].next != FLAST_SECT);
    Flash->free_sect = Flash->sect_tbl[last_in_free_block].next;
    PfAssert(Flash->sect_tbl[Flash->free_sect].prev == FFREE_SECT);

    /*-----------------------------------------------------------------*/
    /* Mark all free sectors in erase set block to dirty.              */
    /*-----------------------------------------------------------------*/
    sect = free_blck * Flash->block_sects + Flash->hdr_sects;
    for (j = Flash->hdr_sects; j < Flash->block_sects; ++j, ++sect)
    {
      if (Flash->sect_tbl[sect].prev == FFREE_SECT)
      {
        Flash->sect_tbl[sect].prev = FDRTY_SECT;
        --Flash->free_sects;
      }
    }
  }

  /*-------------------------------------------------------------------*/
  /* Turn back to good all blocks in erasable set.                     */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < Flash->set_blocks; ++i)
    if (Flash->erase_set[i] != -1)
      Flash->blocks[Flash->erase_set[i]].bad_block = FALSE;
}

/***********************************************************************/
/* recycle_not_possible: Determine whether there are enough free       */
/*              sectors to recycle the erase set                       */
/*                                                                     */
/*     Returns: TRUE if not enough free, FALSE otherwise               */
/*                                                                     */
/***********************************************************************/
static int recycle_not_possible(void)
{
  ui32 block_sects, used, ctrl_blocks;

  FlashRecycleValues(&ctrl_blocks, &used, &block_sects);

  return ctrl_blocks * block_sects + used > Flash->free_sects;
}

/***********************************************************************/
/*   erase_set: Write signature bytes and erase erasable set as part   */
/*              of a recycle operation                                 */
/*                                                                     */
/*       Input: old_set_size = size of erasable set before adjustment  */
/*              due to write ctrl in recycle_finish()                  */
/*                                                                     */
/*     Returns: 0 on success, -1 on error                              */
/*                                                                     */
/***********************************************************************/
static int erase_set(int old_set_size)
{
  int s;

  /*-------------------------------------------------------------------*/
  /* Erase all blocks in next erasable set.                            */
  /*-------------------------------------------------------------------*/
  for (s = 0; s < old_set_size; ++s)
    if (Flash->erase_set[s] != -1 &&
        FlashEraseBlock((ui32)Flash->erase_set[s]))
      return -1;

  return 0;
}

/***********************************************************************/
/* in_erase_set: Determine if a block belongs to the erase set         */
/*                                                                     */
/*       Input: block = block to look for                              */
/*                                                                     */
/*     Returns: TRUE if block in set, FALSE otherwise                  */
/*                                                                     */
/***********************************************************************/
static int in_erase_set(ui32 block)
{
  ui32 s;

  /*-------------------------------------------------------------------*/
  /* Skip checking during format.                                      */
  /*-------------------------------------------------------------------*/
  if (Flash->set_blocks == 1)
    return FALSE;
  for (s = 0; s < Flash->set_blocks; ++s)
    if (Flash->erase_set[s] == block)
      return TRUE;
  return FALSE;
}

/***********************************************************************/
/* choose_free_block: Choose free block to write control info          */
/*                                                                     */
/*       Input: action = flag to indicate if in middle of reycles      */
/*                                                                     */
/*     Returns: First data sector in block, -1 on error                */
/*                                                                     */
/***********************************************************************/
static ui32 choose_free_block(int action)
{
  ui32 i, curr_sect, last_b4_curr = (ui32)-1, last_in_lowest;

  /*-------------------------------------------------------------------*/
  /* If free sector on block boundary, consider the first block in free*/
  /* list, otherwise skip it.                                          */
  /*-------------------------------------------------------------------*/
  if (Flash->free_sect % Flash->block_sects == Flash->hdr_sects)
    curr_sect = Flash->free_sect;
  else
  {
    last_b4_curr = (Flash->free_sect / Flash->block_sects + 1) *
                   Flash->block_sects - 1;
    curr_sect = Flash->sect_tbl[last_b4_curr].next;
  }

  /*-------------------------------------------------------------------*/
  /* Selected free block shouldn't be in erase set.                    */
  /*-------------------------------------------------------------------*/
  PfAssert(!in_erase_set(curr_sect / Flash->block_sects));

  /*-------------------------------------------------------------------*/
  /* If no more free blocks, error.                                    */
  /*-------------------------------------------------------------------*/
  if (curr_sect == FLAST_SECT)
    return (ui32)-1;

  /*-------------------------------------------------------------------*/
  /* Figure out last sector in free block and check block is free.     */
  /*-------------------------------------------------------------------*/
  last_in_lowest = curr_sect + Flash->block_sects - Flash->hdr_sects - 1;
  PfAssert(Flash->sect_tbl[curr_sect].prev == FFREE_SECT &&
           Flash->sect_tbl[last_in_lowest].prev == FFREE_SECT);

  /*-------------------------------------------------------------------*/
  /* Take block out of free list.                                      */
  /*-------------------------------------------------------------------*/
  if (curr_sect == Flash->free_sect)
  {
    /*-----------------------------------------------------------------*/
    /* If no more free blocks, error.                                  */
    /*-----------------------------------------------------------------*/
    if (Flash->sect_tbl[last_in_lowest].next == FLAST_SECT)
      return (ui32)-1;
    Flash->free_sect = Flash->sect_tbl[last_in_lowest].next;
  }
  else
  {
    PfAssert(last_b4_curr != (ui32)-1);
    Flash->sect_tbl[last_b4_curr].next =
                                    Flash->sect_tbl[last_in_lowest].next;

    /*-----------------------------------------------------------------*/
    /* Update last free sector if selected block is last block in list.*/
    /*-----------------------------------------------------------------*/
    if (last_in_lowest == Flash->last_free_sect)
      Flash->last_free_sect = last_b4_curr;
  }

  /*-------------------------------------------------------------------*/
  /* Mark all of its sectors as dirty.                                 */
  /*-------------------------------------------------------------------*/
  for (i = curr_sect; i <= last_in_lowest; ++i)
  {
    --Flash->free_sects;
    PfAssert(Flash->sect_tbl[i].prev == FFREE_SECT);
    Flash->sect_tbl[i].prev = FDRTY_SECT;
  }

  /*-------------------------------------------------------------------*/
  /* Return first sector in selected block.                            */
  /*-------------------------------------------------------------------*/
  return curr_sect;
}

/***********************************************************************/
/* adjust_set_size: Adjust the erase set size based on control size    */
/*                                                                     */
/*      Inputs: adjust_erase = flag to adjust erase set                */
/*              check_recycle = flag to check recycles                 */
/*                                                                     */
/***********************************************************************/
static void adjust_set_size(int adjust_erase, int check_recycle)
{
  int s1, set_increase = FALSE, b, max_f, f_b, max_b = 0;
  ui32 old_size = Flash->set_blocks, s_optimal, s = 0;
  ui32 max_set_blocks = (Flash->max_set_blocks == 1) ? 1 :
                        Flash->max_set_blocks - 1;
  ui32 ctrl_sects, ctrl_inc;

  /*-------------------------------------------------------------------*/
  /* Compute the control sectors with control increment accounted.     */
  /*-------------------------------------------------------------------*/
  ctrl_inc = (Flash->num_sects - Flash->used_sects - Flash->set_blocks *
              Flash->block_sects - Flash->num_blocks * Flash->hdr_sects +
              Flash->block_sects - 1) / Flash->block_sects +
              Flash->used_sects;
  ctrl_sects = (Flash->ctrl_size + 2 * ctrl_inc + Flash->sect_sz - 1) /
               Flash->sect_sz;

  /*-------------------------------------------------------------------*/
  /* Reset the free_sects_used count.                                  */
  /*-------------------------------------------------------------------*/
  Flash->free_sects_used = 0;

  /*-------------------------------------------------------------------*/
  /* Determine the erase set size.                                     */
  /*-------------------------------------------------------------------*/
  for (Flash->set_blocks = 0; Flash->set_blocks < max_set_blocks; ++s)
  {
    ++Flash->set_blocks;

    /*-----------------------------------------------------------------*/
    /* If size goes up, mark new holder with invalid blocks.           */
    /*-----------------------------------------------------------------*/
    if (s >= old_size)
    {
      Flash->erase_set[s] = -1;
      set_increase = TRUE;
    }

    /*-----------------------------------------------------------------*/
    /* Determine if size is big enough.                                */
    /*-----------------------------------------------------------------*/
    if ((ctrl_sects <= Flash->block_sects * Flash->set_blocks /
                       FLASH_SET_LIMIT ||
         Flash->set_blocks >= Flash->num_blocks / 8) &&
        Flash->set_blocks >= Flash->max_set_blocks / 40)
      break;

⌨️ 快捷键说明

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