📄 vend_cbw.c
字号:
//-----------------------------------------------------------------------------
// Copyright (c) 2005 Cypress Semiconductor, Inc. All rights reserved
//-----------------------------------------------------------------------------
//--------------------------------------------------------------------------
#include "globals.h"
#define NX2LP_CMD 0xC8 // NX2LP Manufacturing/Validation command support
#define CBW_NAND_READ_PAGE 0 // <bank><page><len> Read NAND Page (only 528 or 2K+64)
#define CBW_NAND_WRITE_PAGE 1 // <bank><page><len> Write NAND page (only 528 or 2K+64)
#define CBW_NAND_ERASE_BLK 2 // <bank><block> Erase Block (single block)
#define CBW_NAND_READ_REDUNDANT 3 // <bank><page> Read Redundant <block number>
#define CBW_NAND_READ_FLASH_ID 4 // <bank><len=7> Read Flash ID: return 4-byte ID, 2-status, 1-nandtype
#define CBW_NAND_ERASE_ALL 5 // <bank><skip> Erase All with <skip bad block=1>
#define CBW_NAND_SET_ERR 6 // Simulate NAND error on NAND Read Status
#define CBW_NAND_GEN_CMD 7 // TBD (need design)
#define CBW_8051_LUT_DUMP 8 // <len>
#define CBW_8051_MEM_READ 9 // <address><len> 8051 memory read
#define CBW_8051_MEM_WRITE 0xa // <address><len> 8051 memory write
#define CBW_8051_RENUM 0xb // re-enumeration
#define CBW_READ_UNIQUE_ID 0xc // Read NAND unique ID
//-----------------------------------------------------------------------------
// Configure FIFO6 to read data from NAND
//-----------------------------------------------------------------------------
void Fifo6In() { P_FIFORESET=6, P_EP6CFG=EP6CFG_IN_DEFAULT; }
//-----------------------------------------------------------------------------
// Send Command to NAND chip
// cmd = NAND Command
//-----------------------------------------------------------------------------
void NandSendCmd(BYTE cmd)
{
NAND_CLE=1, P_XGPIFSGLDATLX=cmd, NAND_CLE=0;
}
//-----------------------------------------------------------------------------
// General read data from NAND using GPIF wave form 0
//-----------------------------------------------------------------------------
void NandRead(BYTE ep, WORD len)
{
nand_ready3();
FifoRd(ep, len);
}
//-----------------------------------------------------------------------------
// Get NAND Type
// EP6FIFOBUF contains 4-bytes ID, 2-byte status, 1-byte=bNand2k
//-----------------------------------------------------------------------------
void GetNandType()
{
Fifo6In(); // need this for reading data, see waveform
NandSendCmd(cNAND_READ_ID);
NAND_ALE=1, P_XGPIFSGLDATLX=0, NAND_ALE=0;
NandRead(cEP6,4-1); // read NAND ID: 4 bytes
NandSendCmd(cNAND_READ_STATUS);
NandRead(cEP6,2-1); // read status 2 bytes
// 512/2K NAND Auto detect should be done here
// Use NAND_2K as sharing 2K/512 FW code
#ifdef NAND_2K
bNand2k = 1; // force this bit = 2K NAND
#else
bNand2k = 0; // force this bit = 512 NAND
#endif
EP6FIFOBUF[6]= bNand2k; // return NAND type
}
//-----------------------------------------------------------------------------
// NAND Set Address: Take 2.2 us for 512P NAND
// msk = 0-3, read page 1-4
// msk = 4, read offset 0x830 = redundant
// return none
// global: bit bNand2k = 1 = 2KP NAND, else 512P NAND
// gPhyAdd: set this before call this subroutine
//-----------------------------------------------------------------------------
// for 2K NAND sub-page address: 0=0x000 1=0x210, 2=0x420, 3=0x630, 4=0x830
const char code nadd0[5]={0, 0x10, 0x20, 0x30, 0x30};
const char code nadd1[5]={0, 0x02, 0x04, 0x06, 0x08};
void NandSetAdd(BYTE cmd, BYTE msk)
{
nand_ready3();
NAND_CLE=1,P_XGPIFSGLDATLX=cmd, NAND_CLE=0;
NAND_ALE = 1;
if (bNand2k)
{
P_XGPIFSGLDATLX = nadd0[msk];
P_XGPIFSGLDATLX = nadd1[msk];
}
else
P_XGPIFSGLDATLX = 0;
P_XGPIFSGLDATLX = ((BYTE *)&gPhyAdd)[3];
P_XGPIFSGLDATLX = ((BYTE *)&gPhyAdd)[2];
P_XGPIFSGLDATLX = ((BYTE *)&gPhyAdd)[1];
NAND_ALE = 0;
if (bNand2k && cmd==cNAND_READ_DATA) NAND_CLE=1, P_XGPIFSGLDATLX=cNAND_READ_START, NAND_CLE=0;
}
//-----------------------------------------------------------------------------
// Reading NAND Configuration page
// The reading always support ECC correction
//-----------------------------------------------------------------------------
bit nReadCfgPage()
{
Fifo6In();
P_ECCRESET=0;
NandSetAdd(cNAND_READ_DATA, 0);
NandRead(cEP6, cNAND_PSIZE); // always read 512+16 bytes
ECCSetup(EP6FIFOBUF+512+cCFG_ECC_OFF);
gPhyAdd++; // next page
return CorrectData(); // always correct data
}
//-----------------------------------------------------------------------------
// nCopyBlock:
// Correct Bad ECC Block for both 2K NAND and 512 NAND
// Mark the block bad with 0xF0 if there is more than 2-bit ECC error
// bSofErr will control the
/// Mark the block bad with multiple repeat 1-bit ECC errors
//-----------------------------------------------------------------------------
void nCopyBlock()
{
#ifdef NAND_2K // 2K FW code
BYTE xdata cnt;
bit bECC_Retry;
xbyte *p;
WORD xdata pa0;
#ifdef USE_2NAND
if (gBank==0) CE0_ON(); else CE1_ON();
#else
IOD = gEnableBanks;
#endif
p = (xbyte*)&gLog2Phy[gSrc];
bECC_Retry = (*p & MSB(cBLK_ECC));
*p |= MSB(cBLK_ECC); // set ECC bit
pa0 = gCurZone << cMaxBlock2N; // compute Zone
gSrcAdd = ((DWORD)(pa0 | gSrc) << c2KPageSize2N);
gSrcBlk0 = ((BYTE *)&gSrcAdd)[3];
nGetFreeBlk(); // return gFreeBlk
gPhyAdd = ((DWORD)(pa0 | gFreeBlk) << c2KPageSize2N);
b2BitErr = 0;
nCopyPages(0, 0); // copy and correct ECC data
bNeedErase=1;
if (b2BitErr || (bECC_Retry && !bSoftErr))
{
if (b2BitErr) // more than 2 bit need to erase
{
xPhyAdd -= c2KPageSize2N; // need to erase good block
nand_blk_erase(gPhyAdd);
}
// mask the src block bad
((BYTE *)&gPhyAdd)[3] = gSrcBlk0;
((BYTE *)&gPhyAdd)[2] = ((BYTE *)&gSrcAdd)[2];
((BYTE *)&gPhyAdd)[1] = ((BYTE *)&gSrcAdd)[1];
NandSetAdd(cNAND_WRITE_DATA, 3);
for (cnt=0; cnt<(528/4); cnt++) // mask this block bad
{
P_XGPIFSGLDATLX = 0xf0; _nop_();
P_XGPIFSGLDATLX = 0xf0; _nop_();
P_XGPIFSGLDATLX = 0xf0; _nop_();
P_XGPIFSGLDATLX = 0xf0;
}
NandSendCmd(cNAND_PROGRAM_PAGE); // program only one page
gCurZone = 0xff; // refresh the LUT
}
else
{
*p &= MSB(~cBLK_USE); // set this block free
*(xbyte*)&gLog2Phy[gFreeBlk] |= MSB(cBLK_USE); // Set this block is used
*pDst = (*pDst & cBLK_uMSK) | gFreeBlk; // update Logical address
nEraseBlock(); // erase block
}
#else // 512 FW code
BYTE cnt=32;
bit bECC_Retry;
xbyte *p;
WORD pa0;
if (bInterLeave) cnt=64; // (32 page per NAND)*2
#ifdef USE_2NAND
CE0_ON(), CE1_ON();
#else
IOD = gEnableBanks;
#endif
p = (xbyte*)&gLog2Phy[gSrc];
bECC_Retry = (*p & MSB(cBLK_ECC));
*p |= MSB(cBLK_ECC); // set ECC bit
pa0 = gCurZone << cMaxBlock2N; // compute Zone
gSrcAdd = ((DWORD)(pa0 | gSrc) << c512PageSize2N);
gSrcBlk0 = ((BYTE *)&gSrcAdd)[3];
nGetFreeBlk(); // return gFreeBlk
gPhyAdd = ((DWORD)(pa0 | gFreeBlk) << c512PageSize2N);
b2BitErr = 0;
nCopyPages(cnt, 0); // copy and correct ECC data
bNeedErase=1;
if (b2BitErr || (bECC_Retry && !bSoftErr))
{
#ifdef USE_2NAND
CE0_ON(), CE1_ON();
#else
IOD = gEnableBanks;
#endif
if (b2BitErr) // more than 2 bit need to erase
{
xPhyAdd -= c512PageSize2N; // need to erase good block
nand_blk_erase(gPhyAdd);
}
// mask the src block bad
((BYTE *)&gPhyAdd)[3] = gSrcBlk0;
((BYTE *)&gPhyAdd)[2] = ((BYTE *)&gSrcAdd)[2];
((BYTE *)&gPhyAdd)[1] = ((BYTE *)&gSrcAdd)[1];
NandSetAdd(cNAND_WRITE_DATA, 3);
for (cnt=0; cnt<(528/4); cnt++) // mask this block bad
{
P_XGPIFSGLDATLX = 0xf0; _nop_();
P_XGPIFSGLDATLX = 0xf0; _nop_();
P_XGPIFSGLDATLX = 0xf0; _nop_();
P_XGPIFSGLDATLX = 0xf0;
}
NandSendCmd(cNAND_PROGRAM_PAGE); // program only one page
gCurZone = 0xff; // refresh the LUT
}
else
{
*p &= MSB(~cBLK_USE); // set this block free
*(xbyte*)&gLog2Phy[gFreeBlk] |= MSB(cBLK_USE); // Set this block is used
*pDst = (*pDst & cBLK_uMSK) | gFreeBlk; // update Logical address
nEraseBlock(); // erase block
}
#endif
DISABLE_NAND();
}
//-----------------------------------------------------------------------------
// Get NAND configuration data
// This code follow the Boot-Loader code to get configuration data and
// Vendor Strings
// This code supports both 2K and 512 NAND types
//-----------------------------------------------------------------------------
void GetNandCfg()
{
BYTE xdata n, ID, ntype, bank;
bit nand=0;
gZones = cMaxZone; // 512: default = 8 zone
#ifdef USE_2NAND
CE0_ON();
#else
IOD = 0xFE; // start from Bank0
#endif
GetNandType(); // Get ID & Status byte
GetNandType(); // Get ID & Status byte
ID = EP6FIFOBUF[0]; // get NAND ID
ntype = EP6FIFOBUF[1]; // get NAND ID
for (bank=0; bank<2 && nand==0; bank++)
{
for (n=0; n<cMaxBlkChk; n++)
{
if (bNand2k==0) gPhyAdd = n << 5; else gPhyAdd = n << 6;
if ( (nReadCfgPage()==cOK) && // make sure no ECC error
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -