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

📄 nand_util.c

📁 ATMEL单片机可用的文件系统源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
        crc = CRC_UPDATE(crc, Flash->tmp_sect[j - 2]);
        crc = CRC_UPDATE(crc, Flash->tmp_sect[j - 1]);
      }
      else
        while (j < Flash->sect_sz)
        {
          Flash->tmp_sect[j++] = 0xFF;
          crc = CRC_UPDATE(crc, 0xFF);
        }
      PfAssert(j == Flash->sect_sz);
      rc = FlashWriteCtrlSect();
      if (rc)
        return rc;
      offset = 0;
      Flash->ctrl_sect = Flash->sect_tbl[Flash->ctrl_sect].next;
    }

    /*-----------------------------------------------------------------*/
    /* Pad the rest of the last sector with 0xFFs, except for CRC.     */
    /*-----------------------------------------------------------------*/
    PfAssert(offset < Flash->sect_sz - 4);
    for (i = offset; i < Flash->sect_sz - 4; ++i)
    {
      Flash->tmp_sect[i] = 0xFF;
      crc = CRC_UPDATE(crc, 0xFF);
    }

    /*-----------------------------------------------------------------*/
    /* Write the CRC.                                                  */
    /*-----------------------------------------------------------------*/
    for (j = 0, crc = ~crc; j < 4; ++j)
      Flash->tmp_sect[i + j] = (ui8)(crc >> (8 * j));

    /*-----------------------------------------------------------------*/
    /* Write the buffered sector to flash.                             */
    /*-----------------------------------------------------------------*/
    rc = FlashWriteCtrlSect();
    if (rc)
      return rc;
  }

  return 0;
}

/***********************************************************************/
/* FsNandEraseBlockWrapper: Wrapper function for the NAND driver erase */
/*              block                                                  */
/*                                                                     */
/*       Input: addr = address within block to be erased               */
/*                                                                     */
/*     Returns: 0 on success, -1 on failure                            */
/*                                                                     */
/***********************************************************************/
int FsNandEraseBlockWrapper(ui32 addr)
{
  int status;
  FlashGlob *vol;

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

  /*-------------------------------------------------------------------*/
  /* Erase block.                                                      */
  /*-------------------------------------------------------------------*/
  status = vol->driver.nand.erase_block(addr, vol->vol);

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

  /*-------------------------------------------------------------------*/
  /* If the block erase fails, it's an invalid block.                  */
  /*-------------------------------------------------------------------*/
  if (status)
  {
    ui32 i, sect, first_invalid, last_invalid = (ui32)-1;
    ui32 block = (addr - Flash->mem_base) / Flash->block_size;
#if FFS_DEBUG
printf("NAND: erase block %u failure!\n", block);
#endif

    /*-----------------------------------------------------------------*/
    /* Increment the total number of bad blocks.                       */
    /*-----------------------------------------------------------------*/
    ++Flash->bad_blocks;

    /*-----------------------------------------------------------------*/
    /* Mark block as bad.                                              */
    /*-----------------------------------------------------------------*/
    PfAssert(!Flash->blocks[block].ctrl_block);
    Flash->blocks[block].bad_block = TRUE;

    /*-----------------------------------------------------------------*/
    /* Mark all sectors in block as invalid.                           */
    /*-----------------------------------------------------------------*/
    sect = block * Flash->block_sects;
    if (Flash->sect_tbl[sect].prev == FFREE_SECT)
    {
      first_invalid = sect;
      last_invalid = first_invalid + Flash->block_sects - 1;
      Flash->free_sects -= Flash->block_sects;
      PfAssert(Flash->sect_tbl[last_invalid].prev == FFREE_SECT);
    }
    else
      first_invalid = (ui32)-1;

    for (i = 0; i < Flash->block_sects; ++i, ++sect)
      Flash->sect_tbl[sect].prev = FNVLD_SECT;

    if (first_invalid != (ui32)-1)
    {
      /*---------------------------------------------------------------*/
      /* Find the sector in free list that points to first invalid     */
      /* sector (if there is one, it is at end of a block).            */
      /*---------------------------------------------------------------*/
      sect = Flash->block_sects - 1;
      for (block = 0; block < Flash->num_blocks; ++block)
      {
        if (!Flash->blocks[block].bad_block)
        {
          if (Flash->sect_tbl[sect].prev == FFREE_SECT &&
              Flash->sect_tbl[sect].next == first_invalid)
          {
            Flash->sect_tbl[sect].next =
                                      Flash->sect_tbl[last_invalid].next;
            if (Flash->sect_tbl[sect].next == FLAST_SECT)
              Flash->last_free_sect = sect;
            break;
          }
        }
        sect += Flash->block_sects;
      }
    }
  }

  /*-------------------------------------------------------------------*/
  /* If number of bad blocks has exceeded maximum, error.              */
  /*-------------------------------------------------------------------*/
  if (Flash->bad_blocks > Flash->max_bad_blocks)
    return -1;

  return 0;
}

