⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inand.c

📁 CY7C68033芯片 USB DEVICE 代码;标准c代码
💻 C
📖 第 1 页 / 共 3 页
字号:
    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;    
    P_INPKTEND   = 0x84;          // skip 16-byte of the redundant data
}

//==========================================================================
//  Check ECC, if fail, return bErr=1
//  Should call CorrectData if more than ECC 2bit error, the b2BitErr will 
//  be set.
//  Modify:
//     bCnt = 0 will terminate the while loop
//     bErr = 1 will send STALL to USB Host
//==========================================================================
void CheckECC()
{
     if   ( (ecc0[0] != ecc1[0]) || (ecc0[1] != ecc1[1]) || (ecc0[2] != ecc1[2]) ||
            (ecc0[3] != ecc1[3]) || (ecc0[4] != ecc1[4]) || (ecc0[5] != ecc1[5]) )
     {
         bErr = 1; bCnt = 0; // Will stall in the Status phase
     }
}

//==========================================================================
// Get Physical block from LUT
// return gCurZone    = (dwLBA/PageSize)/cMaxLogical
//                    = (dwLBA/PageSize) % cMaxLogical
//        gPhyAdd     = Physical block
//        gSrcAdd     = Physical Source Address for Write
//==========================================================================
void Log2Phy()
{
    BYTE page, zz, z;
    WORD wi, wTmp;
#ifdef NAND_2K
    if (bErr) return;    
    page    = xLBA3;                           // 2K: pagesize = 256
    ((BYTE *)&gDst)[0] = ((BYTE *)&dwLBA)[1];  // MSB: gDst = (WORD)(dwLBA>>16);
    ((BYTE *)&gDst)[1] = ((BYTE *)&dwLBA)[2];  // LSB:  Dst = 2K Block number   
    z = 0;
    while (gDst >= cMaxLogical) { gDst -= cMaxLogical; z++; }  // z = gDst/cMaxLogical
  
    zz  = z & (gZones-1);
    z   /= gZones;                     // z = number of NAND bank
#ifdef USE_2NAND
    if (z==0) CE0_ON(), CE1_OFF(); else CE1_ON(), CE0_OFF();
#else
    gEnableBanks = IOD = nBank[z];     // enable banks
#endif
    if ((gBank != z) || (zz != gCurZone))     // need to reload when bank switch
    { 
        gBank    = z;                 // update bank
        gCurZone = zz;                // update zone
        //=================================================================
        // BuildTable(); 
        // This function build the LUT for Logical to Physical translation
        // need gCurZone
        //=================================================================
        memset16((xbyte*)gLog2Phy, MSB(cBLK_INIT), (cMaxBlock*2)/16);
        ((BYTE *)&gPhyAdd)[3] = 0;
        ((BYTE *)&gPhyAdd)[2] = 0;                  // optimize for speed
        ((BYTE *)&gPhyAdd)[1] = gCurZone;           // gPhyAdd <<= 16;

        for (wi=0; wi<cMaxBlock; wi++)
        {   // read the redundant section of the page into EP6
            xbyte *p = &gLog2Phy[wi];             // get address pointer
            NandSetAdd(cNAND_READ_DATA, 4); 
            Fifo6In();
            NandRead(cEP6, cNAND_RSIZ);
            bFreeBlk = (EP6FIFOBUF[0] == 0xff) && (EP6FIFOBUF[1] == 0xff);
            if (!bFreeBlk)
                *p |= MSB(cBLK_CFG);  // special block or bad block
            else
            {
                ((BYTE *)&wTmp)[0] = EP6FIFOBUF[cAddOffset];     // MSB address1
                // check if the block is not free
                if (((BYTE *)&wTmp)[0] != 0xff) 
                {
                    ((BYTE *)&wTmp)[1] = EP6FIFOBUF[cAddOffset+1];   // LSB address1
                    if ( (((BYTE *)&wTmp)[0] == EP6FIFOBUF[cAddOffset+2]) &&   // check if both addresses are matched
                         (((BYTE *)&wTmp)[1] == EP6FIFOBUF[cAddOffset+3]) )
                    {
                        xword *pTmp = &gLog2Phy[wTmp];
                        wTmp = *pTmp;
                        if (wTmp & cBLK_INIT)                   // multiple blocks map check
                        {   *pTmp =  ( wTmp & cBLK_uMSK ) | wi; // store the remap block                    
                            *p    |= MSB(cBLK_USE);             // Set Block Use
                        }
                        else
                        {
                            nand_blk_erase(gPhyAdd); 
                            *(xbyte*)0xe100 = 0xee;
                        }
                    }
                }  // else this block is free
            }
            gPhyAdd += c2KPageSize;  // next block for 2K NAND
        } // for wi
        bFreeFound = 0;               // cross the Zone, reset the Free Block Found
    } // update table again
    wTmp  = zz << cMaxBlock2N;        // compute Zone 
    pDst  = gLog2Phy + gDst;          // pDst = &gLog2Phy[gDst]
    gSrc  = *pDst & cBLK_aMSK;        // gLog2Phy[gDst]: Get Physical block
    if (directionIn)                  // read just get the table
    {
        wTmp |= gSrc;    
        ((BYTE *)&gPhyAdd)[3] = ( ((BYTE *)&wTmp)[1] << 6 ) | (page>>2);
        ((BYTE *)&gPhyAdd)[2] = ( ((BYTE *)&wTmp)[1] >> 2 ) | ( ((BYTE *)&wTmp)[0] << 6 );
        ((BYTE *)&gPhyAdd)[1] = ( ((BYTE *)&wTmp)[0] >> 2 );
        NandSetAdd(cNAND_READ_DATA, (page&3));
    }
    else
    {
        xbyte  *p;
        nGetFreeBlk();                                // get Free Block
        wi = gFreeBlk;
        if (gSrc&cBLK_INIT) gSrc=wi;                  // default value set to free block
        bNeedErase = (wi != gSrc);                    // don't erase if Src = Dst && block free

        // *(xbyte*)&gLog2Phy[gSrc] &=  MSB(~cBLK_USE);  // set this block free
        p = (xbyte*)&gLog2Phy[gSrc];                  // point to the SRC block
        // July-07-05 Free Block must exclude CFG block as well
        bFreeBlk = !(*p & MSB(cBLK_uMSK));             // free block 
        *p = *p & MSB(~cBLK_USE);                      // set this block free
        
        *(xbyte*)&gLog2Phy[wi]   |=  MSB(cBLK_USE);   // Set this block is used        
        *pDst = (*pDst & cBLK_uMSK) | wi;             // update Logical address

        wi |= wTmp;    
        ((BYTE *)&gPhyAdd)[3] = ( ((BYTE *)&wi)[1] << 6 );
        ((BYTE *)&gPhyAdd)[2] = ( ((BYTE *)&wi)[1] >> 2 ) | ( ((BYTE *)&wi)[0] << 6 );
        ((BYTE *)&gPhyAdd)[1] = ( ((BYTE *)&wi)[0] >> 2 );

        wTmp |= gSrc;    
        gSrcBlk0 = ((BYTE *)&gSrcAdd)[3] = ( ((BYTE *)&wTmp)[1] << 6 );
        ((BYTE *)&gSrcAdd)[2] = ( ((BYTE *)&wTmp)[1] >> 2 ) | ( ((BYTE *)&wTmp)[0] << 6 );
        ((BYTE *)&gSrcAdd)[1] = ( ((BYTE *)&wTmp)[0] >> 2 );
        if (page) NAND_PCPY(page, 0);
    }
#else
    BYTE npage;

    if (bErr) return;    
    gSrc    = (WORD)dwLBA; 
    ((BYTE *)&gDst)[0] = ((BYTE *)&dwLBA)[0];  // MSB: gDst = (WORD)(dwLBA>>16);
    ((BYTE *)&gDst)[1] = ((BYTE *)&dwLBA)[1];  // LSB 
    if (bInterLeave)
    {    
        page = xLBA3 & cInterLeaveMsk;      
        npage = page>>1;                       // remove bit0 for interleave
        gDst <<= 16-(c512PageSize2N+1);        // dwLBA >>= c512PageSize2N+1
        gSrc >>= c512PageSize2N+1;
    }
    else
    {
        npage = page = xLBA3 & (c512PageSize-1); // mask page 5-bits 0x1F
        gDst <<= 16-c512PageSize2N;              // dwLBA >>= c512PageSize2N
        gSrc >>= c512PageSize2N;
    }   
    gDst |= gSrc;                                // gDst = dwLBA/c512PageSize

    z = 0;
    while (gDst >= cMaxLogical) { gDst -= cMaxLogical; z++; }  // z = gDst/cMaxLogical   
    zz  =  z & (gZones-1);    // zz = zone numbers within a NAND
    z   /= gZones;            // gZones=8=8192, gZones=4=4096

#ifdef USE_2NAND
    CE0_ON(),CE1_ON();       // enable both NAND chip select
#else
    gEnableBanks = IOD = aBanks[z];  // pre-load fast variables
#endif
  
    //  Reload the LUT when cross bank and zone
    if ( zz != gCurZone || z != gBank)
    { 
#ifndef USE_2NAND
        gEnableBank0 = aBank0[z];        // pre-load fast variables
        gEnableBank1 = aBank1[z];        // pre-load fast variables
#endif
        gBank    = z;                    // update bank
        gCurZone = zz;
        // 1K Zone
        // gPhyAdd  = ((DWORD)gCurZone << (cMaxBlock2N+c512PageSize2N));   // Get Page address
        ((BYTE *)&gPhyAdd)[3] = 0;
        ((BYTE *)&gPhyAdd)[2] = gCurZone<<7; 
        ((BYTE *)&gPhyAdd)[1] = gCurZone>>1;

        // 2K Zone
        //((BYTE *)&gPhyAdd)[3] = 0;
        //((BYTE *)&gPhyAdd)[2] = 0;                                        // optimize for speed
        //((BYTE *)&gPhyAdd)[1] = gCurZone;

        //==========================================================================
        // This function build the LUT for Logical to Physical translation
        // need gCurZone
        //==========================================================================

        memset16((xbyte*)gLog2Phy, MSB(cBLK_INIT), (cMaxBlock*2)/16);
        for (wi=0; wi<cMaxBlock; wi++)
        {   // read the redundant section of the page into EP6           
            NandSetAdd(cNAND_READ_REDUNDANT, 0); 
            for (z=0; z <3; z++) // retry 3 times
            {
                xbyte *p = &gLog2Phy[wi];             // get address pointer
                // for InterLeave case
                // if either block in bank0 or bank1 is bad, will mark both blocks bad
                if (bInterLeave) bank_select(cBank0);  // check bank0                
                Fifo6In();
                NandRead(cEP6, 16);
                bFreeBlk = (EP6FIFOBUF[0] == 0xff) && (EP6FIFOBUF[1] == 0xff);
                if (bInterLeave)                       // check bank1
                { 
                    bank_select(cBank1);
                    NandRead(cEP6, 16);
                    if (EP6FIFOBUF[16] != 0xff || EP6FIFOBUF[17] != 0xff) bFreeBlk = 0;
                }
                if (!bFreeBlk) 
                {
                    *p |= MSB(cBLK_CFG);  // special block or bad block
                    break;
                }
                else
                {
                    ((BYTE *)&wTmp)[0] = EP6FIFOBUF[cAddOffset];     // MSB address1
                    if  (((BYTE *)&wTmp)[0]==0xff) break;            // free block
                    ((BYTE *)&wTmp)[1] = EP6FIFOBUF[cAddOffset+1];   // LSB address1

                    if ( (((BYTE *)&wTmp)[0] == EP6FIFOBUF[cAddOffset+2]) &&   // check if both addresses are matched
                         (((BYTE *)&wTmp)[1] == EP6FIFOBUF[cAddOffset+3]) )
                    {
                        xword *pTmp = &gLog2Phy[wTmp];
                        wTmp = *pTmp;
                        if (wTmp & cBLK_INIT)                   // multiple blocks map check
                        {
                            *pTmp =  ( wTmp & cBLK_uMSK ) | wi; // store the remap block                    
                            *p    |= MSB(cBLK_USE);             // Set Block Use
                        }
                        else
                        {
                            NandSendCmd(cNAND_RESET);           // fix the multiple blocks case
                            nand_blk_erase(gPhyAdd); 
                        }
                        break;
                    }
                }
                if (z == 2) *p |= MSB(cBLK_BAD);
            }
            gPhyAdd += c512PageSize;  // next block
        } // for gi
        bank_default();               // set default
        NandSendCmd(cNAND_RESET);     // must reset afer REDUNDANT read
        bFreeFound = 0;               // cross the Zone, reset the Free Block Found
    } // update table again

    wTmp  = zz << cMaxBlock2N;        // compute Zone 
    pDst  = gLog2Phy + gDst;          // pDst = &gLog2Phy[gDst]
    gSrc  = *pDst & cBLK_aMSK;        // gLog2Phy[gDst]: Get Physical block
    if (directionIn)                  // Host Read data
    {
        wTmp |= gSrc;    
        nand_ready3();
        NAND_CLE  = 1;
        P_XGPIFSGLDATLX = cNAND_READ_DATA;
        NAND_CLE  = 0; 
        NAND_ALE  = 1;
        P_XGPIFSGLDATLX = 0;     
        P_XGPIFSGLDATLX = ( ((BYTE *)&wTmp)[1] << 5 ) | npage;
        P_XGPIFSGLDATLX = ( ((BYTE *)&wTmp)[1] >> 3 ) | ( ((BYTE *)&wTmp)[0] << 5 );
        P_XGPIFSGLDATLX = ( ((BYTE *)&wTmp)[0] >> 3 );
        NAND_ALE  = 0;              
        Fifo6In();
        if (bInterLeave) ready_ignore(); 
        nand_ready3();       
    }
    else
    {   
        nGetFreeBlk();                                // get Free Block
        wi = gFreeBlk;
        if (gSrc&cBLK_INIT) gSrc=wi;                  // default value set to free block
        bNeedErase = (wi != gSrc);                    // don't erase if Src = Dst && block free
        *(xbyte*)&gLog2Phy[gSrc] &=  MSB(~cBLK_USE);  // set this block free
        *(xbyte*)&gLog2Phy[wi]   |=  MSB(cBLK_USE);   // Set this block is used        
        *pDst = (*pDst & cBLK_uMSK) | wi;             // update Logical address
 
        wi |= wTmp;    
        //gPhyAdd = ((DWORD)(wTmp | wi) << c512PageSize2N);
        ((BYTE *)&gPhyAdd)[3] = ( ((BYTE *)&wi)[1] << 5 );
        ((BYTE *)&gPhyAdd)[2] = ( ((BYTE *)&wi)[1] >> 3 ) | ( ((BYTE *)&wi)[0] << 5 );
        ((BYTE *)&gPhyAdd)[1] = ( ((BYTE *)&wi)[0] >> 3 );
        //gSrcAdd = ((DWORD)(wTmp | gSrc) << c512PageSize2N);
        wTmp |= gSrc;    
        gSrcBlk0 = ((BYTE *)&gSrcAdd)[3] = ( ((BYTE *)&wTmp)[1] << 5 );
        ((BYTE *)&gSrcAdd)[2] = ( ((BYTE *)&wTmp)[1] >> 3 ) | ( ((BYTE *)&wTmp)[0] << 5 );
        ((BYTE *)&gSrcAdd)[1] = ( ((BYTE *)&wTmp)[0] >> 3 );
        // check for head copy here
        if (page) nCopyPages(page, 0);
    }
#endif
    DBUG_DUMP();
}

//==========================================================================
// Nand Copy Pages:
//   always perform ECC correction for SOFT error.
//   If more than 2-bit error, return b2BitErr will be set
//==========================================================================
void nCopyPages(BYTE cnt, BYTE cc)
{
#ifdef NAND_2K
    BYTE msk=cc&3;   
    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)
        n2k_radd(gSrcAdd, msk);
        GPIFTRIG = 0x04 | cEP6;                       // Arm EP6
        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]; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -