fmd.cpp

来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,511 行 · 第 1/4 页

CPP
1,511
字号
    pBaseAddress = (ULONG)NAND_DATA_PORT;	

    FlashLength  = 0x2000000;

    // Run in kernel mode.
    bLastMode = SetKMode(TRUE);

	*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_RESET; 
//	Sleep(1);    // check ready
/////	mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 1000);
//	Sleep(1);
	mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 1000);
	
    // Identify the flash part and collect device information.
    //


    SetKMode(bLastMode);
    return ((PVOID)(pBaseAddress));
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_Deinit()

Description:    De-initializes the Flash memory device.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_Deinit(PVOID pBaseAddress)
{
    return(TRUE);
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_GetInfo()

Description:    Determines the size characteristics for the Flash memory device.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.
                To compute the number of sectors per block, you have to divide the
                total Flash block size by the number of bytes per sector and the number 
                bytes for the sector metadata.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_GetInfo(PFlashInfo pFlashInfo)
{
    pFlashInfo->flashType           = NAND;
//wzw test
    pFlashInfo->dwNumBlocks         = 8192;//	2048;	//512;	//	8192;//wzw size
//  pFlashInfo->dwNumBlocks         = 200;

    pFlashInfo->dwBytesPerBlock     = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
    pFlashInfo->wDataBytesPerSector = 2048 ;
    pFlashInfo->wSectorsPerBlock    = 64 ;  

    return(TRUE);
}


/* 
 *  NAND_ReadSectorInfo
 *
 *  Read SectorInfo out of the spare area. The current implementation only handles
 *  one sector at a time.
 */
void NAND_ReadSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo)
{
    UCHAR  addr1, addr2, addr3, wData,TEMP;

    addr1 = (UCHAR) ((sectorAddr) & 0xff);
    addr2 = (UCHAR) ((sectorAddr>> 8) & 0xff);
    addr3 = (UCHAR) ((sectorAddr>> 16) & 0xff);

   
    //  Issue Read command, reading from the spare bits
	*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_READ;
	*((volatile ULONG *)(NAND_ADDR_PORT ))=0x00; 
	*((volatile ULONG *)(NAND_ADDR_PORT ))=0x08; 
	*((volatile ULONG *)(NAND_ADDR_PORT ))=(addr1); 
	*((volatile ULONG *)(NAND_ADDR_PORT ))=(addr2); 
	*((volatile ULONG *)(NAND_ADDR_PORT ))=addr3;
         
	*((volatile ULONG *)(NAND_CMD_PORT ))=0x30;
   	//*((volatile ULONG *)(NAND_ADDR_PORT ))=(addr3)&0xff; 
// 	usWait(20);//wzw
	mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 20);
//	Sleep(1);
//	mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 1000);
	
   	//Sleep(1);    // check ready
    //  Read the SectorInfo data (we only need to read first 8 bytes) 
    //  NOTE: The bytes are swapped because of Little Endian.
   	wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));              // Bad block byte
	pInfo->bBadBlock    = (wData);
	
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));               // First reserved field (DWORD)
    pInfo->dwReserved1   = (wData);
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT))); 
    pInfo->dwReserved1  |= (wData << 8);
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT))); 
    pInfo->dwReserved1  |= (wData << 16);
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT))); 
    pInfo->dwReserved1  |= (wData<<24);
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));               // OEM byte
	pInfo->bOEMReserved = (wData);
    
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));              // Second reserved field (WORD)
	pInfo->wReserved2   = (wData );
    wData = (UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));              
	pInfo->wReserved2  |= (wData << 8);  
   
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_ReadSector()

Description:    Reads the requested sector data and/or sector metadata from the
                Flash media.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.  
                Thus, for each sector request, we must determine where this data
                resides in the respective Flash block (see note above).

                By default, the NOR Flash is configured in READ ARRAY MODE so there
                is no need to set any control lines to access the media.  The data
                can just be read directly from the media (like RAM).
                
Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL  FMD_ReadSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    UCHAR  addr1, addr2, addr3, wData;
    DWORD   i,count;
	BOOL bLastMode;

//	ULONG startSectorAddr;//++	

   *((volatile ULONG *)(NAND_CMD_PORT ))=CMD_RESET; 
    //----- 1. Check the input parameters -----
    //         NOTE: The FAL insures that the starting sector address is in the allowable range.
    /*if((dwNumSectors == 0) || ((pSectorBuff == NULL) && (pSectorInfoBuff == NULL)))
    {
        return(FALSE);
    }*/

	if (!pSectorBuff && !pSectorInfoBuff || dwNumSectors > 1) {
        //RETAILMSG(1, (TEXT("Invalid parameters!\n")));
        return FALSE;
    }
	
    //----- 2. Process the read request(s)... -----
    bLastMode = SetKMode(TRUE);
	// SetWriteProtect(FALSE);

    *((volatile ULONG *)(NAND_CMD_PORT ))=CMD_READ;
	//Sleep(1);
    for(i = 0; i < dwNumSectors; i++)
    {
      	// Sleep(1);    // check ready
       	if(!pSectorBuff) {
            //  We are reading spare only
           	// RETAILMSG(1, (TEXT("FMD_ReadSector1!\r\n")));
            NAND_ReadSectorInfo(startSectorAddr, pSectorInfoBuff);
            pSectorInfoBuff ++;

        }
	   	else{
		   	//  Reading data from the flash
            addr1 = (UCHAR) ((startSectorAddr) & 0xff);
            addr2 = (UCHAR) ((startSectorAddr>> 8) & 0xff);
            addr3 = (UCHAR) ((startSectorAddr>> 16) & 0xff);

            //  Issue Read command 
	     	*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_READ;
            *((volatile ULONG *)(NAND_ADDR_PORT ))=0x00; 
	     	*((volatile ULONG *)(NAND_ADDR_PORT ))=0x00;
            *((volatile ULONG *)(NAND_ADDR_PORT ))=addr1; 
            *((volatile ULONG *)(NAND_ADDR_PORT ))=addr2; 
			*((volatile ULONG *)(NAND_ADDR_PORT ))=addr3;
			*((volatile ULONG *)(NAND_CMD_PORT ))=0x30;
//			usWait(20);//wzw
			mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 20);
//	Sleep(1);
//		mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 1000);
		
	    	//Sleep(1);    // check ready
	     	//  Read only data portion of the sector.
            for(i=0; i<0x800; i++)
            {            
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));
                // Copy the bytes directly into pSectorBuff
                pSectorBuff[i] = wData;
            }

           
			
			// Read the SectorInfo data (we only need to read first 8 bytes) 
            // Read the SectorInfo data
			if(pSectorInfoBuff)
            {
               	wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));               // Bad block byte
                pSectorInfoBuff->bBadBlock    = (wData);
	
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));              // First reserved field (DWORD)
                pSectorInfoBuff->dwReserved1  = (wData);
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));               
                pSectorInfoBuff->dwReserved1  |= (wData << 8);
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));               
                pSectorInfoBuff->dwReserved1  |= (wData << 16);
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));             
                pSectorInfoBuff->dwReserved1  |= (wData << 24);

                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));              // OEM byte
                pSectorInfoBuff->bOEMReserved = (wData);
                

                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));              // Second reserved field (WORD)
                pSectorInfoBuff->wReserved2  = (wData);
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));            
                pSectorInfoBuff->wReserved2   |= (wData << 8);
   
                pSectorInfoBuff ++;
            }else
            {
                // Make sure we advance the Flash's read pointer (even though we don't need the SectorInfo data).
                for(i=0; i<sizeof(SectorInfo); i++)
                {
                   wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));
                }
            }
	      	// Read the ECC info
            for(i=0; i<8; i++)
            {
                wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));
            
                //  Read out the ECC bits saved  
                ECC[i]   = wData;
            }

           //  Test the data integrity; if the data is invalid, attempt to fix it using ECC
            if(!ECC_IsDataValid(pSectorBuff, 2048, ECC, 24))
            {
                RETAILMSG(1, (TEXT("FMD: Sector data (sector 0x%x) is invalid.  Attempting ECC to fix it.\n"), startSectorAddr));
                if(!ECC_CorrectData(pSectorBuff, 2048, ECC, 24))
                {
                    // NOTE: this is specifically a debug message because sometimes it's valid to try to read from a sector in a good
                    // block which might contain bogus data (ECC fails) - example: loader code that needs to save/restore non-block-aligned
                    // data and we don't want a bunch of warnings in a retail build.
                    RETAILMSG(1, (TEXT("FMD: ERROR - Sector data (sector 0x%x) Unable to correct invalid data!\r\n"),startSectorAddr));
                    
                   // return FALSE;

                }else{
                     RETAILMSG(1, (TEXT("FMD: Invalid data was corrected using ECC!\r\n")));
                }
            }
		pSectorBuff +=2048;
	   	}

       startSectorAddr ++;
    }
    
    SetKMode(bLastMode);
    return(TRUE);
}



/* 
 *  NAND_WriteSectorInfo
 *
 *  Write SectorInfo out to the spare area. The current implementation only handles
 *  one sector at a time.
 */
BOOL NAND_WriteSectorInfo(SECTOR_ADDR sectorAddr, PSectorInfo pInfo)
{
    UCHAR  addr1, addr2, addr3, wData,status;
	

    addr1 = (UCHAR) ((sectorAddr) & 0xff);
    addr2 = (UCHAR) ((sectorAddr>> 8) & 0xff);
    addr3 = (UCHAR) ((sectorAddr>> 16) & 0xff);

 
   	// *((volatile UCHAR *)(NAND_CMD_PORT ))=CMD_READ2;
	//Sleep(1);    // check ready
   	*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_WRITE;
   	*((volatile ULONG *)(NAND_ADDR_PORT ))=0x00; 
   	*((volatile ULONG *)(NAND_ADDR_PORT ))=0x08;
   	*((volatile ULONG *)(NAND_ADDR_PORT ))=addr1; 
   	*((volatile ULONG *)(NAND_ADDR_PORT ))=addr2; 
	*((volatile ULONG *)(NAND_ADDR_PORT ))=addr3;
        
  	//Sleep(1);    // check ready

    //  Since there is not any ECC information, we only need to write the SectorInfo data
	*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)(pInfo->bBadBlock);                        // Bad block byte
	*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pInfo->dwReserved1 & 0x000000FF)); // Reserved field 1 
	*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pInfo->dwReserved1 & 0x0000FF00) >> 8); 
	*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pInfo->dwReserved1 & 0x00FF0000) >> 16);
	*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pInfo->dwReserved1 & 0xFF000000) >> 24);   

    *((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)(pInfo->bOEMReserved);                        // OEM byte
    *((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pInfo->wReserved2 & 0x00FF)); // Reserved field 2
    *((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pInfo->wReserved2 & 0xFF00) >> 8);          

    // Instruct the Flash to commit the data to the media
    *((volatile ULONG *)(NAND_CMD_PORT ))=CMD_WRITE2;

    //  Check the status
    status = GetStatus((DWORD) -1);

    if(status & STATUS_ERROR) {
        RETAILMSG(1, (TEXT("######## Error Programing page %d!\n"), sectorAddr));
        //FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1);    // disable chip
        return FALSE;
    }
//RETAILMSG(1, (TEXT("NAND_WriteSectorInfo dwReserved1 is %x bOEMReserved is %x bBadBlock is %x wReserved2 is %x\r\n"),pInfo->dwReserved1,pInfo->bOEMReserved,pInfo->bBadBlock,pInfo->wReserved2));
   
    return TRUE;
}


/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function:       FMD_WriteSector()

Description:    Writes the requested sector data and/or sector metadata to the
                Flash media.

Notes:          Notice that although each byte of a NOR Flash block is individually
                addressable, the media is still logically broken up into sectors.
                Thus, for each sector request, we must determine where to put the
                data in each respective Flash block (see note above).

                By default, the NOR Flash is configured in READ ARRAY MODE we need
                to set some control lines to prepare for the WRITE operation.

Returns:        Boolean indicating success.
------------------------------------------------------------------------------*/

BOOL  FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)
{
    DWORD   i,count;
	UCHAR  addr1, addr2, addr3, wData,status;
	
	 BOOL bLastMode = SetKMode(TRUE);

    //----- 1. Check the input parameters -----
    //         NOTE: The FAL insures that the starting sector address is in the allowable range.
    if((!pSectorBuff && !pSectorInfoBuff) || dwNumSectors == 0) {
        RETAILMSG(1, (TEXT("Invalid parameters!\n")));
        return FALSE;
    }

       
    //----- 2. Process the write request(s)... -----

    bLastMode = SetKMode(TRUE);
	//*((volatile UCHAR *)(NAND_CMD_PORT ))=CMD_READ;
   
    for(i = 0; i < dwNumSectors; i++)
    {  	
    	//Sleep(1);    // check ready
		if(!pSectorBuff) {
			//  If we are asked just to write the SectorInfo, we will do that separately
			if(!NAND_WriteSectorInfo(startSectorAddr, pSectorInfoBuff)) {
                return FALSE;
            }
            pSectorInfoBuff ++;
        }
		else{
	   		//  Reading data from the flash

⌨️ 快捷键说明

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