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

📄 mmcmng.c

📁 好记星的控件,包括button,list,对文件操作
💻 C
📖 第 1 页 / 共 4 页
字号:
*
*       This function reads or writes data from and to the FLASH Disk
*       based on the 'reading' parameter.
*
* AUTHOR
*
*       Victor Li
*
* INPUTS
*
*       driveno                             The number assigned to the
*                                            FLASH Disk (not used)
*       dwLogicalPage                        The page number to read or
*                                            write
*       buffer                              Pointer to the data to be
*                                            placed from a read or
*                                            stored on a write
*       uPages                               Number of bytes to be read
*                                            or written
*       reading                             Indicates whether or not we
*                                            are reading or writing
*
* OUTPUTS
*
*       YES                                 Successful Completion.
*       NO                                  Block number is out of range.
*
* Note
*
*       victor modify for quick R/W 2003/06/22
*
*************************************************************************/
INT __MmcIo(UINT16 driveno, UINT32 dwLogicalPage, VOID *buffer, UINT16 uPages, INT reading)
{
UINT32		dwPhysicalPage;
INT      offset;
UINT8       *pB;
UINT32		dwTotalLen, dwReturnLen;

    /* We don't use drive no. You could have multiple drives if wanted */
    driveno = driveno;
    pB = buffer;
	dwTotalLen = 0;

    while (uPages)
    {
		dwPhysicalPage = __MmcGetPhysicalPage(dwLogicalPage);
		if(dwPhysicalPage == 0)
			return 0;

        offset = __MmcReadPhyEraseUnit(dwPhysicalPage, dwLogicalPage);
        if(offset < 0)
            return 0;

        if (reading)
        {
            dwReturnLen = __MmcReadBytesBuf(offset, pB, FLASH_PAGE_SIZE);
			if(dwReturnLen != FLASH_PAGE_SIZE)
				return dwTotalLen;
        }
        else
        {
            UINT8   bModify;
//            UINT32  dwEcc;

            //读取Spare区Write标志
            bModify = __MmcReadModifyFlag(dwPhysicalPage);
            if(bModify == FLASH_FLAG_MODIFY)
            {
                //做要擦除标记
                g_MmcDirty = 1;      // set modify flash
            }
            else if(bModify == FLASH_FLAG_FREE)
            {
                //做临时修改标记
                __MmcWriteModifyFlag(dwPhysicalPage, FLASH_FLAG_MODIFY_TEMP);
            }
//            else if(bModify == FLASH_FLAG_MODIFY_TEMP)
                //已经做了临时修改标记,不处理

            dwReturnLen = __MmcWriteBytesBuf(offset, pB, FLASH_PAGE_SIZE);
            if(dwReturnLen != FLASH_PAGE_SIZE)
                return dwTotalLen;
#ifdef  FLASH_ECC_CHECK
            dwEcc = __MmcEccCalc(pB);
            __MmcWriteEccFlag(dwPhysicalPage, dwEcc);
#endif
        }
        uPages--;
        dwLogicalPage++;
        pB += FLASH_PAGE_SIZE;
		dwTotalLen += dwReturnLen;
    }

    return dwTotalLen;
}

INT CardIo(UINT16 driveno, UINT32 dwLogicalPage, VOID *buffer, UINT16 uPages, INT reading)
{
    INT     nRet;
/*	OPTION	preempt_status;

	preempt_status = NU_Change_Preemption(NU_NO_PREEMPT);*/

    nRet = __MmcIo(driveno, dwLogicalPage, buffer, uPages, reading);

//    NU_Change_Preemption(preempt_status);

    return nRet;
}



BOOL __MmcWriteBlock(UINT32 dwOffset)
{
    UINT16  i;

    //写Data
    if(__MmcWriteBytes(dwOffset, g_MmcReadBuf, g_MmcParam.uBlockSize, TRUE) != g_MmcParam.uBlockSize)
        return FALSE;

    //整理Spare区
    for(i = 0; i < g_MmcParam.uBlockSize / g_MmcParam.uDataSize; i ++)
    {
        //将临时修改标记,改为真正的修改标志
        if(__MmcReadModifyFlag(i) == FLASH_FLAG_MODIFY_TEMP)
            __MmcWriteModifyFlag(i, FLASH_FLAG_MODIFY);
    }

    //写Spare区
    if(__MmcWriteSpareBytes(dwOffset, g_MmcSpareBuf,
        g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize, TRUE) !=
        g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize)
        return FALSE;

    return TRUE;
}

BOOL __MmcUpdateBlock(BOOL bCurBlockGood)
{
    UINT32  dwOffset;
    UINT16  wTemp;

    while(g_uMmcBlockPrepare)
    {
        //擦除备用块
        dwOffset = (UINT32)g_MmcTablePrepare[0] * g_MmcParam.uBlockSize;
        if(__MmcEraseBlock(dwOffset, TRUE) == TRUE)
        {
#ifdef  FLASH_ERASE_COUNTER
            if(__MmcSetEraseCounter() != TRUE)
                return FALSE;
#endif
            if(__MmcWriteBlock(dwOffset) == TRUE)
                break;
        }
        __MmcBadRegister(FLASH_STATUS_BAD_USER, g_MmcTablePrepare[0]);
        memcpy(&g_MmcTablePrepare[0], &g_MmcTablePrepare[1], g_uMmcBlockPrepare * sizeof(UINT16));
        g_uMmcBlockPrepare --;
        g_uMmcBlockBadUser ++;
    }

    if(g_uMmcBlockPrepare == 0)
        return FALSE;

    //更新表
    *(UINT16 *)(g_MmcTableLog2Phy + g_MmcLogicNum * sizeof(UINT16)) = g_MmcTablePrepare[0];

    wTemp = g_MmcPhyNum;
    g_MmcPhyNum = g_MmcTablePrepare[0];
    g_MmcTablePrepare[0] = wTemp;

    if(bCurBlockGood == FALSE)
    {
        __MmcBadRegister(FLASH_STATUS_BAD_USER, g_MmcTablePrepare[0]);
        memcpy(&g_MmcTablePrepare[0], &g_MmcTablePrepare[1], g_uMmcBlockPrepare * sizeof(UINT16));
        g_uMmcBlockPrepare --;
        g_uMmcBlockBadUser ++;
    }


    return TRUE;
}

BOOL __MmcUpdate()
{
    UINT32 dwOffset;

    if(g_MmcModify)
    {   // content has been modified
        // xiaoming must modify it for backup block
        if(g_MmcDirty)
        {
            //Replace标志加1
            g_MmcSpareBuf[FLASH_REPLACE_OFFSET] ++;
            g_MmcSpareBuf[FLASH_REPLACE_OFFSET] %= FLASH_REPLACE_MAXVALUE;

            if(__MmcUpdateBlock(TRUE) == FALSE)
                return FALSE;      // there have some error
        }
        else
        {
            dwOffset = g_MmcPhyNum * g_MmcParam.uBlockSize;
            if(__MmcWriteBlock(dwOffset) == FALSE)
            {
                if(__MmcUpdateBlock(FALSE) == FALSE)
                    return FALSE;      // there have some error
            }
        }
    }
    return TRUE;
}

BOOL MmcUpdate()
{
    BOOL    bRet;
/*	OPTION	preempt_status;

	preempt_status = NU_Change_Preemption(NU_NO_PREEMPT);*/

    bRet = __MmcUpdate();
    g_MmcPhyNum = -1;
    g_MmcModify = 0;
    g_MmcDirty = 0;   // xiaoming must modify it

//    NU_Change_Preemption(preempt_status);

    return bRet;
}

INT __MmcReadPhyEraseUnit(INT dwPhysicalPage, INT dwLogicPage)
{
    INT curEraseNum, dwOffset;

    // get erase unit number which contains "dwPhysicalPage"
    curEraseNum = dwPhysicalPage * g_MmcParam.uDataSize / g_MmcParam.uBlockSize;

    if(curEraseNum != g_MmcPhyNum)
    {   // if the erase unit has been in buffer, don't read it
        if(__MmcUpdate() == FALSE)
        {
            g_MmcPhyNum = -1;
            g_MmcModify = 0;
            return -1;      // there have some error
        }

        g_MmcPhyNum = curEraseNum;
        g_MmcLogicNum = dwLogicPage * g_MmcParam.uDataSize / g_MmcParam.uBlockSize;
        dwOffset = g_MmcPhyNum * g_MmcParam.uBlockSize;

        //读取数据区
        if(__MmcReadBytes(dwOffset, g_MmcReadBuf, g_MmcParam.uBlockSize) != g_MmcParam.uBlockSize)
        {
            g_MmcPhyNum = -1;
            g_MmcModify = 0;
		    return -1;      // there have some error
        }
        //读取Spare区
        if(__MmcReadSpareBytes(dwOffset, g_MmcSpareBuf, g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize) != g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize)
        {
            g_MmcPhyNum = -1;
            g_MmcModify = 0;
		    return -1;      // there have some error
        }

#ifdef  FLASH_ECC_CHECK
        //Compare ECC
        if(__MmcCheckEcc() != TRUE)
        {
            g_MmcPhyNum = -1;
            g_MmcModify = 0;
		    return -1;      // there have some error
        }
#endif

        g_MmcModify = 0;
        g_MmcDirty = 0;   // xiaoming must modify it
    }

    return dwPhysicalPage * g_MmcParam.uDataSize - curEraseNum * g_MmcParam.uBlockSize;
}


INT __MmcReadBytesBuf(INT offset, UINT8 *pB, INT size)
{
    memmove(pB, &g_MmcReadBuf[0] + offset, size);
/*#ifdef  __PC__
    memmove(pB, &g_MmcReadBuf[0] + offset, size);
#else
	if ( (*((unsigned char *)TIMER_CONTROL_REG) & 0x01) == 0x01)
        memmove(pB, &g_MmcReadBuf[0] + offset, size);
	else
	    IDMA_MemCpy(pB, (UINT8*)&g_MmcReadBuf[0] + offset, size / 2, FLAG_IDMA_16BIT | FLAG_IDMA_TGTINC | FLAG_IDMA_SRCINC);
#endif*/

/*    INT i;
    for(i = 0; i < size; i++){
        pB[i] = ~g_MmcReadBuf[offset + i];
    }
*/    return size;
}

INT __MmcWriteBytesBuf(INT offset, UINT8 *pB, INT size)
{
    memmove(&g_MmcReadBuf[0] + offset, pB, size);
/*#ifdef  __PC__
    memmove(&g_MmcReadBuf[0] + offset, pB, size);
#else
	if ( (*((unsigned char *)TIMER_CONTROL_REG) & 0x01) == 0x01)
        memmove(&g_MmcReadBuf[0] + offset, pB, size);
	else
	    IDMA_MemCpy((UINT8*)&g_MmcReadBuf[0] + offset, pB, size / 2, FLAG_IDMA_16BIT | FLAG_IDMA_TGTINC | FLAG_IDMA_SRCINC);
#endif*/

/*    INT i;
    for(i = 0; i < size; i++){
        g_MmcReadBuf[offset + i] = ~pB[i];
    }
*/
    g_MmcModify = 1;      // set modify flash
    return size;
}

UINT8   __MmcReadModifyFlag(UINT32 dwPage)
{
    UINT32  wPage;
    UINT32  wOffset;

    wPage = dwPage % (g_MmcParam.uBlockSize / g_MmcParam.uDataSize);
    wOffset = wPage * g_MmcParam.uSpareSize + (FLASH_MODIFY_OFFSET);

    return g_MmcSpareBuf[wOffset];
}

UINT8   __MmcWriteModifyFlag(UINT32 dwPage, UINT8 byErase)
{
    UINT32  wPage;
    UINT32  wOffset;

    wPage = dwPage % (g_MmcParam.uBlockSize / g_MmcParam.uDataSize);
    wOffset = wPage * g_MmcParam.uSpareSize + (FLASH_MODIFY_OFFSET);

    g_MmcSpareBuf[wOffset] = byErase;
    return byErase;
}

#ifdef  FLASH_ECC_CHECK
UINT32  __MmcEccCalc(UINT8* pBuf)
{
    UINT32  dwEcc;

    dwEcc = make_ecc_512Byte((pBuf));
    dwEcc &= 0xFFFFFF;

    return dwEcc;
}

UINT8   __MmcWriteEccFlag(UINT32 dwPage, UINT32 dwEcc)
{
    UINT32  wPage;
    UINT32  wOffset;

    wPage = dwPage % (g_MmcParam.uBlockSize / g_MmcParam.uDataSize);

    wOffset = wPage * g_MmcParam.uSpareSize + (FLASH_ECC_OFFSET - FLASH_PAGE_SIZE);
    memcpy(&g_MmcSpareBuf[wOffset], &dwEcc, FLASH_ECC_LENGTH);

    return 0;
}

BOOL __MmcCheckEcc()
{
    UINT32  i;
    UINT32  dwEccOffset;
    UINT32  dwErrOffset;
    UINT32  dwEccCalc, dwEccSave;
    UINT32  dwCompare;

    for(i = 0; i < g_MmcParam.uBlockSize / g_MmcParam.uDataSize; i ++)
    {
        dwEccCalc = __MmcEccCalc(&g_MmcReadBuf[i * FLASH_PAGE_SIZE]);

        dwEccOffset = i * g_MmcParam.uSpareSize + (FLASH_ECC_OFFSET - FLASH_PAGE_SIZE);
        memcpy(&dwEccSave, &g_MmcSpareBuf[dwEccOffset], FLASH_ECC_LENGTH);

        dwCompare = compare_ecc(&dwEccCalc, &dwEccSave, &g_MmcReadBuf[i * FLASH_PAGE_SIZE], &dwErrOffset, g_MmcEccBuf);
        if(dwCompare == 0)  //ECC_NO_ERROR
            continue;
        else if(dwCompare == 1)  //ECC_CORRECTABLE_ERROR
        {
            memcpy(&g_MmcReadBuf[i * FLASH_PAGE_SIZE], g_MmcEccBuf, FLASH_PAGE_SIZE);
            continue;
        }
        else
            return FALSE;
    }

    return TRUE;
}
#endif

INT CardCheck(UINT16 driveno)
{
    extern BOOL IsCardExist(void);
    if (IsCardExist())
    {
        return(NU_SUCCESS);
    }

    return (~NU_SUCCESS);
}

#ifdef  FLASH_ERASE_COUNTER

#define ERASE_COUNT_UNIT    10

BOOL __MmcGetEraseCounter()
{
    UINT32  i, j;

    g_MmcEraseCounterBuf = (UINT8 *)MemAlloc(g_MmcParam.uBlockSize);
    if(g_MmcEraseCounterBuf == NULL)
        return FALSE;
	//读出第一块数据
	if(__MmcReadBytes(0, g_MmcEraseCounterBuf, g_MmcParam.uBlockSize) != g_MmcParam.uBlockSize)
		return FALSE;

    for(i = 0; i < g_MmcParam.uBlockSize; i ++)
    {
        if(g_MmcEraseCounterBuf[i] != 0)
        {
            for(j = 0; j < 8; j ++)
            {
                if(((g_MmcEraseCounterBuf[i] >> j) & 1) != 0)
                    break;
            }
            break;
        }
    }
    g_dwMmcEraseCounter = (i * 8 + j) * ERASE_COUNT_UNIT;

    i ++;
    for(; i < g_MmcParam.uBlockSize; i ++)
    {
        //发现数据不合理,重新擦除
        if(g_MmcEraseCounterBuf[i] != 0xFF)
        {
            if(SysGetLowVoltageStatus() == SYSTEM_FLASH_LOWVOL)
            {
                if(__MmcEraseBlock(0, FALSE) != TRUE)
                    return FALSE;
            }
            g_dwMmcEraseCounter = 0;
            memset(g_MmcEraseCounterBuf, 0, g_MmcParam.uBlockSize);
            break;
        }
    }
    return TRUE;
}

BOOL __MmcSetEraseCounter()
{
    UINT32  i, j;

    g_dwMmcEraseCounter ++;
    if((g_dwMmcEraseCounter % ERASE_COUNT_UNIT) == 0)
    {
        i = (g_dwMmcEraseCounter / ERASE_COUNT_UNIT - 1) / 8;
        j = (g_dwMmcEraseCounter / ERASE_COUNT_UNIT - 1) % 8;

        g_MmcEraseCounterBuf[i] &= (~(1 << j));

        if(SysGetLowVoltageStatus() == SYSTEM_FLASH_LOWVOL)

⌨️ 快捷键说明

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