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

📄 fdi_recl.c

📁 Flash file system
💻 C
📖 第 1 页 / 共 5 页
字号:

   DWORD spare_unit_offset;             /* offset to spare block unit */
   DWORD reclaim_unit_offset;           /* offset to reclaim block unit */
   union this_block
   {
      WORD physical_block;             /* physical reclaim block number */
      WORD logical_block;              /* logical reclaim block number */
   }  this_blk;
   union bytes
   {
      WORD logical;                    /* logical block loop counter */
      BYTE status;                     /* power off recovery status field */
      WORD physical;                   /* physical block loop counter */
      DWORD actual;                     /* the actual size data read */
      WORD state;                      /* */
   }  block;

#if (DATA_STREAM == TRUE)
   BYTE streaming_in_prog = FALSE;
#endif
   HW_ERROR errors = HW_ERR_NONE;
#if (PACKET_DATA == TRUE)
   WORD  tag_index;
#endif /* PACKET_DATA */

   this_blk.physical_block = 0;
   Rip.recl_in_prog_flag = FALSE;
   MemorySet(Rip.recl_header_mask, 0, HDR_MASK_SIZE);
   Rip.reclaim_block_addr = DWORDMAX;
   Rip.spare_block_addr = DWORDMAX;
   Rip.reclaim_header_offset = FIRST_HEADER_OFFSET;
   Rip.spare_header_offset = FIRST_HEADER_OFFSET;
   Rip.spare_free = 0;
   Rip.spare_dirty = 0;
   RECL_SetState(RECL_DONE);           /* initialize state flag */
   for(;;)                             /* DO FOREVER */
   {
      /* Wait for ReclaimEnable semaphore to become unlocked */
      SEM_WAIT(RECL_Enable);

#ifdef TIMING
      /* Get timestamp for start of update */
      COMM_getTimestamp(&RECL_Start);
#endif
      /*
       * Lock the ReclaimDone semaphore for the background task to know that
       * the reclamation is in progress.
       */
      SEM_TRY_WAIT(RECL_Done);

      RECL_SetState(RECL_ENABLED);     /* state flag */

      /* Determine the reclaim block candidate and determine the spare block */

      least_erased_count = DWORDMAX;   /* initialize the least erased count */
      most_erased_count = 0;           /* initialize the most erased count */
      reclaim.this_count = 0;

      /* assign reclaim_addr to the first data block's first address */
      reclaim_block_addr = FDV_RELATIVE_ADDRESS;
      /* DO FOR each physical block */
      for (block.physical = 0;
           block.physical < FDV_BLOCKCOUNT;
           block.physical++)
      {
         /* IF this block is the spare THEN continue to the next block */
         if (block.physical == FDI_SpareBlock)
         {
            /* increment to the next block */
            reclaim_block_addr += FDV_BLOCK_SIZE;
            continue;
         }
         /* read the erase_count field of BLOCK_INFO for this block */
         errors = FlashDevRead((BYTE_PTR) & block_info,
                               reclaim_block_addr + BOTTOM_OF_UNITS,
                               sizeof(BLOCK_INFO));
         if (errors != HW_ERR_NONE)
         {
            FDI_HandleError(errors);
            break;
         }
         /*
          * IF this block's current status is okay THEN save the block's erase
          * count
          */
         if (block_info.current_state == BLOCK_INTEGRITY)
         {
            /* save the block's erase count */
            reclaim.this_count = block_info.erase_count;
         }
         /* there is a format problem with this block; return error. */
         else
         {
            errors = HW_ERR_READ;
            FDI_HandleError(errors);
            break;
         }                             /* ENDELSE block's totally erased */

         /* IF the block's erase count < least erased block count */
         if (reclaim.this_count < least_erased_count)
         {
            /* assign least erased block count to the block's erase count */
            least_erased_count = reclaim.this_count;

            /* save the physical block number of the least_erased_count */
            this_blk.physical_block = block.physical;
         }                             /* ENDIF < least_erased_count */
         /* IF the block's erase count > most erased block count */
         if (reclaim.this_count > most_erased_count)
         {
            /* assign the most erased block count to the block's erase count */
            most_erased_count = reclaim.this_count;
         }                             /* ENDIF > most_erased_count */
         /* increment to the next block */
         reclaim_block_addr += FDV_BLOCK_SIZE;
      }                                /* ENDDO FOR each block */
      if (errors != HW_ERR_NONE)
         break;

     #if (DATA_STREAM == TRUE) /* wearleveling while data stream is set */

      /* can not take the SEM_OpenStream semaphore without effecting
       * data streaming throughput */
      /* if FDI_OpenParam is in use set the flag true, else false */
      /*If "this_blk.open_flag" is set then that invalidates the "this_blk.physical_block */
      /*this_blk.open_flag = ((FDI_OpenParam.identifier != WORDMAX) &&
                        (FDI_OpenParam.data_streaming == FALSE)) ?
                        TRUE : FALSE;
      */
      /*
       * IF FDI_OpenParam is not in use and the difference between the least
       * erased count and the most erased count is < the wear leveling limit
       */

      if((most_erased_count - least_erased_count ) > WEARLEVELING_LIMIT)
      {
         streaming_in_prog = FALSE;
         for(index =0; index < OPEN_ARRAY_SIZE; index++)
         {
            if ((FDI_OpenParam[index].identifier != WORDMAX) &&
                (FDI_OpenParam[index].data_streaming == FALSE))
            {
               streaming_in_prog = TRUE;
               break;
            }
         }
      }
      if(((most_erased_count - least_erased_count ) > WEARLEVELING_LIMIT) &&
            (streaming_in_prog == FALSE))
      #else /* !DATA_STREAM */

      /*
       * IF the difference between the least erased count and the most erased
       * count is < the wear leveling limit
       */
      if ((most_erased_count - least_erased_count) > WEARLEVELING_LIMIT)

      #endif /* DATA_STREAM */
      {
         /* assign the reclaim block number to be the least erased block */
         RECL_ReclaimBlock = this_blk.physical_block;
         SEM_MTX_WAIT(SEM_BlockTable);     /* wait for block table access */
         for (block.logical = 0; block.logical < MAX_DATA_BLOCKS;
            block.logical++)
         {
            if (FDI_LogicalBlockTable[block.logical].physical_block_number ==
               RECL_ReclaimBlock)
            {
               this_blk.logical_block = block.logical;
               break;
            }
         }
         SEM_MTX_POST(SEM_BlockTable);

#ifdef TEST_MSGS
         logMsg("WEARLEVELING LIMIT REACHED, least %d, most %d, reclaim %d\n",
                (WORD) least_erased_count, (WORD) most_erased_count,
                RECL_ReclaimBlock, 0, 0, 0);
#endif                                 /* TEST_MSGS */
      }
      /* ELSE did not meet the WEARLEVELING_LIMIT value */
      else
      {
         /* initialize the dirtiest block count to ZERO */
         reclaim.this_count = 0;
         this_blk.logical_block = 0;
         SEM_MTX_WAIT(SEM_BlockTable); /* wait for block table access */
         RECL_ReclaimBlock = FDI_LogicalBlockTable[0].physical_block_number;

         /* DO FOR each block in logical block table */
         for (block.logical = 0; block.logical < MAX_DATA_BLOCKS;
              block.logical++)
         {
            /*
             * read the dirty space field in the logical block table IF the
             * dirty space > the dirtiest block count THEN assign the dirtiest
             * count to the block's dirty_space and assign the
             * RECL_ReclaimBlock to the physical block number
             */
#if (DATA_STREAM == TRUE)
            if ((FDI_LogicalBlockTable[block.logical].dirty_space != 0) &&
                (reclaim.this_count <
                 FDI_LogicalBlockTable[block.logical].dirty_space))
            {
               reclaim.this_count =
                FDI_LogicalBlockTable[block.logical].dirty_space;
               RECL_ReclaimBlock =
                FDI_LogicalBlockTable[block.logical].physical_block_number;

               /* save the reclaim block's logical block number */
               this_blk.logical_block = block.logical;
            }                          /* ENDIF count > dirty_space */
#else
            if ((FDI_LogicalBlockTable[block.logical].dirty_space != 0) &&
                (reclaim.this_count <
                 (FDI_LogicalBlockTable[block.logical].dirty_space +
                  FDI_LogicalBlockTable[block.logical].free_space)))
            {
               reclaim.this_count =
                FDI_LogicalBlockTable[block.logical].free_space +
                FDI_LogicalBlockTable[block.logical].dirty_space;
               RECL_ReclaimBlock =
                FDI_LogicalBlockTable[block.logical].physical_block_number;

               /* save the reclaim block's logical block number */
               this_blk.logical_block = block.logical;
            }                          /* ENDIF count > dirty_space */
#endif
         }                             /* ENDDO FOR each logical block */
         SEM_MTX_POST(SEM_BlockTable); /* finished with block table access */
      }                                /* #ENDIF WEARLEVELING not enabled */
      /*
       * We now have the first addresses of the reclaim block and the spare
       * block
       */
      /* Check to make sure a reclaim really needs to occur. If not, state */
      /* reclaim done and return */
      if (((most_erased_count - least_erased_count) < WEARLEVELING_LIMIT) &&
          (reclaim.this_count == 0))
      {
#ifdef TEST_MSGS
         logMsg("reclaim done, Nothing to reclaim\n", 0, 0, 0, 0, 0, 0);
#endif
         RECL_ReclaimBlock = WORDMAX;
         RECL_SetState(RECL_DONE);
         SEM_POST(RECL_Done);
         continue;
      }


      SEM_MTX_WAIT(SEM_ReclaimInProg); /* Take the ReclaimInProg semaphore */
      /* assign reclaim_addr the first address of the RECL_ReclaimBlock */
      Rip.reclaim_block_addr = BLOCK_ADDRESS(RECL_ReclaimBlock);

      /* assign spare_addr the first address of the FDI_SpareBlock */
      Rip.spare_block_addr = BLOCK_ADDRESS(FDI_SpareBlock);
      RECL_SetState(RECL_BLK_FOUND);   /* state flag */


      /* write the spare block's block information status field to 'recover' */
      block.status = BLK_RECOVER;      /* set the status to 'recover' */
      errors = FlashDevWrite(&block.status,
                             Rip.spare_block_addr + BOTTOM_OF_UNITS +
                             offsetof(BLOCK_INFO, status),
                             mFDI_MemberSize(BLOCK_INFO, status));
      if (errors != HW_ERR_NONE)
      {
         FDI_HandleError(errors/* | 0x30030000 */);
         break;
      }
      RECL_SetState(RECL_RECOVERING);  /* state flag */

      /* Write BLOCK_INTEGRITY word to the last address in the spare block */

      /* write the spare block's block information current_state field */
      block.state = BLOCK_INTEGRITY;   /* set the current_state */
      errors = FlashDevWrite((BYTE_PTR) & block.state,
                             Rip.spare_block_addr + BOTTOM_OF_UNITS +
                             offsetof(BLOCK_INFO, current_state),
                             mFDI_MemberSize(BLOCK_INFO, current_state));
      if (errors != HW_ERR_NONE)
      {
         FDI_HandleError(errors/* | 0x30040000 */);
         break;
      }
      /*
       * Read the erase count from the parameter system and write this to the
       * spare block's erase count field in BLOCK_INFO
       */
      /*
       * read the erase_count of the spare block as data identifier
       * NUM_IDENTIFIERS, increment the erase_count and then write into the
       * block information structure.
       */
      errors = ReadModify((BYTE_PTR) & reclaim.this_count,
               (DWORD_PTR)&block.actual, 0, sizeof(DWORD), ERASE_COUNT_ID,
               ERASE_COUNT_TYPE, 1, READ_DATA);
      if (errors != HW_ERR_NONE)
      {
         FDI_HandleError(errors/* | 0x30050000 */);
         break;
      }

      errors = FlashDevWrite((BYTE_PTR) & reclaim.this_count,
                             Rip.spare_block_addr + BOTTOM_OF_UNITS +
                             offsetof(BLOCK_INFO, erase_count),
                             mFDI_MemberSize(BLOCK_INFO, erase_count));
      if (errors != HW_ERR_NONE)
      {
         FDI_HandleError(errors/* | 0x30060000 */);
         break;
      }
      /*
       * initialize spare_free to sizeof the block minus the size of the block
       * information structure
       */
      Rip.spare_free = ((BOTTOM_OF_UNITS - sizeof(UNIT_HEADER)) -
         FIRST_HEADER_OFFSET);
      Rip.spare_dirty = 0;
      /* reset the recl_header_mask to zeros */
      MemorySet(Rip.recl_header_mask, 0, HDR_MASK_SIZE);
      /* initialize spare_header_offset and reclaim_header_offset to zero */
      Rip.reclaim_header_offset = FIRST_HEADER_OFFSET;
      Rip.spare_header_offset = FIRST_HEADER_OFFSET;
      reclaim_unit_offset = 0;
      /*
       * initialize spare_unit_offset to block size - sizeof the block
       * information structure
       */
      spare_unit_offset = BOTTOM_OF_UNITS;
      /*
       * Scan through each unit header in the reclaim block and transfer only
       * the valid headers and units to the spare block
       */
      Rip.recl_in_prog_flag = TRUE;
      /*
       * DO WHILE there are unit headers to read, copy only valid headers from
       * the reclaim block to the spare
       */

#if (PACKET_DATA == TRUE)
      tag_index = WORDMAX;  /* initialization */
#endif /* PACKET_DATA */

⌨️ 快捷键说明

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