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

📄 nand_if.c

📁 STM32实现读卡器功能,适用于STM32E-EVAL开发板
💻 C
📖 第 1 页 / 共 2 页
字号:
             }
             LUT [ MAX_LOG_BLOCKS_PER_ZONE + WEAR_DEPTH - 1] = LUT_Item ;
#endif

  return NAND_OK;
}

/*******************************************************************************
* Function Name  : NAND_GetAddress
* Description    : Translate logical address into a phy one
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
static NAND_ADDRESS NAND_GetAddress (u32 Address)
{
  NAND_ADDRESS Address_t;

  Address_t.Page  = Address & (NAND_BLOCK_SIZE - 1);
  Address_t.Block = Address / NAND_BLOCK_SIZE;
  Address_t.Zone = 0;

  while (Address_t.Block >= MAX_LOG_BLOCKS_PER_ZONE)
  {
    Address_t.Block -= MAX_LOG_BLOCKS_PER_ZONE;
    Address_t.Zone++;
  }
  return Address_t;
}

/*******************************************************************************
* Function Name  : NAND_GetFreeBlock
* Description    : Look for a free block for data exchange
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
static u16 NAND_GetFreeBlock (void)
{
  return LUT[MAX_LOG_BLOCKS_PER_ZONE]& ~(USED_BLOCK | VALID_BLOCK);
}

/*******************************************************************************
* Function Name  : ReadSpareArea
* Description    : Check used block
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
SPARE_AREA ReadSpareArea (u32 address)
{
  SPARE_AREA t;
  u8 Buffer[16];
  NAND_ADDRESS address_s;
  address_s = NAND_ConvertPhyAddress(address);
  FSMC_NAND_ReadSpareArea(Buffer , address_s, 1) ;

  t = *(SPARE_AREA *)Buffer;

  return t;
}

/*******************************************************************************
* Function Name  : NAND_Copy
* Description    : Copy page
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
static u16 NAND_Copy (NAND_ADDRESS Address_Src, NAND_ADDRESS Address_Dest, u16 PageToCopy)
{
  u8 Copybuff[512];
  for ( ; PageToCopy > 0 ; PageToCopy-- )
  {
    FSMC_NAND_ReadSmallPage  ((u8 *)Copybuff, Address_Src , 1 );
    FSMC_NAND_WriteSmallPage ((u8 *)Copybuff, Address_Dest, 1);
    FSMC_NAND_AddressIncrement(&Address_Src);
    FSMC_NAND_AddressIncrement(&Address_Dest);
  }

  return NAND_OK;
}

/*******************************************************************************
* Function Name  : NAND_Format
* Description    : Format the entire NAND flash
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
u16 NAND_Format (void)
{
  NAND_ADDRESS phAddress;
  SPARE_AREA  SpareArea;
  u32 BlockIndex;

  for (BlockIndex = 0 ; BlockIndex < NAND_ZONE_SIZE * NAND_MAX_ZONE; BlockIndex++)
  {
    phAddress = NAND_ConvertPhyAddress(BlockIndex * NAND_BLOCK_SIZE );
    SpareArea = ReadSpareArea(BlockIndex * NAND_BLOCK_SIZE);
   
    if((SpareArea.DataStatus != 0)||(SpareArea.BlockStatus != 0)){
        FSMC_NAND_EraseBlock (phAddress);
    }  
  }
  NAND_BuildLUT(0);
  return NAND_OK;
}

/*******************************************************************************
* Function Name  : NAND_Write_Cleanup
* Description    : None
* Input          : None
* Output         : None
* Return         : Status
*******************************************************************************/
static u16 NAND_Write_Cleanup (void)
{
  u16  tempSpareArea [8];
  u16  Page_Back;

  if ( Block_State == OLD_BLOCK )
  {
    /* precopy old first pages */
    if (Initial_Page != 0)
    {
      Page_Back = wAddress.Page;
      fAddress.Page = wAddress.Page = 0;
      NAND_Copy (wAddress, fAddress, Initial_Page);
      wAddress.Page =  Page_Back ;
    }

    /* postcopy remaining pages */
    if ((NAND_BLOCK_SIZE - (wAddress.Page + 1)) != 0)
    {
      FSMC_NAND_AddressIncrement(&wAddress);
      fAddress.Page = wAddress.Page;
      NAND_Copy (wAddress, fAddress, NAND_BLOCK_SIZE - wAddress.Page);
    }

    /* assign logical address to new block */
    tempSpareArea [0] = LogAddress | USED_BLOCK ;
    tempSpareArea [1] = 0xFFFF;
    tempSpareArea [2] = 0xFFFF;

    fAddress.Page     = 0x00;
    FSMC_NAND_WriteSpareArea( (u8 *)tempSpareArea , fAddress , 1);

    /* erase old block */
    FSMC_NAND_EraseBlock(wAddress);
    NAND_CleanLUT(wAddress.Zone);
  }
  else
  {/* unused block case */
    /* assign logical address to the new used block */
    tempSpareArea [0] = LogAddress | USED_BLOCK ;
    tempSpareArea [1] = 0xFFFF;
    tempSpareArea [2] = 0xFFFF;

    wAddress.Page     = 0x00;
    FSMC_NAND_WriteSpareArea((u8 *)tempSpareArea , wAddress, 1);
    NAND_CleanLUT(wAddress.Zone);
  }
  return NAND_OK;
}

/*******************************************************************************
* Function Name  : NAND_ConvertPhyAddress
* Description    : None
* Input          : physical Address
* Output         : None
* Return         : Status
*******************************************************************************/
static NAND_ADDRESS NAND_ConvertPhyAddress (u32 Address)
{
  NAND_ADDRESS Address_t;

  Address_t.Page  = Address & (NAND_BLOCK_SIZE - 1);
  Address_t.Block = Address / NAND_BLOCK_SIZE;
  Address_t.Zone = 0;

  while (Address_t.Block >= MAX_PHY_BLOCKS_PER_ZONE)
  {
    Address_t.Block -= MAX_PHY_BLOCKS_PER_ZONE;
    Address_t.Zone++;
  }
  return Address_t;
}

/*******************************************************************************
* Function Name  : NAND_BuildLUT
* Description    : Build the look up table
* Input          : None
* Output         : None
* Return         : Status
* !!!! NOTE : THIS ALGORITHM IS A SUBJECT OF PATENT FOR STMICROELECTRONICS !!!!!
*******************************************************************************/
static u16 NAND_BuildLUT (u8 ZoneNbr)
{

  u16  pBadBlock, pCurrentBlock, pFreeBlock;
  SPARE_AREA  SpareArea;
  /*****************************************************************************
                                  1st step : Init.
  *****************************************************************************/
  /*Init the LUT (assume all blocks free) */
  for (pCurrentBlock = 0 ; pCurrentBlock < MAX_PHY_BLOCKS_PER_ZONE ; pCurrentBlock++)
  {
    LUT[pCurrentBlock] = FREE_BLOCK;  /* 12th bit is set to 1 */
  }

  /* Init Pointers */
  pBadBlock    = MAX_PHY_BLOCKS_PER_ZONE - 1;
  pCurrentBlock = 0;

  /*****************************************************************************
                         2nd step : locate used and bad blocks
  *****************************************************************************/

  while (pCurrentBlock < MAX_PHY_BLOCKS_PER_ZONE)
  {

    SpareArea = ReadSpareArea(pCurrentBlock * NAND_BLOCK_SIZE + (ZoneNbr * NAND_BLOCK_SIZE * MAX_PHY_BLOCKS_PER_ZONE));

    if ((SpareArea.DataStatus == 0) || (SpareArea.BlockStatus == 0))
    {

      LUT[pBadBlock--]    |= pCurrentBlock | (u16)BAD_BLOCK ;
      LUT[pCurrentBlock] &= (u16)~FREE_BLOCK;
      if (pBadBlock == MAX_LOG_BLOCKS_PER_ZONE)
      {
        return NAND_FAIL;
      }
    }
    else if (SpareArea.LogicalIndex != 0xFFFF)
    {

      LUT[SpareArea.LogicalIndex & 0x3FF] |= pCurrentBlock | VALID_BLOCK | USED_BLOCK;
      LUT[pCurrentBlock] &= (u16)( ~FREE_BLOCK);
    }
    pCurrentBlock++ ;
  }

  /*****************************************************************************
     3rd step : locate Free Blocks by scanning the LUT already built partially
  *****************************************************************************/
  pFreeBlock = 0;
  for (pCurrentBlock = 0 ; pCurrentBlock < MAX_PHY_BLOCKS_PER_ZONE ; pCurrentBlock++ )
  {

    if ( !(LUT[pCurrentBlock]& USED_BLOCK))
    {
      do
      {
        if (LUT[pFreeBlock] & FREE_BLOCK)
        {

          LUT [pCurrentBlock] |= pFreeBlock;
          LUT [pFreeBlock]   &= ~FREE_BLOCK;
          break;
        }
        pFreeBlock++;
      }
      while ( pFreeBlock < MAX_PHY_BLOCKS_PER_ZONE );
    }
  }
  return NAND_OK;
}
#endif

/******************* (C) COPYRIGHT 2008 STMicroelectronics *****END OF FILE****/

⌨️ 快捷键说明

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