📄 skipblocknandflash.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 "SkipBlockNandFlash.h"
#include "NandSpareScheme.h"
#include "NandFlashModel.h"
#include "RawNandFlash.h"
#include <utility/trace.h>
#include <utility/assert.h>
#include <string.h>
//------------------------------------------------------------------------------
// Internal definitions
//------------------------------------------------------------------------------
// Casts
#define ECC(skipBlock) ((struct EccNandFlash *) skipBlock)
#define RAW(skipBlock) ((struct RawNandFlash *) skipBlock)
#define MODEL(skipBlock) ((struct NandFlashModel *) skipBlock)
// Values returned by the CheckBlock() function
#define BADBLOCK 255
#define GOODBLOCK 254
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns BADBLOCK if the given block of a nandflash device is bad; returns
/// GOODBLOCK if the block is good; or returns a NandCommon_ERROR code.
/// \param skipBlock Pointer to a SkipBlockNandFlash instance.
/// \param block Number of block to check.
//------------------------------------------------------------------------------
static unsigned char CheckBlock(
const struct SkipBlockNandFlash *skipBlock,
unsigned short block)
{
#if !defined (OP_BOOTSTRAP_on)
unsigned char spare[NandCommon_MAXPAGESPARESIZE];
unsigned char error;
unsigned char badBlockMarker;
const struct NandSpareScheme *scheme;
// Retrieve model scheme
scheme = NandFlashModel_GetScheme(MODEL(skipBlock));
// Read spare area of first page of block
error = RawNandFlash_ReadPage(RAW(skipBlock), block, 0, 0, spare);
if (error) {
TRACE_ERROR("CheckBlock: Cannot read page #0 of block #%d\n\r", block);
return error;
}
NandSpareScheme_ReadBadBlockMarker(scheme, spare, &badBlockMarker);
if (badBlockMarker != 0xFF) {
return BADBLOCK;
}
// Read spare area of second page of block
error = RawNandFlash_ReadPage(RAW(skipBlock), block, 1, 0, spare);
if (error) {
TRACE_ERROR("CheckBlock: Cannot read page #1 of block #%d\n\r", block);
return error;
}
NandSpareScheme_ReadBadBlockMarker(scheme, spare, &badBlockMarker);
if (badBlockMarker != 0xFF) {
return BADBLOCK;
}
#endif
return GOODBLOCK;
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes a SkipBlockNandFlash instance. Scans the device to retrieve or
/// create block status information.
/// \param skipBlock Pointer to a SkipBlockNandFlash 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 SkipBlockNandFlash_Initialize(
struct SkipBlockNandFlash *skipBlock,
const struct NandFlashModel *model,
unsigned int commandAddress,
unsigned int addressAddress,
unsigned int dataAddress,
const Pin pinChipEnable,
const Pin pinReadyBusy)
{
unsigned char error;
#if !defined(OP_BOOTSTRAP_on)
unsigned int numBlocks;
unsigned int block;
#endif
TRACE_DEBUG("SkipBlockNandFlash_Initialize()\n\r");
// Initialize SkipBlockNandFlash
#if !defined(OP_BOOTSTRAP_on)
error = EccNandFlash_Initialize(ECC(skipBlock),
model,
commandAddress,
addressAddress,
dataAddress,
pinChipEnable,
pinReadyBusy);
#else
error = RawNandFlash_Initialize(RAW(skipBlock),
model,
commandAddress,
addressAddress,
dataAddress,
pinChipEnable,
pinReadyBusy);
#endif
#if !defined(OP_BOOTSTRAP_on)
if (error) {
return error;
}
// Retrieve model information
numBlocks = NandFlashModel_GetDeviceSizeInBlocks(MODEL(skipBlock));
// Initialize block statuses
TRACE_DEBUG("Retrieving bad block information ...\n\r");
// Retrieve block status from their first page spare area
for (block = 0; block < numBlocks; block++) {
// Read spare of first page
error = CheckBlock(skipBlock, block);
if (error != GOODBLOCK) {
if (error == BADBLOCK) {
TRACE_DEBUG("Block #%d is bad\n\r", block);
}
else {
TRACE_ERROR(
"SkipBlockNandFlash_Initialize: Cannot retrieve info from block #%u\n\r", block);
}
}
}
#endif
return 0;
}
//------------------------------------------------------------------------------
/// Erases a block of a SkipBlock NandFlash.
/// Returns the RawNandFlash_EraseBlock code or NandCommon_ERROR_WRONGSTATUS.
/// \param skipBlock Pointer to a SkipBlockNandFlash instance.
/// \param block Number of block to erase.
//------------------------------------------------------------------------------
unsigned char SkipBlockNandFlash_EraseBlock(
struct SkipBlockNandFlash *skipBlock,
unsigned short block,
unsigned int eraseType)
{
unsigned char error;
const struct NandSpareScheme *scheme;
unsigned char spare[NandCommon_MAXPAGESPARESIZE];
// TRACE_INFO("SkipBlockNandFlash_EraseBlock(%d)\n\r", block);
if (eraseType != SCRUB_ERASE) {
// Check block status
if (CheckBlock(skipBlock, block) != GOODBLOCK) {
TRACE_INFO("SkipBlockNandFlash_EraseBlock: Block is BAD\n\r");
return NandCommon_ERROR_BADBLOCK;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -