📄 mappednandflash.c
字号:
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "MappedNandFlash.h"
#include <utility/trace.h>
#include <utility/assert.h>
#include <utility/math.h>
#include <string.h>
//------------------------------------------------------------------------------
// Internal definitions
//------------------------------------------------------------------------------
/// Custom trace levels for the current file
#define DEBUG trace_DEBUG
#define INFO trace_INFO
#define IMPORTANT trace_FATAL
/// Casts
#define MANAGED(mapped) ((struct ManagedNandFlash *) mapped)
#define ECC(mapped) ((struct EccNandFlash *) mapped)
#define RAW(mapped) ((struct RawNandFlash *) mapped)
#define MODEL(mapped) ((struct NandFlashModel *) mapped)
/// Logical block mapping pattern
#define PATTERN(i) ((i << 1) & 0x73)
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Scans a mapped nandflash to find an existing logical block mapping. If a
/// block contains the mapping, its index is stored in the provided variable (if
/// pointer is not 0).
/// Returns 0 if mapping has been found; otherwise returns
/// NandCommon_ERROR_NOMAPPING if no mapping exists, or another
/// NandCommon_ERROR_xxx code.
/// \param mapped Pointer to a MappedNandFlash instance.
/// \param logicalMappingBlock Pointer to a variable for storing the block
/// number.
//------------------------------------------------------------------------------
static unsigned char FindLogicalMappingBlock(
const struct MappedNandFlash *mapped,
signed short *logicalMappingBlock)
{
unsigned short block;
unsigned char found;
unsigned short numBlocks = NandFlashModel_GetDeviceSizeInBlocks(MODEL(mapped));
unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(mapped));
unsigned char error;
unsigned char data[NandCommon_MAXPAGEDATASIZE];
unsigned int i;
trace_LOG(DEBUG, "FindLogicalMappingBlock()\n\r");
// Search each LIVE block
found = 0;
block = 0;
while (!found && (block < numBlocks)) {
// Check that block is LIVE
if (MANAGED(mapped)->blockStatuses[block].status == NandBlockStatus_LIVE) {
// Read block
trace_LOG(DEBUG, "Checking LIVE block #%d\n\r", block);
error = ManagedNandFlash_ReadPage(MANAGED(mapped), block, 0, data, 0);
if (!error) {
// Compare data with logical mapping pattern
i = 0;
found = 1;
while ((i < pageDataSize) && found) {
if (data[i] != PATTERN(i)) {
found = 0;
}
i++;
}
// If this is the mapping, stop looking
if (found) {
trace_LOG(IMPORTANT, "Logical mapping found in block #%d\n\r", block);
if (logicalMappingBlock) {
*logicalMappingBlock = block;
}
return 0;
}
}
else if (error != NandCommon_ERROR_WRONGSTATUS) {
trace_LOG(trace_ERROR,
"FindLogicalMappingBlock: Failed to scan block #%d\n\r",
block);
return error;
}
}
block++;
}
trace_LOG(IMPORTANT, "No logical mapping found in device\n\r");
return NandCommon_ERROR_NOMAPPING;
}
//------------------------------------------------------------------------------
/// Loads the logical mapping contained in the given physical block.
/// Returns 0 if successful; otherwise, returns a NandCommon_ERROR code.
/// \param mapped Pointer to a MappedNandFlash instance.
/// \param physicalBlock Physical block number.
//------------------------------------------------------------------------------
static unsigned char LoadLogicalMapping(
struct MappedNandFlash *mapped,
unsigned short physicalBlock)
{
unsigned char error;
unsigned char data[NandCommon_MAXPAGEDATASIZE];
unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(mapped));
unsigned short numBlocks = NandFlashModel_GetDeviceSizeInBlocks(MODEL(mapped));
unsigned int remainingSize;
unsigned char *currentBuffer;
unsigned short currentPage;
unsigned int readSize;
unsigned int i;
unsigned char status;
signed short logicalBlock;
signed short firstBlock, lastBlock;
trace_LOG(INFO, "LoadLogicalMapping(B#%d)\n\r", physicalBlock);
// Load mapping from pages #1 - #XXX of block
currentBuffer = (unsigned char *) mapped->logicalMapping;
remainingSize = sizeof(mapped->logicalMapping);
currentPage = 1;
while (remainingSize > 0) {
// Read page
readSize = min(remainingSize, pageDataSize);
error = ManagedNandFlash_ReadPage(MANAGED(mapped),
physicalBlock,
currentPage,
data,
0);
if (error) {
trace_LOG(trace_ERROR,
"LoadLogicalMapping: Failed to load mapping\n\r");
return error;
}
// Copy page info
memcpy(currentBuffer, data, readSize);
currentBuffer += readSize;
remainingSize -= readSize;
currentPage++;
}
// Store mapping block index
mapped->logicalMappingBlock = physicalBlock;
// Power-loss recovery
for (i=0; i < numBlocks; i++) {
// Check that this is not the logical mapping block
if (i != physicalBlock) {
status = mapped->managed.blockStatuses[i].status;
logicalBlock = MappedNandFlash_PhysicalToLogical(mapped, i);
// Block is LIVE
if (status == NandBlockStatus_LIVE) {
// Block is not mapped -> release it
if (logicalBlock == -1) {
trace_LOG(IMPORTANT, "Releasing unmapped LIVE block #%d\n\r", i);
ManagedNandFlash_ReleaseBlock(MANAGED(mapped), i);
}
}
// Block is DIRTY
else if (status == NandBlockStatus_DIRTY) {
// Block is mapped -> fake it as live
if (logicalBlock != -1) {
trace_LOG(IMPORTANT, "Marking mapped DIRTY block #%d as LIVE\n\r", i);
mapped->managed.blockStatuses[i].status = NandBlockStatus_LIVE;
}
}
// Block is FREE or BAD
else {
// Block is mapped -> remove it from mapping
if (logicalBlock != -1) {
trace_LOG(IMPORTANT, "Unmapping FREE or BAD block #%d\n\r", i);
mapped->logicalMapping[logicalBlock] = -1;
}
}
}
}
trace_LOG(IMPORTANT, "Mapping loaded from block #%d\n\r", physicalBlock);
return 0;
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes a MappedNandFlash instance. Scans the device to look for and
/// existing logical block mapping; otherwise starts from scratch (no block
/// mapped).
/// Returns 0 if successful; otherwise returns a NandCommon_ERROR_xxx code.
/// \param mapped Pointer to a MappedNandFlash instance.
/// \param model Pointer to the underlying nand chip model. Can be 0.
/// \param commandAddress Address at which commands are sent.
/// \param addressAddress Address at which addresses are sent.
/// \param dataAddress Address at which data is sent.
/// \param pinChipEnable Pin controlling the CE signal of the NandFlash.
/// \param pinReadyBusy Pin used to monitor the ready/busy signal of the Nand.
//------------------------------------------------------------------------------
unsigned char MappedNandFlash_Initialize(
struct MappedNandFlash *mapped,
const struct NandFlashModel *model,
unsigned int commandAddress,
unsigned int addressAddress,
unsigned int dataAddress,
const Pin pinChipEnable,
const Pin pinReadyBusy)
{
unsigned char error;
unsigned short numBlocks;
unsigned short block;
signed short logicalMappingBlock = 0;
trace_LOG(INFO, "MappedNandFlash_Initialize()\n\r");
// Initialize ManagedNandFlash
error = ManagedNandFlash_Initialize(MANAGED(mapped),
model,
commandAddress,
addressAddress,
dataAddress,
pinChipEnable,
pinReadyBusy);
if (error) {
return error;
}
// Scan to find logical mapping
mapped->mappingModified = 0;
error = FindLogicalMappingBlock(mapped, &logicalMappingBlock);
if (!error) {
// Extract mapping from block
mapped->logicalMappingBlock = logicalMappingBlock;
return LoadLogicalMapping(mapped, logicalMappingBlock);
}
else if (error == NandCommon_ERROR_NOMAPPING) {
// Start with no block mapped
mapped->logicalMappingBlock = -1;
numBlocks = NandFlashModel_GetDeviceSizeInBlocks(MODEL(mapped));
for (block=0; block < numBlocks; block++) {
mapped->logicalMapping[block] = -1;
}
}
else {
trace_LOG(trace_ERROR, "MappedNandFlash_Initialize: Failed to initialize device\n\r");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -