fmdhal.c

来自「该BSP是基于PXA270+WINCE的BSP」· C语言 代码 · 共 683 行 · 第 1/2 页

C
683
字号
            /* Disable interrupts again */
            g_RelocFuncStruct.FMDHAL_ASMInterruptDisable();

            g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_STATUS, g_FMDConfig);
            if (!g_RelocFuncStruct.ReadStatus(pBlockAddress, FMDHAL_FLASH_ERASE_SUSPENDED, g_FMDConfig))
            {
                /* in case Vcc low or dropped during suspend. Erase suspend will not resume. */
                g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
                g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
                g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
                return(FALSE);
            } else
            {
                /*                Specs recommend to Clear-Status before
                 *                Erase-Resume to avoid errors in other operation
                 *                still there before the Resume
                 */
                g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
                g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_ERASE_RESUME, g_FMDConfig);
            }

            /* put the flash into Status mode */
            g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_STATUS, g_FMDConfig);

        }
    }
#endif

    /* Check for Errors */
    flash_status = g_RelocFuncStruct.ReadStatus(pBlockAddress, 0, g_FMDConfig);
    if (flash_status & ~mFMDHAL_CmdCreate(g_FMDConfig, FMDHAL_FLASH_STATUS_READY))
    {
        // clear status here might be back for the top of the FMD to find out what went wrong
        g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
        g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
        if (g_SWRWW_Enable)
        {
            g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
        }
        return(FALSE);
    }

    /* Put the flash back into Read Array mode */
    g_RelocFuncStruct.WriteCommand(pBlockAddress, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
    }

    return(TRUE);
}



BOOL FMDHAL_WriteCommand(volatile ULONG* pBaseAddress, ULONG uCmd, ULONG uConfig)
{
    //    if (uConfig & FMDHAL_BusConfigx16)
    //    {
    //        *(volatile UINT16 *)pBaseAddress = mFMDHAL_CmdCreate(uConfig, uCmd);
    //    } else
    //    {
    *(volatile UINT32 *)pBaseAddress = mFMDHAL_CmdCreate(uConfig, uCmd);
    //    }
    return(TRUE);
}


BOOL FMDHAL_ReadStatus(volatile ULONG* pBaseAddress, ULONG uMask, ULONG uConfig)
{
        unsigned long status, mask;
    status = mFMDHAL_ReadFlash(uConfig, pBaseAddress);
    last_status = status;

    if (uMask == 0)
        return(status);
    else
        {
        mask = mFMDHAL_CmdCreate(uConfig, uMask);
        return((status & mask) == mask);
        }
}


BOOL FMDHAL_IsInterruptPending(void)
{
    /* A '1' in any of the bits in the following
       registers is considered a pending intr */
    /*    if (g_pIRQ_Address->icip && !g_pIRQ_Address->icfp)
        {
            return(g_pIRQ_Address->icip || g_pIRQ_Address->icfp);
        } else if (g_pIRQ_Address->icip && g_pIRQ_Address->icfp)
        {
            return(g_pIRQ_Address->icip);
        } else
        {
            return(FALSE);
        }
    */
    return(FALSE);
}


BOOL FMDHAL_CFIQuery(void)
{
    ULONG *pBaseAddress = g_CurrCmdStruct.pTargetAddress;
    BOOL bPairedFlash = TRUE;
    BOOL g_bPairedFlash = TRUE; // To Make the Macros work, please fix cnc
    UINT nCount;
    volatile ULONG output;
    ULONG iteration =0, working_val =0, temp_val =0;

    //fill the structure
    g_CFIInfo.ParameterLocation         = BOTTOM_BOOT;
    g_CFIInfo.StartSmallBlockAddress    = g_CFIInfo.ActualFlashBase;

    if (g_FMDConfig & FMDHAL_BusConfigx16)
    {
        bPairedFlash = FALSE;
        g_bPairedFlash = FALSE;
    }

    if (g_SWRWW_Enable)
    {
        //FMDHAL_ASMInterruptDisable();
        g_RelocFuncStruct.FMDHAL_ASMInterruptDisable();
    }

    g_RelocFuncStruct.WriteCommand(pBaseAddress, READ_QUERY_CMD, g_FMDConfig);

    if (!CHECK_STATUS_INDEXED(pBaseAddress, QS_IDSTRING_OFFSET,  IDSTRING_Q) ||
        !CHECK_STATUS_INDEXED(pBaseAddress, QS_IDSTRING_OFFSET + 1, IDSTRING_R) ||
        !CHECK_STATUS_INDEXED(pBaseAddress, QS_IDSTRING_OFFSET + 2, IDSTRING_Y))
    {
        // This flash doesn't support CFI, so it's not a Strataflash.
        DEBUGMSG(1, (TEXT("ERROR: InitializeFlash: didn't find StrataFlash CFI.\r\n")));
        return(FALSE);
    }

    // We're pretty sure this is an Intel Strataflash part at this point - use the CFI to
    // collect information on it (we're still in query mode).  Also, we'll assume that both
    // high and low word flash parts are the same from here on out (if paired).
    //
    for (nCount = 0 ; nCount < sizeof(FLASH_SYSINTERFACE_INFO) ; nCount++)
    {
        *((PUCHAR)&g_CFIInfo.SysInt + nCount) = (UCHAR)(READ_FLASH_INDEXED(pBaseAddress, QS_SYSINTF_OFFSET + nCount) & 0xFF);
    }
    for (nCount = 0 ; nCount < sizeof(FLASH_GEOMETRY_INFO) ; nCount++)
    {
        *((PUCHAR)&g_CFIInfo.Geometry + nCount) = (UCHAR)(READ_FLASH_INDEXED(pBaseAddress, QS_DEVGEOM_OFFSET + nCount) & 0xFF);
    }

    // The block erase code assumes a single block per erase region - check for that here...
    //For Tyax there are 2 types of erase blocks
//    if (g_CFIInfo.Geometry.NumEraseBlocks == 1)
//    {
//        return(FALSE);
//    }

    // Compute block size and the total number of blocks here.  Since we know an erase region contains
    // only one block, the erase region size is equal to the block size.

    // Note that the flash block size is 128KB, if paired, we have two of the 16-bit parts and the block size is effectively 256KB.
    g_CFIInfo.BlockSize = (g_CFIInfo.Geometry.EraseRegionSize1 * REGION_SIZE_MULT);
    g_CFIInfo.TotalFlashBlocks = g_CFIInfo.Geometry.NumIdentEraseBlocks1 + 1;

    if (bPairedFlash)
    {
        g_CFIInfo.BlockSize *= 2;
    }

    if (g_CFIInfo.Geometry.NumEraseBlocks > 1)
    {

    //this is for BB
    g_CFIInfo.SmallBlockSize               = g_CFIInfo.BlockSize;
    g_CFIInfo. CompositeBlockSize          = g_CFIInfo.SmallBlockSize * NUM_SMALL_BLKS;
    g_CFIInfo.EndSmallBlockAddress         = g_CFIInfo.StartSmallBlockAddress + g_CFIInfo.CompositeBlockSize;
        if (((int)((g_CFIInfo.BlockSize *  g_CFIInfo.TotalFlashBlocks*
                    g_CFIInfo.Geometry.NumEraseBlocks)) < (int)(1<<g_CFIInfo.Geometry.DevSize))
           )
        {
            output = (ULONG)pBaseAddress + FLASH_CFIREGION2OFFSET;
            while (iteration < sizeof(ULONG))
            {
                working_val = *((ULONG *)output + iteration)&(ULONG)QUERYTABLEMASK;
                temp_val |=  working_val << (BITS_IN_BYTE *iteration);
                iteration++;
            }
            g_CFIInfo.Geometry.NumIdentEraseBlocks2 = (USHORT)(temp_val & 0xffff);
            g_CFIInfo.TotalFlashBlocks+=  g_CFIInfo.Geometry.NumIdentEraseBlocks2+ 1;
            g_CFIInfo.Geometry.EraseRegionSize2 = (USHORT)(temp_val >> FLASH_CFIREGION_UPPERWORD);
            g_CFIInfo.BlockSize = g_CFIInfo.Geometry.EraseRegionSize2* REGION_SIZE_MULT;
            if (bPairedFlash)
            {
                g_CFIInfo.BlockSize *= 2;
            }


        } else // update the block count for top boot part
        {
            output = (ULONG)pBaseAddress + FLASH_CFIREGION1OFFSET;
            while (iteration < sizeof(ULONG))
            {
                working_val = *((ULONG *)output + iteration)&(ULONG)QUERYTABLEMASK;
                temp_val |=  working_val << (BITS_IN_BYTE *iteration);
                iteration++;
            }
            g_CFIInfo.TotalFlashBlocks+= ((temp_val & 0xffff) + 1);

        }
    }
    g_CFIInfo.TotalFlashSizeMB =((g_CFIInfo.TotalFlashBlocks - g_CFIInfo.Geometry.NumIdentEraseBlocks1 )*(g_CFIInfo.BlockSize))>>MB;
    // Put the Flash into a known state (READ_ARRAY mode with WRITE-ENABLE disabled).
    g_RelocFuncStruct.WriteCommand(pBaseAddress, READ_ARRAY_CMD, g_FMDConfig);
    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
    }

    return(TRUE);

}

BOOL FMDHAL_DoUnlockBlock(void)
{
    volatile ULONG *pCurrBlockAddr = (volatile ULONG *)g_CurrCmdStruct.pTargetAddress;
    UINT idx;

    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptDisable();
    }
    for (idx = 0; idx < g_CurrCmdStruct.ulNumBlocks; idx++)
    {

        g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_UNLOCK_BLOCK_SETUP, g_FMDConfig);
        g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_UNLOCK_BLOCK_CONFIRM, g_FMDConfig);
        while (!g_RelocFuncStruct.ReadStatus(pCurrBlockAddr, FMDHAL_FLASH_STATUS_READY, g_FMDConfig));
        /* Check for Errors */
        if (g_RelocFuncStruct.ReadStatus(pCurrBlockAddr,
                                         (IntelSCSStatusVoltageError |
                                          IntelSCSStatusBlockLockError |
                                          IntelSCSStatusEraseError),
                                         g_FMDConfig))
        {
            g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
            g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
            if (g_SWRWW_Enable)
            {
                g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
            }
            return(FALSE);
        }
    }

    g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
    }

    return(TRUE);
}



BOOL FMDHAL_DoLockBlock(void)
{
    volatile ULONG *pCurrBlockAddr = (volatile ULONG *)g_CurrCmdStruct.pTargetAddress;
    UINT idx;


    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptDisable();
    }
    for (idx = 0; idx < g_CurrCmdStruct.ulNumBlocks; idx++)
    {
        g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_LOCK_BLOCK_SETUP, g_FMDConfig);
        g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_LOCK_BLOCK_CONFIRM, g_FMDConfig);
        while (!g_RelocFuncStruct.ReadStatus(pCurrBlockAddr, FMDHAL_FLASH_STATUS_READY, g_FMDConfig));
        /* Check for Errors */
        if (g_RelocFuncStruct.ReadStatus(pCurrBlockAddr,
                                         (IntelSCSStatusVoltageError |
                                          IntelSCSStatusBlockLockError |
                                          IntelSCSStatusEraseError),
                                         g_FMDConfig))
        {
            g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_CLEAR_STATUS, g_FMDConfig);
            g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
            if (g_SWRWW_Enable)
            {
                g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
            }
            return(FALSE);
        }
    }

    g_RelocFuncStruct.WriteCommand(pCurrBlockAddr, FMDHAL_FLASH_READ_ARRAY, g_FMDConfig);
    if (g_SWRWW_Enable)
    {
        g_RelocFuncStruct.FMDHAL_ASMInterruptEnable();
    }

    return(TRUE);
}



BOOL FMDHAL_RelocateCode(ULONG *pSourceAddress, ULONG *pDestinationAddress, ULONG uFunctionSize)
{
    ULONG  align;
    if ( (uFunctionSize + g_RelocOffset) > FMDHAL_MAX_RELOCATED_AREA)
    {
        pDestinationAddress = NULL;
        NKDbgPrintfW(L"FMDHAL:RelocCode:RelocOffset(%d)Too far\n\r\r\n", g_RelocOffset);
        return(FALSE);
    } else
    {
        *pDestinationAddress = (ULONG)&g_FMDHAL_RelocateRegion[g_RelocOffset];
        //pDestinationAddress = (LPVOID)&g_FMDHAL_RelocateRegion[g_RelocOffset];
        memcpy(&g_FMDHAL_RelocateRegion[g_RelocOffset], pSourceAddress, uFunctionSize);
        g_RelocOffset += uFunctionSize;

        /* Stay DWORD aligned */
        align = g_RelocOffset & 0x3;
		if (align != 0)
		{
           g_RelocOffset += (4 - align);
		}
    }

    // force cache line clean to sync memory with data cache
    // This is needed for imediate execution after the copy. The CPU does not fetch
    // the code through the data cache. It must be written down into ram.
    //
    CleanDataCache( (DWORD)*pDestinationAddress, (DWORD)&g_FMDHAL_RelocateRegion[g_RelocOffset] );
    
    return(TRUE);
}

⌨️ 快捷键说明

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