fdi_recl.c

来自「FDI Intel开发的FLASH文件系统,功能很强大」· C语言 代码 · 共 1,700 行 · 第 1/5 页

C
1,700
字号
      SEM_DESTROY(RECL_Enable);
      SEM_DESTROY(RECL_Done);
/* E.5.5.5.987 Begin */
#endif /* SEM_CREATE_DESTROY */
/* E.5.5.5.987 End */
      status = HW_ERR_PARAM;
   }
/* E.5.5.5.987 Begin */
/* E.5.5.5.987 End */

/*E.5.0.602.START*/
#if(TASK_CREATE_DESTROY == TRUE)
   /* spawn the reclamation task */
   else if ((RECL_TaskId = SPAWN("tFDIreclm", RECL_PRIORITY, TASK_OPTIONS,
      RECL_STACK_SIZE, RECL_Task)) == SPAWN_ERROR)
   {
   
#if(SEM_CREATE_DESTROY == TRUE)
      SEM_DESTROY(RECL_Request);
      SEM_DESTROY(RECL_Enable);
      SEM_DESTROY(RECL_Done);
/* E.5.5.5.987 Begin */
#endif /* SEM_CREATE_DESTROY */
/* E.5.5.5.987 End */
      SEM_MTX_DESTROY(SEM_ReclaimInProg);
/* E.5.5.5.987 Begin */
/* E.5.5.5.987 End */
      status = HW_ERR_PARAM;
   }
#endif /* TASK_CREATE_DESTROY */
/*E.5.0.602.END*/

/* E.5.5.5.987 Begin */
#endif /* SEM_CREATE_DESTROY and CUSTOM_SEM_MTX */
/* E.5.5.5.987 End */

#ifdef TESTING
   taskUnsafe();
#endif

   return status;

}                                      /* END RECL_Init */
/*############################################################################
 *### RECL_Terminate
 *###
 *### DESCRIPTION:
 *### Terminates the three semaphores used to control the reclamation
 *### process and the reclamation task that runs in the background.
 *###
 *### PARAMETERS:
 *###    IN: void
 *###    OUT:
 *###
 *### RETURNS:
 *###    Returns the following errors codes:
 *###       BKGD_ERR_NONE
 *###       BKGD_ERR_SEMAPHORE
 *###*/
HW_ERROR
RECL_Terminate(void)
{

#ifdef TESTING
   /* Make task safe during plr testing to ensure TID is updated
      prior to preemption during power loss emulation. */
   taskSafe();
#endif

#if(TASK_CREATE_DESTROY == TRUE)
   /* destroy the reclamation task */
   if (RECL_TaskId != 0)
   {
      TASK_DESTROY(RECL_TaskId);
   }
#endif /* TASK_CREATE_DESTROY */

/* E.5.5.5.987 Begin */
#if( (SEM_CREATE_DESTROY == TRUE) || defined(CUSTOM_SEM_MTX) ) 
/* E.5.5.5.987 End */

#if(SEM_CREATE_DESTROY == TRUE)

   /* destroy binary semaphore for the global ReclaimRequest */
   if (RECL_Request != SEM_NULL)
   {
      SEM_DESTROY(RECL_Request);
   }

   /* destroy binary semaphore for the global ReclaimEnable */
   if (RECL_Enable != SEM_NULL)
   {
      SEM_DESTROY(RECL_Enable);
   }

   /* destroy binary semaphore for the global ReclaimDone */

   if (RECL_Done != SEM_NULL)
   {
      SEM_DESTROY(RECL_Done);
   }
/* E.5.5.5.987 Begin */   
#endif /* SEM_CREATE_DESTROY */
/* E.5.5.5.987 End */

   /* destroy mutex semaphore for the reclaim copy process */
   if (SEM_ReclaimInProg != SEM_NULL)
   {
      SEM_MTX_DESTROY(SEM_ReclaimInProg);
   }
/* E.5.5.5.987 Begin */
#endif /* SEM_CREATE_DESTROY and CUSTOM_SEM_MTX */
/* E.5.5.5.987 End */


#ifdef TESTING
   taskUnsafe();
#endif

   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 */
   RECL_ReclaimBlock = WORDMAX;

   return HW_ERR_NONE;
}                                      /* END RECL_Init */


/*############################################################################
 *### RECL_Task
 *###
 *### DESCRIPTION:
 *### Reclamation is the process used to make invalid regions of flash memory
 *### available for reuse for parameter storage.  The FDI system uses a spare
 *### block for reclaiming valid headers and data.  This spare is not used for
 *### parameter storage but is used for reclamation only.  When there is no
 *### more room to write updated or new data, the system finds a block with
 *### the greatest amount of invalid space and finds the spare block.
 *###
 *### Transfer of valid data and headers from the block being reclaimed to
 *### the spare block is the next step.  The status of the spare block
 *### indicates the valid data is being transferred.
 *###
 *### Upon completion of the data transfer the next step is to prepare the
 *### spare block to logically take the original block抯 place.  The FDI
 *### writes the original block抯 logical block number to the spare block抯
 *### block information structure. For power off recovery purposes the status
 *### of the spare block indicates the original block is about to be erased.
 *### The old block begins to erase after all valid data exists in the spare
 *### block.
 *###
 *### When the erase of the original block completes, the status of the spare
 *### block changes to indicate that the block is now a writable block.  All
 *### of the valid data and headers have been transferred successfully and
 *### the old locations have been erased.
 *###
 *### PARAMETERS:
 *###    IN:  void
 *###    OUT: void
 *### GLOBALS:
 *###    RECL_ReclaimBLock
 *###    FDI_LogicalBlockTable[]
 *###
 *### RETURNS: void
 *###
 *###*/
void
RECL_Task(void)
{
   BLOCK_INFO block_info;              /* contains block information */
   UNIT_HEADER header;                 /* contains unit header information */
   DWORD least_erased_count;           /* track this count for wearleveling */
   DWORD most_erased_count;            /* track this count for wearleveling */
   DWORD reclaim_block_addr;           /* local address for searching */
   DWORD spare_block_addr;
   BYTE  index;
   union words
   {
      DWORD this_count;                /* track the block's erase count */
      WORD unit_size;                  /* track the reclaimed unit size */
   }  reclaim;

   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

⌨️ 快捷键说明

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