?? rawnandflash.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 "RawNandFlash.h"
#include "NandCommon.h"
#include "NandFlashModelList.h"
#include <utility/trace.h>
#include <utility/assert.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
/// Nand flash chip status codes
#define STATUS_READY (1 << 6)
#define STATUS_ERROR (1 << 0)
/// Nand flash commands
#define COMMAND_READ_1 0x00
#define COMMAND_READ_2 0x30
#define COMMAND_COPYBACK_READ_1 0x00
#define COMMAND_COPYBACK_READ_2 0x35
#define COMMAND_COPYBACK_PROGRAM_1 0x85
#define COMMAND_COPYBACK_PROGRAM_2 0x10
#define COMMAND_RANDOM_OUT 0x05
#define COMMAND_RANDOM_OUT_2 0xE0
#define COMMAND_RANDOM_IN 0x85
#define COMMAND_READID 0x90
#define COMMAND_WRITE_1 0x80
#define COMMAND_WRITE_2 0x10
#define COMMAND_ERASE_1 0x60
#define COMMAND_ERASE_2 0xD0
#define COMMAND_STATUS 0x70
#define COMMAND_RESET 0xFF
/// Nand flash commands (small blocks)
#define COMMAND_READ_A 0x00
#define COMMAND_READ_C 0x50
//------------------------------------------------------------------------------
// Internal macros
//------------------------------------------------------------------------------
#define ENABLE_CE(raw) PIO_Clear(&(raw->pinChipEnable))
#define DISABLE_CE(raw) PIO_Set(&(raw->pinChipEnable))
#define WRITE_COMMAND(raw, command) \
{*((volatile unsigned char *) raw->commandAddress) = (unsigned char) command;}
#define WRITE_ADDRESS(raw, address) \
{*((volatile unsigned char *) raw->addressAddress) = (unsigned char) address;}
#define WRITE_DATA8(raw, data) \
{*((volatile unsigned char *) raw->dataAddress) = (unsigned char) data;}
#define READ_DATA8(raw) \
(*((volatile unsigned char *) raw->dataAddress))
#define WRITE_DATA16(raw, data) \
{*((volatile unsigned short *) raw->dataAddress) = (unsigned short) data;}
#define READ_DATA16(raw) \
(*((volatile unsigned short *) raw->dataAddress))
/// Internal cast macros
#define MODEL(raw) ((struct NandFlashModel *) raw)
/// Number of tries for erasing a block
#define NUMERASETRIES 2
/// Number of tries for writing a block
#define NUMWRITETRIES 2
/// Number of tries for copying a block
#define NUMCOPYTRIES 2
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Sends the column address to the NandFlash chip.
/// \param raw Pointer to a RawNandFlash instance.
/// \param columnAddress Column address to send.
//------------------------------------------------------------------------------
static void WriteColumnAddress(
const struct RawNandFlash *raw,
unsigned short columnAddress)
{
unsigned short pageDataSize = NandFlashModel_GetPageDataSize(MODEL(raw));
/* Check the data bus width of the NandFlash */
if (NandFlashModel_GetDataBusWidth(MODEL(raw)) == 16) {
/* Div 2 is because we address in word and not in byte */
columnAddress >>= 1;
}
while (pageDataSize > 0) {
WRITE_ADDRESS(raw, columnAddress & 0xFF);
pageDataSize >>= 8;
columnAddress >>= 8;
}
}
//------------------------------------------------------------------------------
/// Sends the row address to the NandFlash chip.
/// \param raw Pointer to a RawNandFlash instance.
/// \param rowAddress Row address to send.
//------------------------------------------------------------------------------
static void WriteRowAddress(
const struct RawNandFlash *raw,
unsigned int rowAddress)
{
unsigned int numPages = NandFlashModel_GetDeviceSizeInPages(MODEL(raw));
while (numPages > 0) {
WRITE_ADDRESS(raw, rowAddress & 0xFF);
numPages >>= 8;
rowAddress >>= 8;
}
}
//------------------------------------------------------------------------------
/// Waiting for the completion of a page program, erase and random read completion.
/// \param raw Pointer to a RawNandFlash instance.
//------------------------------------------------------------------------------
static void WaitReady(const struct RawNandFlash *raw)
{
if (raw->pinReadyBusy.mask) {
while (!PIO_Get(&(raw->pinReadyBusy)));
}
else {
WRITE_COMMAND(raw, COMMAND_STATUS);
while ((READ_DATA8(raw) & STATUS_READY) != STATUS_READY);
}
}
//------------------------------------------------------------------------------
/// Return 1 if program or erase operation is completed.
/// and the program or erase operation is completed successfully, otherwise return 0.
/// \param raw Pointer to a RawNandFlash instance.
//------------------------------------------------------------------------------
static unsigned char IsOperationComplete(const struct RawNandFlash *raw)
{
unsigned char status;
WRITE_COMMAND(raw, COMMAND_STATUS);
status = READ_DATA8(raw);
if (((status & STATUS_READY) != STATUS_READY) || ((status & STATUS_ERROR) != 0)) {
return 0;
}
return 1;
}
//------------------------------------------------------------------------------
/// Sends data to the NandFlash chip from the provided buffer.
/// \param raw Pointer to a RawNandFlash instance.
/// \param buffer Buffer where the data is stored.
/// \param size Number of bytes that will be written
//------------------------------------------------------------------------------
static void WriteData(
const struct RawNandFlash *raw,
unsigned char *buffer,
unsigned int size)
{
unsigned int i;
// Check the data bus width of the NandFlash
if (NandFlashModel_GetDataBusWidth(MODEL(raw)) == 16) {
unsigned short *buffer16 = (unsigned short *) buffer;
size >>= 1;
for(i=0; i < size; i++) {
WRITE_DATA16(raw, buffer16[i]);
}
}
else {
for(i=0; i < size; i++) {
WRITE_DATA8(raw, buffer[i]);
}
}
}
//------------------------------------------------------------------------------
/// Reads data from the NandFlash chip into the provided buffer.
/// \param nand Pointer to a RawNandFlash instance.
/// \param buffer Buffer where the data will be stored.
/// \param size Number of bytes that will be read
//------------------------------------------------------------------------------
static void ReadData(
const struct RawNandFlash *raw,
unsigned char *buffer,
unsigned int size)
{
unsigned int i;
// Check the chip data bus width
if (NandFlashModel_GetDataBusWidth(MODEL(raw)) == 16) {
unsigned short *buffer16 = (unsigned short *) buffer;
size >>= 1;
for (i=0; i < size; i++) {
buffer16[i] = READ_DATA16(raw);
}
}
else {
for (i=0; i < size; i++) {
buffer[i] = READ_DATA8(raw);
}
}
}
//------------------------------------------------------------------------------
/// Erases the specified block of the device. Returns 0 if the operation was
/// successful; otherwise returns an error code.
/// \param raw Pointer to a RawNandFlash instance.
/// \param block Number of the physical block to erase.
//------------------------------------------------------------------------------
static unsigned char EraseBlock(
const struct RawNandFlash *raw,
unsigned short block)
{
unsigned char error = 0;
unsigned int rowAddress;
trace_LOG(DEBUG, "EraseBlock(%d)\r\n", block);
// Calculate address used for erase
rowAddress = block * NandFlashModel_GetBlockSizeInPages(MODEL(raw));
// Start erase
ENABLE_CE(raw);
WRITE_COMMAND(raw, COMMAND_ERASE_1);
WriteRowAddress(raw, rowAddress);
WRITE_COMMAND(raw, COMMAND_ERASE_2);
WaitReady(raw);
if (!IsOperationComplete(raw)) {
trace_LOG(trace_ERROR,
"EraseBlock: Could not erase block.\n\r");
error = NandCommon_ERROR_CANNOTERASE;
}
DISABLE_CE(raw);
return error;
}
//------------------------------------------------------------------------------
/// Writes the data and/or the spare area of a page on a NandFlash chip. If one
/// of the buffer pointer is 0, the corresponding area is not written.
/// Returns 0 if the write operation is successful; otherwise returns 1.
/// \param raw Pointer to a RawNandFlash instance.
/// \param block Number of the block where the page to write resides.
/// \param page Number of the page to write inside the given block.
/// \param data Buffer containing the data area.
/// \param spare Buffer containing the spare area.
//------------------------------------------------------------------------------
static unsigned char WritePage(
const struct RawNandFlash *raw,
unsigned short block,
unsigned short page,
void *data,
void *spare)
{
unsigned char error = 0;
unsigned int pageDataSize = NandFlashModel_GetPageDataSize(MODEL(raw));
unsigned int spareDataSize = NandFlashModel_GetPageSpareSize(MODEL(raw));
unsigned int rowAddress;
trace_LOG(DEBUG, "WritePage(B#%d:P#%d)\r\n", block, page);
// Calculate physical address of the page
rowAddress = block * NandFlashModel_GetBlockSizeInPages(MODEL(raw)) + page;
// Start write operation
ENABLE_CE(raw);
// Write data area if needed
if (data) {
WRITE_COMMAND(raw, COMMAND_WRITE_1);
WriteColumnAddress(raw, 0);
WriteRowAddress(raw, rowAddress);
WriteData(raw, (unsigned char *) data, pageDataSize);
// Spare is written here as well since it is more efficient
if (spare) {
WriteData(raw, (unsigned char *) spare, spareDataSize);
}
WRITE_COMMAND(raw, COMMAND_WRITE_2);
WaitReady(raw);
if (!IsOperationComplete(raw)) {
trace_LOG(trace_ERROR, "WritePage: Failed writing data area.\n\r");
error = NandCommon_ERROR_CANNOTWRITE;
}
}
// Write spare area alone if needed
if (spare && !data) {
WRITE_COMMAND(raw, COMMAND_WRITE_1);
WriteColumnAddress(raw, pageDataSize);
WriteRowAddress(raw, rowAddress);
WriteData(raw, (unsigned char *) spare, spareDataSize);
WRITE_COMMAND(raw, COMMAND_WRITE_2);
WaitReady(raw);
if (!IsOperationComplete(raw)) {
trace_LOG(trace_ERROR, "WritePage: Failed writing data area.\n\r");
error = NandCommon_ERROR_CANNOTWRITE;
}
}
// Disable chip
DISABLE_CE(raw);
return error;
}
//------------------------------------------------------------------------------
/// Copies the data in a page of the NandFlash device to an other page on that
/// same chip. Both pages must have be even or odd; it is not possible to copy
/// and even page to an odd page and vice-versa.
/// Returns 0 if the operation is successful; otherwise returns a
/// NandCommon_ERROR code.
/// \param raw Pointer to a RawNandFlash instance.
/// \param sourceBlock Source block number.
/// \param sourcePage Source page number inside the source block.
/// \param destBlock Destination block number.
/// \param destPage Destination page number inside the destination block.
//------------------------------------------------------------------------------
static unsigned char CopyPage(
const struct RawNandFlash *raw,
unsigned short sourceBlock,
unsigned short sourcePage,
unsigned short destBlock,
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -