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

📄 fmd.cpp

📁 Freescale ARM11系列CPU MX31的WINCE 5.0下的BSP
💻 CPP
📖 第 1 页 / 共 4 页
字号:
//     Furthemore, we see that this NOR Flash memory can map (504*256)==>129,024 
//     physical sectors.
// 
//     Note:
//     Unlike NAND, the sector meta info is groups together at the end of the
//     flash block,  
//     -------
// 
//     Two other points are worth mentioning:
// 
//         1) NOR Flash memory is guaranteed by manufacturing to ship with no bad Flash blocks.
//         2) NOR Flash memory doesn't suffer from electrical leakage currents (like NAND Flash) and
//            does not require error-correction codes (ECC) to insure data integrity.
// 
//   Environment:  
//     As noted, this media driver works on behalf of the FAL to directly
//     access the underlying FLASH hardware.  Consquently, this module 
//     needs to be linked with FAL.LIB to produce the device driver 
//     named FLASHDRV.DLL.
// 
// -----------------------------------------------------------------------------*/
// Function defines the virtual layout of logical sectors in flash given the
// flash geometry. 
//
// Parameters:
//          pGeometry
//          [in] pointer to flash geometry information
//
//          pLayout
//          [out] pointer to virtual layout infomation.
//
// Returns:  
//      None
//
//-----------------------------------------------------------------------------
static BOOL DefineLayout(BOOL bIsPaired, CFI_FLASH_GEOMETRY_INFO *pGeometry, NOR_FMD_FLASH_INFO *pInfo)
{
    ULONG FMDBase;
    ULONG FMDLength;
    ULONG FlashWalkAddr;
    ULONG EraseBlockSize;
    ULONG MaxEraseBlockSize;
    BOOL bFMDStartAligned;
    ULONG i;
    ULONG j;
    DWORD NumBlocks;
    ULONG LogicalBlockSize;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("DefineLayout+\r\n")));

    // Currently CE only supported sector size of 512.
    FMDBase = pInfo->BaseAddress + pInfo->FMDBaseOffset;
    FMDLength = pInfo->FlashLength - pInfo->FMDBaseOffset;
    DEBUGMSG(ZONE_FUNCTION, (TEXT("FMDBase 0x%08X FMDLength 0x%08X+\r\n"), FMDBase, FMDLength));

    // Get max block size and check FMD allocation is aligned.
    MaxEraseBlockSize = 0;
    FlashWalkAddr = pInfo->BaseAddress;
    bFMDStartAligned = FALSE;
    for(i = 0; i < pGeometry->NumEraseBlockRegions; i++)
    {
        EraseBlockSize = pGeometry->EraseBlockInfo[i].EraseBlockSize * CFI_ERASE_BLOCK_SIZE_MULTP;
        EraseBlockSize += bIsPaired? EraseBlockSize : 0;
        for(j = 0; j < (ULONG)(pGeometry->EraseBlockInfo[i].NumIdentEraseBlocks + 1); j++)
        {
            // Don't care sectors before FMD allocation
            if(FlashWalkAddr < FMDBase)
            {
                FlashWalkAddr += EraseBlockSize;
                continue;
            }
            
            // Check for FMD allocation start alignment with physical NOR sectors.
            // Shift FMD allocation if not aligned.
            if(bFMDStartAligned == FALSE)
            {
                if(FlashWalkAddr > FMDBase)
                {
                    // Align FMDBase to physical sector and adjust allocated 
                    // FMD flash accordingly.
                    DEBUGMSG(ZONE_INFO, (TEXT("INFO: 0x%08x not NOR sector aligned! Shifted to 0x%08x\r\n"),
                        FMDBase, FlashWalkAddr));
                    FMDLength -= (FlashWalkAddr - FMDBase);
                    FMDBase = FlashWalkAddr;
                }
                bFMDStartAligned = TRUE;
            }
            else
            {
                // Get max erase block size within FMD reserved region.
                MaxEraseBlockSize = MAX(MaxEraseBlockSize, EraseBlockSize);
            }

            // Increment walk address
            FlashWalkAddr += EraseBlockSize;
        }
    }
    DEBUGMSG(ZONE_INFO, (TEXT("INFO: MaxEraseBlockSize 0x%08x\r\n"), MaxEraseBlockSize));
    DEBUGMSG(ZONE_INFO, (TEXT("INFO: Sector aligned FMDBase 0x%08x FMDLength 0x%08x\r\n"), 
                        FMDBase, FMDLength));

    // Check for blocks of < max size and combine them if possible to get
    // uniform blocks.
    // Assumptions:
    // 1. Blocks that are less than the basis block size are grouped sequentially.
    // 2. Such a grouping of lesser blocks will amount to one basis block.
    // 3. Such groupings can only occur at the beginning or end of flash device
    FlashWalkAddr = pInfo->BaseAddress;
    NumBlocks = 0;
    LogicalBlockSize = 0;
    for(i = 0; i < pGeometry->NumEraseBlockRegions; i++)
    {
        EraseBlockSize = pGeometry->EraseBlockInfo[i].EraseBlockSize * CFI_ERASE_BLOCK_SIZE_MULTP;
        EraseBlockSize += bIsPaired? EraseBlockSize : 0;
        
        for(j = 0; j < (ULONG)(pGeometry->EraseBlockInfo[i].NumIdentEraseBlocks + 1); j++)
        {
            if(FlashWalkAddr >= FMDBase)
            {
                if(EraseBlockSize < MaxEraseBlockSize)
                {
                    // Combine all smaller blocks into single larger logical block
                    DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: EraseBlockSize 0x%08x CombineBlockSize 0x%08x\r\n"), 
                            EraseBlockSize, LogicalBlockSize));

                    LogicalBlockSize += EraseBlockSize;

                    if(LogicalBlockSize == MaxEraseBlockSize)
                    {
                        LogicalBlockSize = 0;
                        NumBlocks++;
                        DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: Combine blocks success! NumLogicalBlocks 0x%08X\r\n"), 
                                NumBlocks));
                    }
                }
                else
                {
                    // Trap combine blocks at start of flash error condition
                    if(LogicalBlockSize != 0 && LogicalBlockSize < MaxEraseBlockSize)
                    {
                        // Combination of blocks is insufficient to form a basis block!
                        // Shift the FMD allocation base in this case
                        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: unable to combine blocks! Shifted FMD start to 0x%08x\r\n"),
                            FlashWalkAddr));
                        FMDBase = FlashWalkAddr;
                        FMDLength -= LogicalBlockSize;
                        LogicalBlockSize = 0; 
                        NumBlocks = 0;
                    }
                    NumBlocks++;
                    DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: Found blocks %d FlashWalkAddr 0x%08X\r\n"), NumBlocks, FlashWalkAddr));
                    DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: i %d j %d\r\n"), i, j));
                }
            }
            DEBUGMSG(ZONE_FUNCTION, (TEXT("INFO: FlashWalkAddr 0x%08X\r\n"), FlashWalkAddr));
            FlashWalkAddr += EraseBlockSize;
        }
    }
    // Trap combine blocks at end of flash error condition
    if(LogicalBlockSize != 0 && LogicalBlockSize < MaxEraseBlockSize)
    {
        // Should never be here!
        ERRORMSG(ZONE_ERROR, (TEXT("ERROR: unable to combine blocks at flash end!\r\n")));
        return FALSE;
    }

    // Return values
    pInfo->FMDBaseOffset = FMDBase - pInfo->BaseAddress;
    pInfo->BytesPerSector = SECTOR_SIZE;
    if(!g_bXIPMode)
    {
        pInfo->SectorsPerBlock = (WORD)(MaxEraseBlockSize / (pInfo->BytesPerSector + sizeof(SectorInfo)));
        pInfo->SectorInfoOffset = SECTOR_SIZE * pInfo->SectorsPerBlock;
    }
    else
    {
        pInfo->SectorsPerBlock = (WORD)(MaxEraseBlockSize / pInfo->BytesPerSector);
        pInfo->SectorInfoOffset = 0;
    }
    pInfo->NumBlocks = NumBlocks;
    pInfo->EraseBlockSize = MaxEraseBlockSize;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("DefineLayout-\r\n")));
    return TRUE;
}

//-----------------------------------------------------------------------------
//
// Function: GetPhysicalSectorAddress
//
// Function returns the actual physical address for start of the sector passed in.
//
// Parameters:
//          dwSector
//          [in] sector number
//
//          pStartSectorAddr
//          [out] physical address.
//
// Returns:  
//      None
//
//-----------------------------------------------------------------------------
static void GetPhysicalSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("GetPhysicalSectorAddress+\r\n")));

    // Determine the block this sector resides in
    DWORD dwBlockID = dwSector / g_FMDInfo.SectorsPerBlock;
    DWORD dwSectorOffset = dwSector % g_FMDInfo.SectorsPerBlock;
    SECTOR_ADDR BlockAddr;
    
    BlockAddr = g_FMDInfo.BaseAddress + g_FMDInfo.FMDBaseOffset + (dwBlockID * g_FMDInfo.EraseBlockSize);
    *pStartSectorAddr = BlockAddr + (dwSectorOffset * g_FMDInfo.BytesPerSector);

    if(pStartSectorInfoAddr && !g_bXIPMode)
    {
        *pStartSectorInfoAddr = BlockAddr + g_FMDInfo.SectorInfoOffset + (dwSectorOffset * sizeof(SectorInfo));
    }
    DEBUGMSG(ZONE_FUNCTION, (TEXT("GetPhysicalSectorAddress-\r\n")));
}

//-----------------------------------------------------------------------------
//
// Function: GetMappedSectorAddress
//
// Function returns the mapped address for start of the sector passed in.
//
// Parameters:
//          dwSector
//          [in] sector number
//
//          pStartSectorAddr
//          [out] mapped sector address.
//
//          pStartSectorInfoAddr
//          [out] mapped sector info address.
//
// Returns:  
//      None
//
//-----------------------------------------------------------------------------
static void GetMappedSectorAddress(DWORD dwSector, PSECTOR_ADDR pStartSectorAddr, PSECTOR_ADDR pStartSectorInfoAddr)
{
    DEBUGMSG(ZONE_FUNCTION, (TEXT("GetMappedSectorAddress+, 0x%08X\r\n"), dwSector));

    // Determine the block this sector resides in
    DWORD dwBlockID = dwSector / g_FMDInfo.SectorsPerBlock;
    DWORD dwSectorOffset = dwSector % g_FMDInfo.SectorsPerBlock;
    SECTOR_ADDR BlockAddr;
    
    DEBUGMSG(ZONE_FUNCTION, (TEXT("dwBlockID 0x%08X dwSectorOffset 0x%08X\r\n"), 
                            dwBlockID, dwSectorOffset));

    BlockAddr = (ULONG)g_pNORFlashBase + g_FMDInfo.FMDBaseOffset + (dwBlockID * g_FMDInfo.EraseBlockSize);
    *pStartSectorAddr = BlockAddr + (dwSectorOffset * g_FMDInfo.BytesPerSector);

    if(pStartSectorInfoAddr && !g_bXIPMode)
    {
        *pStartSectorInfoAddr = BlockAddr + g_FMDInfo.SectorInfoOffset + (dwSectorOffset * sizeof(SectorInfo));
    }
    DEBUGMSG(ZONE_FUNCTION, (TEXT("GetMappedSectorAddress-\r\n")));
}

//-----------------------------------------------------------------------------
//
// Function: SetBlockLock
//
// Function locks given number of blocks.
//
// Parameters:
//          blockID
//          [in] start block ID
//
//          NumBlocks
//          [in] number of blocks to lock.
//
//          bLock
//          [in] TRUE to lock blocks
//
// Returns:  
//      FALSE on failure
//
//-----------------------------------------------------------------------------
static BOOL SetBlockLock(BLOCK_ID blockID, ULONG NumBlocks, BOOL bLock)
{
    ULONG ulBlockAddress = 0;

    DEBUGMSG(ZONE_FUNCTION, (TEXT("SetBlockLock+\r\n")));
    while(NumBlocks--)
    {
        // Compute the block address.
        ulBlockAddress  =  (ULONG)g_pNORFlashBase + g_FMDInfo.FMDBaseOffset + (blockID * g_FMDInfo.EraseBlockSize);

        if(bLock)
        {
            if(!NORLockSector(ulBlockAddress))
            {
        	    ERRORMSG(ZONE_ERROR, (TEXT("ERROR: Cannot lock block 0x%08X\r\n"), ulBlockAddress));
                return FALSE;
            }
        }
        else
        {
            if(!NORUnlockSector(ulBlockAddress))
            {
        	    ERRORMSG(ZONE_ERROR, (TEXT("ERROR: Cannot unlock block 0x%08X\r\n"), ulBlockAddress));
                return FALSE;
            }
        }
    }

    DEBUGMSG(ZONE_FUNCTION, (TEXT("SetBlockLock-\r\n")));
    return TRUE;
}

//-----------------------------------------------------------------------------
// END OF FILE
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

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