?? nandflash.c
字號(hào):
#include <string.h>
#include "def.h"
#include "option.h"
#include "2440addr.h"
#include "2440lib.h"
#include "2440slib.h"
#include "mmu.h"
#include "profile.h"
#include "memtest.h"
#include "usbmain.h"
#include "usbout.h"
#include "usblib.h"
#include "2440usb.h"
typedef struct _SectorInfo
{
int dwReserved1; // Reserved - used by FAL
int bOEMReserved; // For use by OEM
int bBadBlock; // Indicates if block is BAD
int wReserved2; // Reserved - used by FAL
}SectorInfo, *PSectorInfo;
#define BAD_CHECK (0)
#define ECC_CHECK (0)
/*#define READ_REGISTER_BYTE(p) (p)
#define WRITE_REGISTER_BYTE(p, v) (p) = (v);
#define READ_REGISTER_USHORT(p) (p)
#define WRITE_REGISTER_USHORT(p, v) (p) = (v);
#define READ_REGISTER_ULONG(p) (p)
#define WRITE_REGISTER_ULONG(p, v) (p) = (v);*/
// Status bit pattern
#define STATUS_READY 0x40
#define STATUS_ERROR 0x01
#define NF_MECC_UnLock() {rNFCONT&=~(1<<5);}
#define NF_MECC_Lock() {rNFCONT|=(1<<5);}
#define NF_SECC_UnLock() {rNFCONT&=~(1<<6);}
#define NF_SECC_Lock() {rNFCONT|=(1<<6);}
#define NF_CMD(cmd) {rNFCMD=cmd;}
#define NF_ADDR(addr) {rNFADDR=addr;}
#define NF_nFCE_L() {rNFCONT&=~(1<<1);}
#define NF_nFCE_H() {rNFCONT|=(1<<1);}
#define NF_RSTECC() {rNFCONT|=(1<<4);}
#define NF_RDDATA() (rNFDATA)
#define NF_RDDATA8() ((*(volatile unsigned char*)0x4E000010) )
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_WRDATA8(data) {rNFDATA8=(BYTE)data;}
#define NF_WAITRB() while(!(rNFSTAT&(1<<0)))
#define NF_DATA_W(val) NF_WRDATA8(val)
#define NF_DATA_W4(val) NF_WRDATA(val)
// RnB Signal
#define NF_CLEAR_RB() {rNFSTAT |= (1<<2);} // Have write '1' to clear this bit.
#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));}
#define NF_CE_L() NF_nFCE_L()
#define NF_CE_H() NF_nFCE_H()
#define NF_DATA_R() rNFDATA
#define NF_ECC() rNFMECC0
typedef DWORD SECTOR_ADDR;
typedef PDWORD PSECTOR_ADDR;
typedef DWORD BLOCK_ID;
typedef PDWORD PBLOCK_ID;
static U32 srcAddress;
static U32 targetBlock; // Block number (0 ~ 4095)
static U32 targetSize; // Total byte size
//U32 downloadAddress;
extern U32 downloadAddress;
#define NFCONF_INIT 0xF850
// NAND Flash Command. This appears to be generic across all NAND flash chips
#define CMD_READ 0x00 // Read
#define CMD_READ1 0x01 // Read1
#define CMD_READ2 0x50 // Read2
#define CMD_READID 0x90 // ReadID
#define CMD_WRITE 0x80 // Write phase 1
#define CMD_WRITE2 0x10 // Write phase 2
#define CMD_ERASE 0x60 // Erase phase 1
#define CMD_ERASE2 0xd0 // Erase phase 2
#define CMD_STATUS 0x70 // Status read
#define CMD_RESET 0xff // Reset
// Status bit pattern
#define STATUS_READY 0x40 // Ready
#define STATUS_ERROR 0x01 // Error
#define VALIDADDR 0x05
#define NEED_EXT_ADDR 1
#define SECTOR_SIZE 512
#define BLOCK_STATUS_UNKNOWN 0x01
#define BLOCK_STATUS_BAD 0x02
#define BLOCK_STATUS_READONLY 0x04
#define BLOCK_STATUS_RESERVED 0x08
#define OEM_BLOCK_RESERVED 0x01
#define OEM_BLOCK_READONLY 0x02
#define BADBLOCKMARK 0x00
#define NUM_BLOCKS 4096
#define IMAGE_START_BLOCK 9
void WritePage512(LPBYTE Buf, PULONG pReg);
extern U32 downloadFileSize;
//*********************************************************************
void NF_Reset()
{
int i;
NF_CE_L();
NF_CLEAR_RB();///用了他,
NF_CMD(CMD_RESET);
for(i=0;i<10;i++); //tWB = 100ns. //??????
NF_CE_H();
}
//************************************************************************
BOOL NAND_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo)
{
BOOL bRet = TRUE;
// Chip enable
NF_CE_L();
NF_CLEAR_RB();
// Write the command
// First, let's point to the spare area
NF_CMD(CMD_READ2);
NF_CMD(CMD_WRITE);
// Write the address
NF_ADDR(0x00);
NF_ADDR(sectorAddr & 0xff);
NF_ADDR((sectorAddr >> 8) & 0xff);
if (NEED_EXT_ADDR) {
NF_ADDR((sectorAddr >> 16) & 0xff);
}
// Now let's write the SectorInfo data
//
// Write the first reserved field (DWORD)
NF_DATA_W4( pInfo->dwReserved1 );
// Write OEM reserved flag
NF_DATA_W( (pInfo->bOEMReserved) );
// Write the bad block flag
NF_DATA_W( (pInfo->bBadBlock) );
// Write the second reserved field
NF_DATA_W( (pInfo->wReserved2 >> 8) & 0xff );
NF_DATA_W( (pInfo->wReserved2) );
// Issue the write complete command
NF_CMD(CMD_WRITE2);
// Check ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
// Check the status of program
NF_CMD(CMD_STATUS);
if(NF_DATA_R() & STATUS_ERROR) {
Uart_Printf("NAND_WriteSectorInfo() ######## Error Programming page %d!\n", sectorAddr);
bRet = FALSE;
}
NF_CE_H();
return bRet;
}
//***********************************************************************
/*static void InputTargetBlock(void)
{
Uart_Printf("\nSource size:0h~%xh\n",downloadProgramSize);
Uart_Printf("\nAvailable target block number: 0~4095\n");
Uart_Printf("Input target block number:");
//targetBlock=GetInputNum(); // Block number(0~4095)
targetBlock = Uart_GetIntNum(); // Block number(0~4095)
if(targetSize==0)
{
Uart_Printf("\nInput target size(0x4000*n):");
targetSize=Uart_GetIntNum(); // Total byte size
}
}*/
//********************************************************************
static int NF_ReadPage(U32 block,U32 page,U8 *buffer)
{
int i;
unsigned int blockPage;
U8 ecc0,ecc1,ecc2;
U8 *bufPt=buffer;
U8 se[16];
page=page&0x1f;
blockPage=(block<<5)+page;
NF_RSTECC(); // Initialize ECC
NF_MECC_UnLock();
NF_CE_L();
NF_CLEAR_RB();
NF_CMD(0x00); // Read command
NF_ADDR(0); // Column = 0
NF_ADDR(blockPage&0xff); //
NF_ADDR((blockPage>>8)&0xff); // Block & Page num.
NF_ADDR((blockPage>>16)&0xff); //
for(i=0;i<10;i++); //wait tWB(100ns)/////??????
NF_WAITRB(); // Wait tR(max 12us)
for(i=0;i<512;i++)
{
*bufPt++=NF_DATA_R(); // Read one page
}
}
//**********************************************************************
BOOL IsBlockBad(BLOCK_ID blockID)
{
DWORD dwPageID = blockID << 5;
BOOL bRet = FALSE;
BYTE wFlag;
//GRABMUTEX();
// Enable the chip
NF_CE_L();
NF_CLEAR_RB();
// Issue the command
NF_CMD(CMD_READ2);
// Set up address
NF_ADDR(VALIDADDR);
NF_ADDR((dwPageID) & 0xff);
NF_ADDR((dwPageID >> 8) & 0xff);
if (NEED_EXT_ADDR) {
NF_ADDR((dwPageID >> 16) & 0xff);
}
// Wait for Ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
// Now get the byte we want
wFlag = (BYTE) NF_DATA_R();
// if(wFlag != 0xff) {
if(wFlag != 0xff) {
bRet = TRUE;
}
// Disable the chip
NF_CE_H();
// RELEASEMUTEX();
return bRet;
}
//**********************************************************************
char FMD_EraseBlock(BLOCK_ID blockID)
{
BOOL bRet = TRUE;
DWORD dwPageID = blockID << 5;
//Uart_Printf("FMD_EraseBlock::::::1 \r\n");
/*#ifndef NOSYSCALL
if(blockID < IMAGE_START_BLOCK)
{
bRet = FALSE;
Uart_Printf("\nFMD_EraseBlock continue\n");
//RELEASEMUTEX();
return bRet;
}
#endif*/
// Enable the chip
NF_CE_L();
//Uart_Printf("FMD_EraseBlock::::::2 \r\n");
NF_CLEAR_RB();
//Uart_Printf("FMD_EraseBlock::::::3 \r\n");
// Issue command
NF_CMD(CMD_ERASE);
//Uart_Printf("FMD_EraseBlock::::::4 \r\n");
// Set up address
NF_ADDR((dwPageID) & 0xff);
NF_ADDR((dwPageID >> 8) & 0xff);
//Uart_Printf("FMD_EraseBlock::::::5 \r\n");
if (NEED_EXT_ADDR) {
NF_ADDR((dwPageID >> 16) & 0xff);
}
// Complete erase operation
NF_CMD(CMD_ERASE2);
//Uart_Printf("FMD_EraseBlock::::::6 \r\n");
// Wait for ready bit
NF_DETECT_RB(); // Wait tR(max 12us)
//Uart_Printf("FMD_EraseBlock::::::7 \r\n");
// Check the status
NF_CMD(CMD_STATUS);
//Uart_Printf("FMD_EraseBlock::::::8 \r\n");
if(NF_DATA_R() & STATUS_ERROR) {
Uart_Printf("######## Error Erasing block %d!\n", blockID);
bRet = FALSE;
}
NF_CE_H();
return bRet;
}
//***********************************************************************
BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff,
DWORD dwNumSectors)
{
DWORD i;
BOOL bRet = TRUE;
DWORD dwECCVal;
BYTE eccBuf[4];
//Uart_Printf("FMD_WriteSector::::::1 \r\n");
if((!pSectorBuff && !pSectorInfoBuff) || dwNumSectors != 1) {
//#ifdef BOOT_LOADER
Uart_Printf("Invalid parameters!\r\n");
//#else
// RETAILMSG(1, (TEXT("Invalid parameters!\n")));
//#endif
//#ifndef NOSYSCALL
// SetLastError(ERROR_INVALID_PARAMETER);
//#endif
return FALSE;
}
//Uart_Printf("FMD_WriteSector::::::2 \r\n");
NF_Reset();
if(!pSectorBuff) {
// If we are asked just to write the SectorInfo, we will do that separately
bRet = NAND_WriteSectorInfo(startSectorAddr, pSectorInfoBuff);
Uart_Printf("FMD_WriteSector::::::3 \r\n");
return bRet; // Do not write the actual sector information...
}
//GRABMUTEX();
// Initialize ECC register
NF_RSTECC();
NF_MECC_UnLock();
// Enable Chip
NF_CE_L();
// Issue command
NF_CMD(CMD_READ);
NF_CMD(CMD_WRITE);
// Setup address
NF_ADDR(0x00);
NF_ADDR((startSectorAddr) & 0xff);
NF_ADDR((startSectorAddr >> 8) & 0xff);
if (NEED_EXT_ADDR) {
NF_ADDR((startSectorAddr >> 16) & 0xff);
}
// Special case to handle un-aligned buffer pointer.
//
if( ((DWORD) pSectorBuff) & 0x3) {
// Write the data
for(i=0; i<SECTOR_SIZE; i++) {
NF_DATA_W(pSectorBuff[i]);
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -