📄 mmcmng.c
字号:
{
if(__MmcWriteBytes(0, g_MmcEraseCounterBuf, g_MmcParam.uBlockSize, FALSE) != g_MmcParam.uBlockSize)
return FALSE;
}
}
return TRUE;
}
#endif
INT __MmcError(UINT16 wErr)
{
#ifdef __DEBUG__
NU_Printf("MmcError: %d \n", wErr);
while(1)
SysWatchClear();
#endif
return FLASH_ERR_UNKNOW;
}
UINT16 __MmcBadRegister(UINT8 bBadType, UINT16 wBadBlock)
{
UINT16 wBadTotal;
UINT16 wInsert;
wBadTotal = g_uMmcBlockBadUser + g_uMmcBlockBadNature +
g_uMmcBlockBadReadFail + g_uMmcBlockBadUnknown;
if(bBadType == FLASH_STATUS_BAD_USER)
wInsert = g_uMmcBlockBadUser;
else if(bBadType == FLASH_STATUS_BAD_NATURE)
wInsert = g_uMmcBlockBadUser + g_uMmcBlockBadNature;
else if(bBadType == FLASH_STATUS_BAD_READFAIL)
wInsert = g_uMmcBlockBadUser + g_uMmcBlockBadNature + g_uMmcBlockBadReadFail;
else if(bBadType == FLASH_STATUS_BAD_UNKNOWN)
wInsert = g_uMmcBlockBadUser + g_uMmcBlockBadNature + g_uMmcBlockBadReadFail + g_uMmcBlockBadUnknown;
if(wBadTotal > wInsert)
memmove(&g_MmcTableBad[wInsert + 1], &g_MmcTableBad[wInsert], (wBadTotal - wInsert) * sizeof(UINT16));
g_MmcTableBad[wInsert] = wBadBlock;
return 0;
}
UINT16 __MmcBadDisplay(UINT8 bBadType)
{
/* UINT8 szInfo[200];
UINT16 wDispStart;
UINT16 wDispNum;
UINT16 i;
if(bBadType == FLASH_STATUS_BAD_USER)
{
wDispStart = 0;
wDispNum = g_uMmcBlockBadUser;
sprintf(szInfo, "BadUser(%d):", wDispNum);
}
else if(bBadType == FLASH_STATUS_BAD_NATURE)
{
wDispStart = g_uMmcBlockBadUser;
wDispNum = g_uMmcBlockBadNature;
sprintf(szInfo, "BadNature(%d):", wDispNum);
}
else if(bBadType == FLASH_STATUS_BAD_READFAIL)
{
wDispStart = g_uMmcBlockBadUser + g_uMmcBlockBadNature;
wDispNum = g_uMmcBlockBadReadFail;
sprintf(szInfo, "BadReadFail(%d):", wDispNum);
}
else if(bBadType == FLASH_STATUS_BAD_UNKNOWN)
{
wDispStart = g_uMmcBlockBadUser + g_uMmcBlockBadNature + g_uMmcBlockBadReadFail;
wDispNum = g_uMmcBlockBadUnknown;
sprintf(szInfo, "BadUnknown(%d):", wDispNum);
}
for(i = 0; i < wDispNum; i ++)
sprintf(&szInfo[strlen(szInfo)], "%d ", g_MmcTableBad[wDispStart + i]);
szInfo[strlen(szInfo) + 1] = 0;
szInfo[strlen(szInfo)] = '\n';
NU_Printf(szInfo);
*/
return 0;
}
UINT16 MmcBadDisplay()
{
__MmcBadDisplay(FLASH_STATUS_BAD_USER);
__MmcBadDisplay(FLASH_STATUS_BAD_NATURE);
__MmcBadDisplay(FLASH_STATUS_BAD_READFAIL);
__MmcBadDisplay(FLASH_STATUS_BAD_UNKNOWN);
return 0;
}
/*读出Mmc对应表*/
INT __MmcTableRead()
{
BOOL bPrepare;
UINT8 status;
UINT16 i;
UINT16 wLogic, wCheck;
UINT32 dwOffset;
UINT8 pageStatusSpare[2][16];
UINT8 pageCheckSpare[16];
memset((VOID *)(g_MmcTableLog2Phy), 0xFF, g_MmcParam.uBlockNum * sizeof(UINT16));
//建立初始化的逻辑物理对应表
g_uMmcBlockUser = 0;
g_uMmcBlockBadUser = 0;
g_uMmcBlockPrepare = 0;
g_uMmcBlockBadNature = 0;
g_uMmcBlockBadReadFail = 0;
g_uMmcBlockBadUnknown = 0;
for(i = FLASH_BLOCK_TABLE; i < g_MmcParam.uBlockNum; i ++)
{
status = __MmcReadBlockStatus(i, (UINT8 *)pageStatusSpare);
if(status == FLASH_STATUS_GOOD)
{
wLogic = *(UINT16 *)(&pageStatusSpare[0][FLASH_LOGIC_OFFSET]);
dwOffset = (UINT32)(i + 1) * g_MmcParam.uBlockSize - g_MmcParam.uDataSize;
if(__MmcReadSpareBytes(dwOffset, pageCheckSpare, g_MmcParam.uSpareSize) != g_MmcParam.uSpareSize)
return __MmcError(2);
wCheck = *(UINT16 *)(&pageCheckSpare[FLASH_CHECK_OFFSET]);
//Check标志错
if(wCheck != FLASH_CHECK_VALUE)
bPrepare = TRUE;
//备用块逻辑号标志
else if(wLogic == FLASH_LOGIC_PREPARE)
bPrepare = TRUE;
//逻辑号大于最大理论值
else if(wLogic >= g_MmcParam.uUserBlockNum)
return __MmcError(5);
//当前逻辑号已经被使用,需要比较Replace标志
else if(*(UINT16 *)(g_MmcTableLog2Phy + wLogic * sizeof(UINT16)) != 0xFFFF)
{
UINT8 replaceNew, replacePrev;
UINT16 wBlockPrev;
//保留当前的Replace标志
replaceNew = pageStatusSpare[0][FLASH_REPLACE_OFFSET];
//得到前一个使用该逻辑号的物理块
wBlockPrev = *(UINT16 *)(g_MmcTableLog2Phy + wLogic * sizeof(UINT16));
//读取第一个Page的Spare区
dwOffset = (UINT32) wBlockPrev * g_MmcParam.uBlockSize;
if(__MmcReadSpareBytes(dwOffset, (UINT8 *)pageStatusSpare, 2 * g_MmcParam.uSpareSize) != 2 * g_MmcParam.uSpareSize)
return __MmcError(2);
//return FALSE;
//得到前一个使用该逻辑号的物理块的Replace标志
replacePrev = pageStatusSpare[0][FLASH_REPLACE_OFFSET];
//发现当前的逻辑号才是正确的,前一个使用该逻辑号的物理块要做备用处理
if((replacePrev + 1) % FLASH_REPLACE_MAXVALUE == replaceNew)
{
if(g_uMmcBlockPrepare >= g_MmcParam.uPrepareBlockNum)
return FLASH_ERR_NOFORMAT;
g_MmcTablePrepare[g_uMmcBlockPrepare] = wBlockPrev;
g_uMmcBlockPrepare ++;
g_uMmcBlockUser --;
bPrepare = FALSE;
}
else
bPrepare = TRUE;
}
else
bPrepare = FALSE;
if(bPrepare == TRUE)
{
if(g_uMmcBlockPrepare >= g_MmcParam.uPrepareBlockNum)
return FLASH_ERR_NOFORMAT;
g_MmcTablePrepare[g_uMmcBlockPrepare] = i;
g_uMmcBlockPrepare ++;
}
else if(wLogic < g_MmcParam.uUserBlockNum)
{
*(UINT16 *)(g_MmcTableLog2Phy + wLogic * sizeof(UINT16)) = i;
g_uMmcBlockUser ++;
}
else
return __MmcError(5);
//return FALSE;
}
else if(status == FLASH_STATUS_BAD_USER)
{
__MmcBadRegister(FLASH_STATUS_BAD_USER, i);
g_uMmcBlockBadUser ++;
}
else if(status == FLASH_STATUS_BAD_NATURE)
{
__MmcBadRegister(FLASH_STATUS_BAD_NATURE, i);
g_uMmcBlockBadNature ++;
}
else if(status == FLASH_STATUS_BAD_READFAIL)
{
__MmcBadRegister(FLASH_STATUS_BAD_READFAIL, i);
g_uMmcBlockBadReadFail ++;
}
else if(status == FLASH_STATUS_BAD_UNKNOWN)
{
__MmcBadRegister(FLASH_STATUS_BAD_UNKNOWN, i);
g_uMmcBlockBadUnknown ++;
}
}
if(g_uMmcBlockPrepare < 1)
return FLASH_ERR_NOPREPARE;
//检查逻辑物理对应表是否存在缺口
for(i = 0; i < g_MmcParam.uUserBlockNum/*g_uMmcBlockUser*/; i ++)
{
if(*(UINT16 *)(g_MmcTableLog2Phy + i * sizeof(UINT16)) == 0xFFFF)
return __MmcError(6);
//return FALSE;
}
return FLASH_ERR_NONE;
}
VOID __MmcBadError(UINT16 wBlock, UINT16 wErr)
{
#ifdef __DEBUG__
NU_Printf("MmcBad%d: %d \n", wErr, wBlock);
#endif
return ;
}
UINT8 __MmcReadBlockStatus(UINT16 uBlock, UINT8* pSpareBuf)
{
UINT32 dwOffset;
UINT8 status1, status2;
//读出前面两个Page的Spare区
dwOffset = (UINT32) uBlock * g_MmcParam.uBlockSize;
if(__MmcReadSpareBytes(dwOffset, pSpareBuf, 2 * g_MmcParam.uSpareSize) != 2 * g_MmcParam.uSpareSize)
return FLASH_STATUS_BAD_READFAIL;
pSpareBuf += FLASH_STATUS_OFFSET;
status1 = *pSpareBuf;
pSpareBuf += g_MmcParam.uSpareSize;
status2 = *pSpareBuf;
if((status1 == FLASH_STATUS_GOOD) && (status2 == FLASH_STATUS_GOOD))
return FLASH_STATUS_GOOD;
else if((status1 == FLASH_STATUS_BAD_NATURE) || (status2 == FLASH_STATUS_BAD_NATURE))
return FLASH_STATUS_BAD_NATURE;
else if((status1 == FLASH_STATUS_BAD_USER) || (status2 == FLASH_STATUS_BAD_USER))
return FLASH_STATUS_BAD_USER;
else
return FLASH_STATUS_BAD_UNKNOWN;
}
/*重新建立Mmc对应表*/
INT __MmcTableCreate(BOOL bShowProgress)
{
UINT16 i/*, j*/;
UINT16 wLogic;
UINT32 dwOffset;
UINT8 pageStatusSpare[2][16];
// UINT32 dwEcc;
//dennyhan changed the following
// if(SysGetLowVoltageStatus() == SYSTEM_FLASH_LOWVOL)
// return FLASH_ERR_LOWVOLTAGE;
//---------------------------------------------
if(bShowProgress == TRUE)
{
NU_Printf("\nSDCard Erasing...\n");
}
//计算ECC
memset(g_MmcReadBuf, 0xFF, g_MmcParam.uBlockSize);
memset(g_MmcSpareBuf, 0xFF, g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize);
#ifdef FLASH_ECC_CHECK
dwEcc = __MmcEccCalc(g_MmcReadBuf);
for(i = 0; i < g_MmcParam.uBlockSize / g_MmcParam.uDataSize; i ++)
{
//写每个Page的ECC
dwOffset = (UINT32) i * g_MmcParam.uSpareSize + (FLASH_ECC_OFFSET - FLASH_PAGE_SIZE);
memcpy(&g_MmcSpareBuf[dwOffset], &dwEcc, FLASH_ECC_LENGTH);
}
#endif
//写每块的Replace标志
g_MmcSpareBuf[FLASH_REPLACE_OFFSET] = 0;
//写每块的Check
*(UINT16 *)(&g_MmcSpareBuf[FLASH_CHECK_OFFSET + 496]) = FLASH_CHECK_VALUE;
/*擦除全部块数据*/
wLogic = 0;
for(i = 0; i < g_MmcParam.uBlockNum; i ++)
{
if((bShowProgress == TRUE) && (i % 50 == 0))
NU_Printf(">");
//擦除每块,检查这一块是否有效
/*读每一块的状态*/
if(__MmcReadBlockStatus(i, (UINT8 *)pageStatusSpare) != FLASH_STATUS_GOOD)
{
__MmcBadError(i, 1);
continue;
}
if(__MmcEraseBlock((UINT32)i * g_MmcParam.uBlockSize, FALSE) != TRUE)
{
__MmcBadError(i, 2);
continue;
}
#ifdef FLASH_ERASE_COUNTER
if(__MmcSetEraseCounter() != TRUE)
return FLASH_ERR_COUNTER;
#endif
//第一块不写逻辑号
if(i < FLASH_BLOCK_TABLE)
continue;
//备份块写备份逻辑号
if((wLogic >= g_MmcParam.uUserBlockNum) || (wLogic == FLASH_LOGIC_PREPARE))
// if(i >= (g_MmcParam.uBlockNum - FLASH_BLOCK_PREPARE))
wLogic = FLASH_LOGIC_PREPARE;
//写每块的逻辑号到第一个Page
dwOffset = (FLASH_LOGIC_OFFSET);
*(UINT16 *)(&g_MmcSpareBuf[dwOffset]) = wLogic;
//写整个Spare区到FALSH中
dwOffset = (UINT32) i * g_MmcParam.uBlockSize;
if(__MmcWriteSpareBytes(dwOffset, g_MmcSpareBuf,
g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize,
FALSE) !=
g_MmcParam.uBlockSize / g_MmcParam.uDataSize * g_MmcParam.uSpareSize)
{
__MmcBadError(i, 8);
continue;
}
if(wLogic != FLASH_LOGIC_PREPARE)
wLogic ++;
}
if(bShowProgress == TRUE)
{
NU_Printf("\nErase End!");
GraphResetLcdRange();
}
return FLASH_ERR_NONE;
}
/*逻辑页转化为物理页*/
UINT32 __MmcGetPhysicalPage(UINT32 dwLogicalPage)
{
UINT32 dwBlock;
UINT32 dwPhysicalPage;
/*得到逻辑块*/
dwBlock = dwLogicalPage / (g_MmcParam.uBlockSize / FLASH_PAGE_SIZE);
dwPhysicalPage = dwLogicalPage % (g_MmcParam.uBlockSize / FLASH_PAGE_SIZE);
/*加上保留的块*/
if(dwBlock >= g_uMmcBlockUser)
return 0;
/*查表得到物理块*/
dwBlock = *(UINT16 *)(g_MmcTableLog2Phy + dwBlock * sizeof(UINT16));
/*得到物理页*/
dwPhysicalPage += dwBlock * (g_MmcParam.uBlockSize / FLASH_PAGE_SIZE);
return dwPhysicalPage;
}
/*擦除一块FLASH*/
BOOL __MmcEraseBlock(UINT32 dwOffset, BOOL bCreateBad)
{
NU_DRIVER_REQUEST request; /*device request*/
request.nu_function = NU_STATUS;
request.nu_supplemental = FLASH_IO_ERASEBLK;
request.nu_request_info.nu_status.nu_extra_status = (VOID *)dwOffset;
request.nu_request_info.nu_status.nu_logical_unit = 0;
NU_Request_Driver(g_pMmcDriver, &request);
if(request.nu_status == NU_SUCCESS)
return TRUE;
else
return FALSE;
}
/*从Mmc Data区读数据*/
UINT32 __MmcReadBytes(UINT32 dwOffset, UINT8* pBuff, UINT32 dwLen)
{
NU_DRIVER_REQUEST request; /*device request*/
request.nu_function = NU_INPUT;
request.nu_supplemental = FLASH_IO_ONLYDATA;
request.nu_request_info.nu_input.nu_offset = dwOffset;
request.nu_request_info.nu_input.nu_request_size = dwLen;
request.nu_request_info.nu_input.nu_buffer_ptr = pBuff;
request.nu_request_info.nu_status.nu_logical_unit = 0;
NU_Request_Driver(g_pMmcDriver, &request);
if(request.nu_status != NU_SUCCESS)
return 0;
else
return request.nu_request_info.nu_input.nu_actual_size;
}
#ifdef USB_EVALUATE
#define EVALUATE_NUM 20
extern UINT8 g_nEvaluateFlag;
extern UINT8 g_nEvaluateTimes;
#endif
/*向Mmc Data区写数据*/
UINT32 __MmcWriteBytes(UINT32 dwOffset, UINT8* pBuff, UINT32 dwLen, BOOL bCreateBad)
{
NU_DRIVER_REQUEST request; /*device request*/
#ifdef USB_EVALUATE
if(dwLen > 10*1024)
{
if(g_nEvaluateTimes++ == EVALUATE_NUM && g_nEvaluateFlag == USB_EVALUATE_RING1)
{
g_nEvaluateTimes = 0;
g_nEvaluateFlag = USB_EVALUATE_RING2; // CHECK receive & write TIME
}
}
if(g_nEvaluateFlag == USB_EVALUATE_RING1) // do not actully write to flash when evaluate ring0
return dwLen;
#endif
request.nu_function = NU_OUTPUT;
request.nu_supplemental = FLASH_IO_ONLYDATA;
request.nu_request_info.nu_output.nu_offset = dwOffset;
request.nu_request_info.nu_output.nu_request_size = dwLen;
request.nu_request_info.nu_output.nu_buffer_ptr = pBuff;
request.nu_request_info.nu_status.nu_logical_unit = 0;
// For evaluate the USB performance. mann.
NU_Request_Driver(g_pMmcDriver, &request);
if(request.nu_status != NU_SUCCESS)
return 0;
else
return request.nu_request_info.nu_output.nu_actual_size;
}
/*从Mmc Spare区读数据*/
UINT32 __MmcReadSpareBytes(UINT32 dwOffset, UINT8* pBuff, UINT32 dwLen)
{
NU_DRIVER_REQUEST request; /*device request*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -