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

📄 nand_util.c

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

/***********************************************************************/
/* invalidate_ctrl_sects_upto: Invalidate all control sectors from     */
/*              beginning upto bad sector                              */
/*                                                                     */
/*       Input: bad_sect = sector to stop at                           */
/*                                                                     */
/*     Returns: First sector in next control block past bad one,       */
/*              FLAST_SECT if no such block                            */
/*                                                                     */
/***********************************************************************/
static ui32 invalidate_ctrl_sects_upto(ui32 bad_sect)
{
  ui32 sect, bad_block = bad_sect / Flash->block_sects;

  /*-------------------------------------------------------------------*/
  /* Mark all sectors from begining to bad sector as dirty.            */
  /*-------------------------------------------------------------------*/
  sect = Flash->frst_ctrl_sect;
  for (;;)
  {
    Flash->sect_tbl[sect].prev = FDRTY_SECT;
    Flash->blocks[sect / Flash->block_sects].ctrl_block = FALSE;

    /*-----------------------------------------------------------------*/
    /* If we've reached the bad sector, stop.                          */
    /*-----------------------------------------------------------------*/
    if (sect == bad_sect)
      break;

    sect = Flash->sect_tbl[sect].next;
    PfAssert(sect != FLAST_SECT);
  }

  /*-------------------------------------------------------------------*/
  /* Get first control sector in next block past bad one.              */
  /*-------------------------------------------------------------------*/
  while (sect != FLAST_SECT && sect / Flash->block_sects == bad_block)
    sect = Flash->sect_tbl[sect].next;

  return sect;
}

/***********************************************************************/
/* update_erase_set: Look for a block in erasable set, and if found,   */
/*              take it out and replace it with another one            */
/*                                                                     */
/*       Input: block = bad block to take out of erasable set          */
/*                                                                     */
/***********************************************************************/
static void update_erase_set(ui32 block)
{
  int s, best_block = -1, f_best_block = -1, f, b, i;

  /*-------------------------------------------------------------------*/
  /* Look for block in erasable set.                                   */
  /*-------------------------------------------------------------------*/
  for (s = 0; s < Flash->set_blocks; ++s)
  {
    /*-----------------------------------------------------------------*/
    /* If block in erasable set, take it out.                          */
    /*-----------------------------------------------------------------*/
    if (Flash->erase_set[s] == block)
    {
      for (b = 0; b < Flash->num_blocks; ++b)
        if (!Flash->blocks[b].bad_block && !Flash->blocks[b].ctrl_block
            && Flash->sect_tbl[(b + 1) * Flash->block_sects - 1].prev !=
               FFREE_SECT)
        {
          /*-----------------------------------------------------------*/
          /* Check if block is in erasable set already.                */
          /*-----------------------------------------------------------*/
          for (i = 0; i < Flash->set_blocks; ++i)
            if (Flash->erase_set[i] == b)
              break;

          /*-----------------------------------------------------------*/
          /* If block not in erase set see if it is a good candidate.  */
          /* When computing the selector function, ignore wear count.  */
          /*-----------------------------------------------------------*/
          if (i == Flash->set_blocks)
          {
            f = (int)(16 * (Flash->block_sects -
                      Flash->blocks[b].used_sects) +
                      (Flash->high_wear - Flash->blocks[b].wear_count));
            if (best_block == -1 || f_best_block < f)
            {
              best_block = b;
              f_best_block = f;
            }
          }
        }

      /*---------------------------------------------------------------*/
      /* If a replacement block found, use it.                         */
      /*---------------------------------------------------------------*/
      if (best_block != -1)
        Flash->erase_set[s] = best_block;

      /*---------------------------------------------------------------*/
      /* Else the flash contains only free/bad blocks. Remove bad block*/
      /* from erase set and replace it with the block containing the   */
      /* first free sector.                                            */
      /*---------------------------------------------------------------*/
      else
        Flash->erase_set[s] = (int)(Flash->free_sect/Flash->block_sects);
    }
  }
}

/***********************************************************************/
/* mark_block_bad: On a write sector failure, invalidate whole block   */
/*                                                                     */
/*       Input: block = block to be marked bad                         */
/*                                                                     */
/*     Returns: 0 on success, -1 on error                              */
/*                                                                     */
/***********************************************************************/
static int mark_block_bad(ui32 block)
{
  ui32 sect, i;

  /*-------------------------------------------------------------------*/
  /* Mark block as bad.                                                */
  /*-------------------------------------------------------------------*/
  Flash->blocks[block].bad_block = TRUE;
  ++Flash->bad_blocks;
  Flash->blocks[block].ctrl_block = FALSE;

  /*-------------------------------------------------------------------*/
  /* Remove any free sectors from bad block and mark all non-data      */
  /* sectors as invalid.                                               */
  /*-------------------------------------------------------------------*/
  sect = block * Flash->block_sects;
  for (i = 0; i++ < Flash->block_sects; ++sect)
  {
    if (Flash->sect_tbl[sect].prev == FFREE_SECT)
    {
      if (Flash->free_sect != Flash->last_free_sect)
      {
        --Flash->free_sects;
        Flash->free_sect = Flash->sect_tbl[sect].next;
        Flash->sect_tbl[sect].prev = FNVLD_SECT;
      }
      else
      {
        PfAssert(FALSE); /*lint !e506, !e774*/
        return -1;
      }
    }
    else if (Flash->sect_tbl[sect].prev == FDRTY_SECT)
      Flash->sect_tbl[sect].prev = FNVLD_SECT;
  }

  /*-------------------------------------------------------------------*/
  /* Update erasable set if bad block is in there.                     */
  /*-------------------------------------------------------------------*/
  update_erase_set(block);

  /*-------------------------------------------------------------------*/
  /* If bad blocks exceeded maximum, error.                            */
  /*-------------------------------------------------------------------*/
  if (Flash->bad_blocks > Flash->max_bad_blocks)
  {
    set_errno(EIO);
    return -1;
  }
  return 0;
}

/***********************************************************************/
/* free_ctrl_blocks_from: Free all control blocks from current sector  */
/*                                                                     */
/*       Input: sect = sector to start at                              */
/*                                                                     */
/***********************************************************************/
static void free_ctrl_blocks_from(ui32 sect)
{
  ui32 next_sect, one_past_last_ctrl_sect = FLAST_SECT;

  while (sect != FLAST_SECT)
  {
    next_sect = Flash->sect_tbl[sect].next;

    /*-----------------------------------------------------------------*/
    /* Mark sector as free.                                            */
    /*-----------------------------------------------------------------*/
    Flash->sect_tbl[sect].prev = FFREE_SECT;
    ++Flash->free_sects;
    Flash->blocks[sect / Flash->block_sects].ctrl_block = FALSE;

    /*-----------------------------------------------------------------*/
    /* If at end of block, add whole block to free list.               */
    /*-----------------------------------------------------------------*/
    if (sect % Flash->block_sects == Flash->block_sects - 1)
    {
      Flash->sect_tbl[Flash->last_free_sect].next =
                                   (ui16)(sect - Flash->block_sects + 1);
      Flash->sect_tbl[sect].next = FLAST_SECT;
      Flash->last_free_sect = sect;
      one_past_last_ctrl_sect = FLAST_SECT;
    }
    else
    {
      Flash->sect_tbl[sect].next = (ui16)(sect + 1);
      one_past_last_ctrl_sect = sect + 1;
    }
    sect = next_sect;
  }

  /*-------------------------------------------------------------------*/
  /* If there are sectors left in last control block, mark them free.  */
  /*-------------------------------------------------------------------*/
  if (one_past_last_ctrl_sect != FLAST_SECT)
    for (sect = one_past_last_ctrl_sect;; ++sect)
    {
      /*---------------------------------------------------------------*/
      /* Mark sector as free.                                          */
      /*---------------------------------------------------------------*/
      Flash->sect_tbl[sect].prev = FFREE_SECT;
      ++Flash->free_sects;

      /*---------------------------------------------------------------*/
      /* If at end of block, add whole block to free list.             */
      /*---------------------------------------------------------------*/
      if (sect % Flash->block_sects == Flash->block_sects - 1)
      {
        Flash->sect_tbl[Flash->last_free_sect].next =
                                   (ui16)(sect - Flash->block_sects + 1);
        Flash->sect_tbl[sect].next = FLAST_SECT;
        Flash->last_free_sect = sect;
        return;
      }
      else
        Flash->sect_tbl[sect].next = (ui16)(sect + 1);
    }
}

/***********************************************************************/
/* Global Function Definitions                                         */
/***********************************************************************/

/***********************************************************************/
/* FsNandReadSect: Read a sector from the volume                       */
/*                                                                     */
/*      Inputs: buffer = buffer to place sector data into              */
/*              sect_num = sector to be read                           */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure                            */
/*                                                                     */
/***********************************************************************/
int FsNandReadSect(void *buffer, ui32 sect_num)
{
  int i, rc = 0;
  ui32 addr = Flash->mem_base + Flash->sect_sz * sect_num;
  ui32 wear = Flash->blocks[sect_num / Flash->block_sects].wear_count;

  /*-------------------------------------------------------------------*/
  /* Read in a page at a time.                                         */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
  {
    rc |= Flash->driver.nand.read_page(buffer, addr, wear, Flash->vol);
    buffer = (void *)((ui32)buffer + Flash->page_size);
  }

  return rc;
}

/***********************************************************************/
/* FsNandWriteType: Attempt to invalidate control sectors              */
/*                                                                     */
/*      Inputs: sect_num = control sector to be invalidated            */
/*              type = sector type to be written for this sector       */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure, RWR_CTRL_OK if control    */
/*              was rewritten succesfully                              */
/*                                                                     */
/***********************************************************************/
int FsNandWriteType(ui32 sect_num, ui32 type)
{
  ui32 addr = Flash->mem_base + sect_num * Flash->sect_sz, bad_block;
  ui32 frst_ctrl_sect, j, i;
  FlashGlob *vol;
  int status;

  /*-------------------------------------------------------------------*/
  /* Write sector type a page at a time.                               */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
  {
    /*-----------------------------------------------------------------*/
    /* Release exclusive access to the flash file system.              */
    /*-----------------------------------------------------------------*/
    vol = Flash;
    semPost(FlashSem);

    /*-----------------------------------------------------------------*/
    /* Write the type.                                                 */
    /*-----------------------------------------------------------------*/
    status = vol->driver.nand.write_type(addr, type, vol->vol);

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

    /*-----------------------------------------------------------------*/
    /* If chip error, mark whole block as bad.                         */

⌨️ 快捷键说明

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