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 + -
显示快捷键?