/***********************************************************************/
/* FsNandUnformatToFormat: NAND specific code to prepare unformatted   */
/*              volume for format                                      */
/*                                                                     */
/*     Returns: 0 on success, -1 on error                              */
/*                                                                     */
/***********************************************************************/
int FsNandUnformatToFormat(void)
{
  int sect, block, i;

  Flash->bad_blocks = 0;
  Flash->free_sect = (ui32)-1;
  Flash->free_sects = 0;
  Flash->last_free_sect = (ui32)-1;

  /*-------------------------------------------------------------------*/
  /* Look for bad vs. free blocks.                                     */
  /*-------------------------------------------------------------------*/
  for (block = 0; block < Flash->num_blocks; ++block)
  {
    Flash->blocks[block].used_sects = 0;
    Flash->blocks[block].ctrl_block = FALSE;
    Flash->blocks[block].wear_count = 0;

    sect = (int)(block * Flash->block_sects);
    for (i = 0; i < Flash->block_sects; ++i, ++sect)
    {
      /*---------------------------------------------------------------*/
      /* If a sector is non-empty at this stage, its block is bad.     */
      /*---------------------------------------------------------------*/
      if (Flash->max_bad_blocks && !FsNandEmptySect(sect))
      {
        Flash->blocks[block].bad_block = TRUE;
        ++Flash->bad_blocks;

        /*-------------------------------------------------------------*/
        /* Mark all sectors in block as invalid.                       */
        /*-------------------------------------------------------------*/
        sect = (int)(block * Flash->block_sects);
        for (i = 0; i < Flash->block_sects; ++i, ++sect)
          Flash->sect_tbl[sect].prev = FNVLD_SECT;
        sect = -1;
        break;
      }

      /*---------------------------------------------------------------*/
      /* Mark sector as free.                                          */
      /*---------------------------------------------------------------*/
      Flash->sect_tbl[sect].prev = FFREE_SECT;
      Flash->sect_tbl[sect].next = (ui16)(sect + 1);
    }

    /*-----------------------------------------------------------------*/
    /* If block is free, tie it in with the free list.                 */
    /*-----------------------------------------------------------------*/
    if (sect != -1)
    {
      Flash->free_sects += Flash->block_sects;
      if (Flash->free_sect == (ui32)-1)
        Flash->free_sect = block * Flash->block_sects;
      else
        Flash->sect_tbl[Flash->last_free_sect].next =
                                      (ui16)(block * Flash->block_sects);
      Flash->last_free_sect = (ui32)(sect - 1);
      Flash->sect_tbl[Flash->last_free_sect].next = FLAST_SECT;
      Flash->blocks[block].bad_block = FALSE;
    }
  }
  return 0;
}

/***********************************************************************/
/* FsNandAddVol: Add NAND volume                                       */
/*                                                                     */
/*       Input: driver = pointer to the driver control block           */
/*                                                                     */
/*     Returns: 0 on success, -1 on error                              */
/*                                                                     */
/***********************************************************************/
int FsNandAddVol(const FfsVol *driver)
{
  return FlashAddVol(driver, FFS_NAND);
}

/***********************************************************************/
/* FsNandFindLastCtrl: Look for most recent control information        */
/*                                                                     */
/*     Returns: First sector of most recent control information or -1  */
/*              if no control information was found                    */
/*                                                                     */
/***********************************************************************/
int FsNandFindLastCtrl(void)
{
  int  beg_ctrl_sect = -1, ctrl_start;
  ui32 high_seq_num = 0, seq_num, sect;

  /*-------------------------------------------------------------------*/
  /* Scan the whole flash for valid ctrl info. Remember the one with   */
  /* latest sequence number.                                           */
  /*-------------------------------------------------------------------*/
  for (sect = 0;;)
  {
    /*-----------------------------------------------------------------*/
    /* Find the next valid copy of control information in flash.       */
    /*-----------------------------------------------------------------*/
    ctrl_start = next_ctrl(&sect, &seq_num);

    /*-----------------------------------------------------------------*/
    /* If no more valid ctr info found, break.                         */
    /*-----------------------------------------------------------------*/
    if (ctrl_start == -1)
      break;

    /*-----------------------------------------------------------------*/
    /* If this is first valid ctrl info, or it's more recent than the  */
    /* saved one, remember it as the most recent one.                  */
    /*-----------------------------------------------------------------*/
    if ((beg_ctrl_sect == -1) || SEQ_GT(seq_num, high_seq_num))
    {
      beg_ctrl_sect = ctrl_start;
      high_seq_num = seq_num;
#if FFS_DEBUG
      printf("high_seq_num = 0x%08X\n", high_seq_num);
#endif
    }
  }

  /*-------------------------------------------------------------------*/
  /* Return beginning ctrl sect or -1 if ctrl info not present.        */
  /*-------------------------------------------------------------------*/
  return beg_ctrl_sect;
}

/***********************************************************************/
/* FsNandEmptySect: Check if a flash sector is empty                   */
/*                                                                     */
/*       Input: sector = sector to check                               */
/*                                                                     */
/*     Returns: TRUE if empty, FALSE otherwise                         */
/*                                                                     */
/***********************************************************************/
int FsNandEmptySect(ui32 sector)
{
  ui32 i, addr = Flash->mem_base + Flash->sect_sz * sector;

  /*-------------------------------------------------------------------*/
  /* Loop to check each page in the sector.                            */
  /*-------------------------------------------------------------------*/
  for (i = 0; i < Flash->pages_per_sect; ++i, addr += Flash->page_size)
  {
    /*-----------------------------------------------------------------*/
    /* If read fails, sector is considered not empty.                  */
    /*-----------------------------------------------------------------*/
    if (!Flash->driver.nand.page_erased(addr, Flash->vol))
      return FALSE;
  }
  return TRUE;
}
#endif /* INC_NAND_FS && NUM_FFS_VOLS */

⌨️ 快捷键说明

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