?? translatednandflash.c
字號:
if ((block == translated->currentLogicalBlock)
&& (translated->previousPhysicalBlock != -1)
&& (PageIsClean(translated, page))) {
trace_LOG(DEBUG, "Reading page from current block\n\r");
translated->previousPhysicalBlock,
page,
data,
spare);
}
else {
// Try to read the page from the logical block
error = MappedNandFlash_ReadPage(MAPPED(translated), block, page, data, spare);
// Block was not mapped
if (error == NandCommon_ERROR_BLOCKNOTMAPPED) {
ASSERT(!spare, "Cannot read the spare information of an unmapped block\n\r");
// Check if a block can be allocated
if (BlockCanBeAllocated(translated)) {
// Return 0xFF in buffers with no error
trace_LOG(DEBUG,
"Block #%d is not mapped but can be allocated, filling buffer with 0xFF\n\r",
block);
if (data) {
memset(data, 0xFF, NandFlashModel_GetPageDataSize(MODEL(translated)));
}
if (spare) {
memset(spare, 0xFF, NandFlashModel_GetPageSpareSize(MODEL(translated)));
}
}
else {
trace_LOG(trace_ERROR, "Block #%d is not mapped and there are no more blocks available\n\r", block);
return NandCommon_ERROR_NOMOREBLOCKS;
}
}
// Error
else if (error) {
return error;
}
}
return 0;
}
//------------------------------------------------------------------------------
/// Writes the data and/or spare area of a page on a translated nandflash.
/// Allocates block has needed to keep the wear even between all blocks.
/// \param translated Pointer to a TranslatedNandFlash instance.
/// \param block Logical block number.
/// \param page Number of page to write inside logical block.
/// \param data Data area buffer, can be 0.
/// \param spare Spare area buffer, can be 0.
//------------------------------------------------------------------------------
unsigned char TranslatedNandFlash_WritePage(
struct TranslatedNandFlash *translated,
unsigned short block,
unsigned short page,
void *data,
void *spare)
{
unsigned char allocate = 1;
unsigned char error;
trace_LOG(INFO, "TranslatedNandFlash_WritePage(B#%d:P#%d)\n\r", block, page);
// A new block must be allocated unless:
// 1. the block is not mapped and there are no more blocks to allocate
if (MappedNandFlash_LogicalToPhysical(MAPPED(translated), block) == -1) {
// Block is not mapped, check if it can be
if (!BlockCanBeAllocated(translated)) {
trace_LOG(trace_ERROR, "TranslatedNandFlash_WritePage: Not enough free blocks\n\r");
return NandCommon_ERROR_NOMOREBLOCKS;
}
trace_LOG(DEBUG, "Allocate because block not mapped\n\r");
}
// or 2. the block to write is the current one and the page to write is
// clean
else if (translated->currentLogicalBlock == block) {
if (PageIsClean(translated, page)) {
trace_LOG(DEBUG, "NO allocate because write in current block\n\r");
allocate = 0;
}
else {
trace_LOG(DEBUG, "Allocate because page DIRTY in current block\n\r");
}
}
else {
trace_LOG(DEBUG, "Allocate because block is mapped and different from current block\n\r");
}
// Allocate block if needed
if (allocate) {
// Flush current block write (if any) and then allocate block
error = TranslatedNandFlash_Flush(translated);
if (error) {
return error;
}
translated->previousPhysicalBlock = MappedNandFlash_LogicalToPhysical(
MAPPED(translated),
block);
trace_LOG(DEBUG, "Previous physical block is now #%d\n\r",
translated->previousPhysicalBlock);
error = AllocateBlock(translated, block);
if (error) {
return error;
}
// Block becomes the current block with all pages clean
translated->currentLogicalBlock = block;
MarkAllPagesClean(translated);
}
// Start writing page
error = MappedNandFlash_WritePage(MAPPED(translated),
block,
page,
data,
spare);
if (error) {
return error;
}
// If write went through, mark page as written
MarkPageDirty(translated, page);
return 0;
}
//------------------------------------------------------------------------------
/// Terminates the current write operation by copying all the missing pages from
/// the previous physical block.
/// \param translated Pointer to a TranslatedNandFlash instance.
//------------------------------------------------------------------------------
unsigned char TranslatedNandFlash_Flush(struct TranslatedNandFlash *translated)
{
unsigned int i;
unsigned char error;
unsigned int currentPhysicalBlock;
// Check if there is a current block and a previous block
if ((translated->currentLogicalBlock == -1)
|| (translated->previousPhysicalBlock == -1)) {
return 0;
}
trace_LOG(INFO, "TranslatedNandFlash_Flush(PB#%d -> LB#%d)\n\r",
translated->previousPhysicalBlock, translated->currentLogicalBlock);
// Copy missing pages in the current block
currentPhysicalBlock = MappedNandFlash_LogicalToPhysical(
MAPPED(translated),
translated->currentLogicalBlock);
for (i=0; i < NandFlashModel_GetBlockSizeInPages(MODEL(translated)); i++) {
if (PageIsClean(translated, i)) {
trace_LOG(DEBUG, "Copying back page #%d of block #%d\n\r", i,
translated->previousPhysicalBlock);
// Copy page
error = ManagedNandFlash_CopyPage(MANAGED(translated),
translated->previousPhysicalBlock,
i,
currentPhysicalBlock,
i);
if (error) {
trace_LOG(trace_ERROR, "FinishCurrentWrite: Failed to copy page #%d\n\r", i);
return error;
}
}
}
translated->currentLogicalBlock = -1;
translated->previousPhysicalBlock = -1;
return 0;
}
//------------------------------------------------------------------------------
/// Allocates a free block to save the current logical mapping on it.
/// Returns 0 if successful; otherwise returns a NandCommon_ERROR code.
/// \param translated Pointer to a TranslatedNandFlash instance.
//------------------------------------------------------------------------------
unsigned char TranslatedNandFlash_SaveLogicalMapping(
struct TranslatedNandFlash *translated)
{
unsigned char error;
unsigned short freeBlock;
trace_LOG(INFO, "TranslatedNandFlash_SaveLogicalMapping()\n\r");
// Save logical mapping in the youngest free block
// Find the youngest block
error = ManagedNandFlash_FindYoungestBlock(MANAGED(translated),
NandBlockStatus_FREE,
&freeBlock);
if (error) {
trace_LOG(trace_FATAL, "TranslatedNandFlash_SaveLogicalMapping: Could not find a free block\n\r");
return error;
}
// Check if this is the last free block, in which case dirty blocks are wiped
// prior to saving the mapping
if (ManagedNandFlash_CountBlocks(MANAGED(translated),
NandBlockStatus_FREE) == 1) {
TranslatedNandFlash_Flush(translated);
error = ManagedNandFlash_EraseDirtyBlocks(MANAGED(translated));
if (error) {
trace_LOG(trace_FATAL, "TranslatedNandFlash_Flush: Could not erase dirty blocks\n\r");
return error;
}
}
// Save the mapping
error = MappedNandFlash_SaveLogicalMapping(MAPPED(translated), freeBlock);
if (error) {
trace_LOG(trace_FATAL,
"TranslatedNandFlash_Flush: Failed to save mapping in block #%d\n\r",
freeBlock);
return error;
}
return 0;
}
//------------------------------------------------------------------------------
/// Returns the number of available blocks in a translated nandflash.
/// \param translated Pointer to a TranslatedNandFlash instance.
//------------------------------------------------------------------------------
unsigned short TranslatedNandFlash_GetDeviceSizeInBlocks(
const struct TranslatedNandFlash *translated)
{
return NandFlashModel_GetDeviceSizeInBlocks(MODEL(translated))
- MINNUMUNALLOCATEDBLOCKS
- ManagedNandFlash_CountBlocks(MANAGED(translated), NandBlockStatus_BAD)
- 1; // Logical mapping block
}
//------------------------------------------------------------------------------
/// Returns the number of available pages in a translated nandflash.
/// \param translated Pointer to a TranslatedNandFlash instance.
//------------------------------------------------------------------------------
unsigned int TranslatedNandFlash_GetDeviceSizeInPages(
const struct TranslatedNandFlash *translated)
{
return TranslatedNandFlash_GetDeviceSizeInBlocks(translated)
* NandFlashModel_GetBlockSizeInPages(MODEL(translated));
}
//------------------------------------------------------------------------------
/// Returns the number of available data bytes in a translated nandflash.
/// \param translated Pointer to a TranslatedNandFlash instance.
//------------------------------------------------------------------------------
unsigned long long TranslatedNandFlash_GetDeviceSizeInBytes(
const struct TranslatedNandFlash *translated)
{
return TranslatedNandFlash_GetDeviceSizeInPages(translated)
* NandFlashModel_GetPageDataSize(MODEL(translated));
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -