📄 inand.c
字号:
ecc0[2] = P_ECC1B0[2];
while (!gpifIdle());
//while (P_GPIFTCB0 & 0xf8); // Read second 256 ECC registers
ecc0[3] = P_ECC1B0[3]; // save ECC
ecc0[4] = P_ECC1B0[4]; // GPIF will be done afer reading these
ecc0[5] = P_ECC1B0[5]; // registers
// Stored 6-byte ECC data from NAND Flash
ecc1[0] = P_XAUTODAT1;
ecc1[1] = P_XAUTODAT1;
ecc1[2] = P_XAUTODAT1;
ecc1[3] = P_XAUTODAT1;
ecc1[4] = P_XAUTODAT1;
ecc1[5] = P_XAUTODAT1;
CorrectData();
fifo6_out(); // CFG Out for copy data
n2k_wadd(gPhyAdd, msk);
P_GPIFTCB1 = MSB(cNAND_DSIZE+8); // setup GPIF Count: Ignore 4-bytes
P_GPIFTCB0 = LSB(cNAND_DSIZE+8); // Reading 528 take 36us
GPIFTRIG=cEP6;
cc++;
msk = cc & 3; // use by 2K NAND
if (msk==0) { xSrcAdd++; xPhyAdd++; }
while (!gpifIdle());
P_XGPIFSGLDATLX = MSB(gDst); // Phy2Log
P_XGPIFSGLDATLX = LSB(gDst);
P_XGPIFSGLDATLX = MSB(gDst);
P_XGPIFSGLDATLX = LSB(gDst);
nand_send_command(cNAND_PROGRAM_PAGE);
} while ( bCnt );
#else
bit lba0 = cc&1;
do
{
Fifo6In();
P_GPIFTCB1 = MSB(cNAND_DSIZE+8); // setup GPIF Count
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_DSIZE+8); // Reading 512+2(status)+6(ECC)
if (bInterLeave)
{
#ifdef USE_2NAND
if (lba0) CE0_OFF(), CE1_ON(); else CE0_ON(), CE1_OFF();
#else
if (lba0) IOD=gEnableBank1; else IOD=gEnableBank0;
#endif
}
nand_ready3(); // wait for previous program done
n512_setadd(cNAND_READ_DATA,gSrcAdd); // read program pages
GPIFTRIG = 0x04 | cEP6; // Arm EP6
lba0 = !lba0;
bCnt = --cnt;
// When copy pages, all the data will have ECC correction
AUTOPTR1H = MSB(cEP6FIFO);
AUTOPTR1L = LSB(cEP6FIFO);
while (P_GPIFTCB1); // Read the first 256 ECC registers
ecc0[0] = P_ECC1B0[0]; // save to local buffers
ecc0[1] = P_ECC1B0[1];
ecc0[2] = P_ECC1B0[2];
while (P_GPIFTCB0 & 0xf8); // Read second 256 ECC registers
ecc0[3] = P_ECC1B0[3]; // save ECC
ecc0[4] = P_ECC1B0[4]; // GPIF will be done afer reading these
ecc0[5] = P_ECC1B0[5]; // registers
// Stored 6-byte ECC data from NAND Flash
ecc1[0] = P_XAUTODAT1;
ecc1[1] = P_XAUTODAT1;
ecc1[2] = P_XAUTODAT1;
ecc1[3] = P_XAUTODAT1;
ecc1[4] = P_XAUTODAT1;
ecc1[5] = P_XAUTODAT1;
CorrectData();
fifo6_out(); // CFG Out for copy data
P_GPIFTCB1 = MSB(cNAND_DSIZE+8); // setup GPIF Count: Ignore 4-bytes
P_GPIFTCB0 = LSB(cNAND_DSIZE+8); // Reading 528 take 36us
n512_setadd(cNAND_WRITE_DATA, gPhyAdd);
GPIFTRIG=cEP6;
if (!lba0 || bInterLeave==0) { xSrcAdd++; xPhyAdd++; }
while (!gpifIdle());
P_XGPIFSGLDATLX = MSB(gDst); // Phy2Log
P_XGPIFSGLDATLX = LSB(gDst);
P_XGPIFSGLDATLX = MSB(gDst);
P_XGPIFSGLDATLX = LSB(gDst);
nand_send_command(cNAND_PROGRAM_PAGE);
} while ( bCnt );
#endif
}
//==========================================================================
// Adding this code to support Wear-Leveling.
// Note: This subroutine should call only USB Idle, NAND Busy or
// Waiting GPIF Idle.
//==========================================================================
void nSearchFreeBlock(BYTE i)
{
WORD tmp;
if (bFreeFound) return; // if found do need to search again
tmp = (WORD)gLog2Phy + gFreeBlk*2;
AUTOPTR1H = MSB(tmp); AUTOPTR1L = LSB(tmp);
do
{
if (!(P_XAUTODAT1 & MSB(cBLK_uMSK)))
{
bFreeFound = 1; // Mark found a free erased block
return;
}
P_XAUTODAT1;
gFreeBlk++; // Search Next block
if (gFreeBlk & cMaxBlock)
gFreeBlk = 0, AUTOPTR1H = MSB(gLog2Phy), AUTOPTR1L = LSB(gLog2Phy);
} while (--i); // 1-256 search entries
}
//==========================================================================
// Write NAND Pages: support both interleave and non-interleave code
// Use gFreeBlk as the back ground searching free erased block
//==========================================================================
void nWritePages()
{
#ifdef NAND_2K
BYTE wcmd;
bit prog;
if (gPartialCpy==0) Log2Phy();
// Need to queue up more buffers to avoid hang up on the Write transfer
// for 512-byte just wait for empty
if ((gSectorcount>1) || !EZUSB_HIGHSPEED())
while (!(P_EP2CS & bmEPFULL)); // wait for host send all data
else
while ((P_EP2CS & bmEPEMPTY)); // Wait for host to send data
ARM_EP2();
P_EP2FIFOCFG = bmAUTOOUT | bmOEP; // set auto mode
NandSetAdd(cNAND_WRITE_DATA, (xLBA3 & 3));
do
{
P_GPIFTCB1 = MSB(cNAND_DSIZE);
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_DSIZE);
GPIFTRIG = cEP2;
//-----------------------------------------------------
// PreProcess calculation while waiting transfer done
//-----------------------------------------------------
bCnt = --gSectorcount;
dwLBA++; // next sector
prog = (xLBA3 & 3)==0;
wcmd = cNAND_PROGRAM_CACHE;
bReload = (xLBA3 == 0);
if (bReload || !bCnt) wcmd = cNAND_PROGRAM_PAGE;
bReload &= bCnt;
if (prog) { xPhyAdd++; xSrcAdd++; } // next address
prog |= !bCnt;
while (!gpifIdle());
WriteRedundant();
if (prog)
{
nand_send_command(wcmd);
if (bReload) { nEraseBlock(); Log2Phy(); }
if (bCnt) n2k_set_wadd();
}
} while (bCnt);
gPartialCpy = xLBA3;
// partial block must leave the nand chip select asserted
if (gPartialCpy)
gPartialCpy = 0-gPartialCpy;
else
{
nEraseBlock();
DISABLE_NAND();
}
P_EP2FIFOCFG = 0;
#else
if (gPartialCpy==0) Log2Phy();
// Need to queue up more buffers to avoid hang up on the Write transfer
// for 512-byte just wait for empty
if ((gSectorcount>1) || !EZUSB_HIGHSPEED())
while (!(P_EP2CS & bmEPFULL)); // wait for host send all data
else
while ((P_EP2CS & bmEPEMPTY)); // Wait for host to send data
ARM_EP2();
P_EP2FIFOCFG = bmAUTOOUT | bmOEP; // set auto mode
do
{
P_GPIFTCB1 = MSB(cNAND_DSIZE);
P_ECCRESET = P_GPIFTCB0 = LSB(cNAND_DSIZE);
if (bInterLeave)
{
#ifdef USE_2NAND
if (bLBA0) { CE1_ON(), CE0_OFF(); nand_ready1(); } // bank1
else { CE0_ON(), CE1_OFF(); nand_ready0(); } // bank0
#else
if (bLBA0) { IOD=gEnableBank1; nand_ready1(); } // bank1
else { IOD=gEnableBank0; nand_ready0(); } // bank0
#endif
}
else nand_ready3();
n512_setadd(cNAND_WRITE_DATA,gPhyAdd); // send program pages
GPIFTRIG = cEP2;
//-----------------------------------------------------
// PreProcess calculation while waiting transfer done
//-----------------------------------------------------
bCnt = --gSectorcount;
dwLBA++; // next sector
if (bInterLeave)
gPartialCpy = xLBA3 & cInterLeaveMsk;
else
gPartialCpy = xLBA3 & (c512PageSize-1);
if (!bLBA0 || bInterLeave==0) { xPhyAdd++; xSrcAdd++; } // next address
bReload = bCnt && gPartialCpy==0;
while (!gpifIdle());
WriteRedundant();
nand_send_command(cNAND_PROGRAM_PAGE);
// nSearchFreeBlock(64);
if (bReload) { nEraseBlock(); Log2Phy(); }
} while (bCnt);
// partial block must leave the nand chip select asserted
if (gPartialCpy)
{
if (bInterLeave) gPartialCpy = 64-gPartialCpy;
else gPartialCpy = c512PageSize-gPartialCpy;
}
else
{
nEraseBlock();
DISABLE_NAND();
}
P_EP2FIFOCFG = 0;
#endif
}
//==========================================================================
// Redundant mappping for Configuration block
// 0-9: 0xff, 01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
// a-f: ecc1b0, ecc1b1, ecc1b2, ecc2b0, ecc2b1, ecc2b2
// Redundant mappping for data block
// 0-7: 0xff, 0xff, ecc1b0, ecc1b1, ecc1b2, ecc2b0, ecc2b1, ecc2b2
// 8-b: add1, add2
// c-f: ignore
// set b2BitErr when more than 2 bit ECC error
//==========================================================================
bit CorrectData()
{
BYTE a,b,c,x,i;
for (i=0; i<2; i++)
{
b = ecc0[0] ^ ecc1[0];
a = ecc0[1] ^ ecc1[1];
c = ecc0[2] ^ ecc1[2];
if (a|b|c)
{
if ((((a^(a>>1)) & 0x55) == 0x55) && // Does each pair of parity bits contain
(((b^(b>>1)) & 0x55) == 0x55) && // one error and one match?
(((c^(c>>1)) & 0x54) == 0x54))
{
x = (a & 0x80); // If so, there's a one-bit error in data[].
if (a & 0x20) x |= 0x40; // Find which byte is in error...
if (a & 0x08) x |= 0x20;
if (a & 0x02) x |= 0x10;
if (b & 0x80) x |= 0x08;
if (b & 0x20) x |= 0x04;
if (b & 0x08) x |= 0x02;
if (b & 0x02) x |= 0x01;
a = 0; // ... and which bit...
if (c & 0x80) a |= 0x04;
if (c & 0x20) a |= 0x02;
if (c & 0x08) a |= 0x01;
EP6FIFOBUF[x+ (WORD)(i<<8)] ^= (1 << a); // ... and correct it.
// one bit is ok
}
else { b2BitErr=1; return cFail; } // two bits return error
}
ecc0[0] = ecc0[3];
ecc0[1] = ecc0[4];
ecc0[2] = ecc0[5];
ecc1[0] = ecc1[3];
ecc1[1] = ecc1[4];
ecc1[2] = ecc1[5];
}
return cOK;
}
#ifdef NAND_2K
//==========================================================================
// Internal Move:
// Partial page will use nCopyPages, the full 2K page will use
// internal move
//==========================================================================
void nNandMove(BYTE cnt, BYTE cc)
{
BYTE z, msk = cc&3;
if (!bInternalMove) { nCopyPages(cnt,cc); return; }
if (msk) { z = 4-msk; nCopyPages(z, msk); cnt -= z; }
msk = cnt/4;
// if the src is blank, need to have valid page
if (cc==0 && msk && bFreeBlk)
{
nCopyPages(4, 0); // ONLY need to copy 1st page
cnt -= 4;
msk--;
}
for (z=0; z<msk; z++)
{
nand_ready3();
NAND_CLE=1,P_XGPIFSGLDATLX=0, NAND_CLE=0;
NAND_ALE = 1;
P_XGPIFSGLDATLX = 0; cnt -= 4; P_XGPIFSGLDATLX = 0;
P_XGPIFSGLDATLX = ((BYTE *)&gSrcAdd)[3];
P_XGPIFSGLDATLX = ((BYTE *)&gSrcAdd)[2];
P_XGPIFSGLDATLX = ((BYTE *)&gSrcAdd)[1];
NAND_ALE = 0;
NAND_CLE=1, P_XGPIFSGLDATLX=0x35, NAND_CLE=0;
nand_ready3(); // wait for tr
NAND_CLE=1,P_XGPIFSGLDATLX=0x85, NAND_CLE=0;
NAND_ALE = 1;
P_XGPIFSGLDATLX = 0; xSrcAdd++; P_XGPIFSGLDATLX = 0;
P_XGPIFSGLDATLX = ((BYTE *)&gPhyAdd)[3];
P_XGPIFSGLDATLX = ((BYTE *)&gPhyAdd)[2];
P_XGPIFSGLDATLX = ((BYTE *)&gPhyAdd)[1];
NAND_ALE = 0;
NAND_CLE=1, P_XGPIFSGLDATLX=0x10, NAND_CLE=0;
xPhyAdd++;
}
if (cnt) nCopyPages(cnt, 0);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -