fmd.cpp
来自「该BSP是基于PXA270+WINCE的BSP」· C++ 代码 · 共 1,511 行 · 第 1/4 页
CPP
1,511 行
addr1 = (UCHAR) ((startSectorAddr) & 0xff);
addr2 = (UCHAR) ((startSectorAddr>> 8) & 0xff);
addr3 = (UCHAR) ((startSectorAddr>> 16) & 0xff);
// Issue Read command
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_WRITE;
*((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;
//Sleep(1);
// Read only data portion of the sector.
for(i=0; i<0x800; i++)
{
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR) pSectorBuff[i];
}
if(pSectorInfoBuff)
{
//RETAILMSG(1, (TEXT("FMD_WriteSector4!\r\n")));
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)(pSectorInfoBuff->bBadBlock); // Bad block byte
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pSectorInfoBuff->dwReserved1 & 0x000000FF)); // Reserved field 1
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pSectorInfoBuff->dwReserved1 & 0x0000FF00) >> 8);
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pSectorInfoBuff->dwReserved1 & 0x00FF0000) >> 16);
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pSectorInfoBuff->dwReserved1 & 0xFF000000) >> 24);
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)(pSectorInfoBuff->bOEMReserved); // OEM byte
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pSectorInfoBuff->wReserved2 & 0x000000FF));
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)((pSectorInfoBuff->wReserved2 & 0x0000FF00) >> 8); // Reserved field 2
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++)
{
*((volatile ULONG *)(NAND_DATA_PORT ))=(UCHAR)(0xff);
}
}
// Compute the ECC for this data (only 6 of the available 8 bytes are used)
if(!ECC_ComputeECC(pSectorBuff, 2048, ECC, 24))
{
RETAILMSG(1, (TEXT("FMD: Unable to compute ECC(sector 0x%x) !!!\r\n"),startSectorAddr));
}
// Write the sector info and ECC into the spare area
for(i=0; i<8; i++) {
*((volatile ULONG *)(NAND_DATA_PORT ))= ECC[i];
}
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_WRITE2;
status = GetStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Error Programing page %d!\n"), startSectorAddr));
//FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return FALSE;
}
pSectorBuff += 2048;
}
startSectorAddr ++;
}
SetKMode(bLastMode);
return (TRUE);
}
//
// IsBlockBad
//
// Check to see if the given block is bad. A block is bad if the 517th byte on
// the first or second page is not 0xff.
//
// blockID: The block address. We need to convert this to page address
//
//
BOOL IsBlockBad(BLOCK_ID blockID)
{
UCHAR addr1, addr2, addr3, wData;
DWORD dwPageID = blockID*64; // Get the first page of the blcok
BOOL bLastMode = SetKMode(TRUE);
// RETAILMSG(1, (TEXT("IsBlockBad:blockID=0x%x \r\n"),blockID));
addr1 = (UCHAR) ((dwPageID) & 0xff);
addr2 = (UCHAR) ((dwPageID >> 8) & 0xff);
addr3 = (UCHAR) ((dwPageID >> 16) & 0xff);
// For our NAND flash, we don't have to issue two read command. We just need
// to issue one read command and do contiquous read
// Check the first page.
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_READ;
//Sleep(1);
*((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;
// usWait(20);//wzw
mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 20);
// Sleep(1);
// mmXllpOstDelayMicroSeconds((P_m_OST_T) mg_pOSTRegs, 1000);
//Sleep(1);
//Sleep(1); // check ready
wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));
//RETAILMSG(1, (TEXT("wData:wData=0x%x \r\n"),wData));
if(0xff != wData) {
SetKMode (bLastMode);
//RETAILMSG(1, (TEXT("IsBlockBad111:blockID=0x%x \r\n"),blockID));
return TRUE;
}
// Check the second page
/* Sleep(1); // check ready
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_READ;
Sleep(1);
*((volatile ULONG *)(NAND_ADDR_PORT ))=0x00;
*((volatile ULONG *)(NAND_ADDR_PORT ))=0x08;
*((volatile ULONG *)(NAND_ADDR_PORT ))=(addr1+0x7f);
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr2;
if(NEED_EXT_ADDR) {
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr3&0x07;
}
*((volatile ULONG *)(NAND_CMD_PORT ))=0x30;
Sleep(1); // check ready
wData =(UCHAR)(*((volatile ULONG *)(NAND_DATA_PORT)));
if(0xff != wData) {
SetKMode (bLastMode);
//RETAILMSG(1, (TEXT("IsBlockBad222:blockID=0x%x \r\n"),blockID));
return TRUE;
}*/
//RETAILMSG(1, (TEXT("IsBlockBad333:blockID=0x%x \r\n"),blockID));
SetKMode (bLastMode);
return FALSE;
}
/*
* MarkBlockBad
*
* Mark the block as a bad block. We need to write a 00 to the 517th byte
*/
BOOL MarkBlockBad(BLOCK_ID blockID)
{
UCHAR addr1, addr2, addr3, status;
DWORD dwStartPage = blockID*64;
RETAILMSG(1, (TEXT("MarkBlockBad:blockID=0x%x \r\n"),blockID));
// We will try to write 00 to the 517th byte of the first page
addr1 = (UCHAR) ( (dwStartPage) & 0xff );
addr2 = (UCHAR) ( (dwStartPage >> 8) & 0xff );
addr3 = (UCHAR) ( (dwStartPage >> 16) & 0xff );
//First we set the pointer to point to the spare area
// *((volatile UCHAR *)(NAND_CMD_PORT ))=CMD_READ2;
//Sleep(1); // check ready
//Start writing to the first page of the block
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_WRITE;
// Sleep(1);
*((volatile ULONG *)(NAND_ADDR_PORT ))=0x00;
*((volatile ULONG *)(NAND_ADDR_PORT ))=0x08;
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr1;
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr2;
//if(NEED_EXT_ADDR) {
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr3;
// }
// Sleep(1);
// Put a zero in the block valid address.
*((volatile ULONG *)(NAND_DATA_PORT ))=0x00;
// Close out the write.
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_WRITE2;
// Check the status
status = GetStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Failed to mark the block bad!\n")));
return FALSE;
}
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_GetBlockStatus()
Description: Returns the status of a block. For read-only blocks, checks the sector
info data for the first sector of the block. Block is always good, so no need to check.
Returns: Block status.
------------------------------------------------------------------------------*/
DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
{
//RETAILMSG(1, (TEXT("FMD_GetBlockStatus:blockID=0x%x \r\n"),blockID));
SECTOR_ADDR Sector = blockID * 64;
SectorInfo SI;
DWORD dwResult = 0;
if (IsBlockBad (blockID))
{
//RETAILMSG(1, (TEXT("FMD_GetBlockStatus111:blockID=0x%x \r\n"),blockID));
return BLOCK_STATUS_BAD;
}
if (!FMD_ReadSector(Sector, NULL, &SI, 1))
{
//RETAILMSG(1, (TEXT("FMD_GetBlockStatus222:blockID=0x%x \r\n"),blockID));
return BLOCK_STATUS_UNKNOWN;
}
if (!(SI.bOEMReserved & OEM_BLOCK_READONLY))
{
//RETAILMSG(1, (TEXT("FMD_GetBlockStatus333:blockID=0x%x \r\n"),blockID));
dwResult |= BLOCK_STATUS_READONLY;
}
if (!(SI.bOEMReserved & OEM_BLOCK_RESERVED))
{
//RETAILMSG(1, (TEXT("FMD_GetBlockStatus444:blockID=0x%x \r\n"),blockID));
dwResult |= BLOCK_STATUS_RESERVED;
}
//RETAILMSG(1, (TEXT("FMD_GetBlockStatus555:blockID=0x%x dwResult =%x\r\n"),blockID,dwResult));
return dwResult;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_SetBlockStatus()
Description: Sets the status of a block.
Returns: TRUE if no errors in setting.
------------------------------------------------------------------------------*/
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
RETAILMSG(1, (TEXT("FMD_SetBlockStatus:blockID=0x%x \r\n"),blockID));
if (dwStatus & BLOCK_STATUS_BAD) {
if (!MarkBlockBad (blockID))
return FALSE;
}
if (dwStatus & (BLOCK_STATUS_READONLY | BLOCK_STATUS_RESERVED)) {
SECTOR_ADDR Sector = blockID *64;
SectorInfo SI;
if (!FMD_ReadSector(Sector, NULL, &SI, 1)) {
return FALSE;
}
if (dwStatus & BLOCK_STATUS_READONLY) {
SI.bOEMReserved &= ~OEM_BLOCK_READONLY;
}
if (dwStatus & BLOCK_STATUS_RESERVED) {
SI.bOEMReserved &= ~OEM_BLOCK_RESERVED;
}
if (!FMD_WriteSector (Sector, NULL, &SI, 1)) {
return FALSE;
}
}
return TRUE;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_EraseBlock()
Description: Erases the specified Flash block.
Returns: Boolean indicating success.
------------------------------------------------------------------------------*/
BOOL FMD_EraseBlock(BLOCK_ID blockID)
{
ULONG blockPage = (blockID * 64); // Convert block address to page address.
ULONG ulStatus = 0;
UCHAR addr1, addr2, addr3, status;
BOOL bLastMode = SetKMode(TRUE);
// RETAILMSG(1, (TEXT("FMD_EraseBlock: blockID=0x%x \r\n"),blockID));
addr1 = (UCHAR) ((blockPage) & 0xff);
addr2 = (UCHAR) ((blockPage >> 8) & 0xff);
addr3 = (UCHAR) ((blockPage >> 16) & 0xff);
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_ERASE;
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr1;
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr2;
*((volatile ULONG *)(NAND_ADDR_PORT ))=addr3;
//Sleep(1); // check ready
*((volatile ULONG *)(NAND_CMD_PORT ))=CMD_ERASE2;
//Sleep(10); // check ready
status = GetStatus((DWORD) -1);
if(status & STATUS_ERROR) {
RETAILMSG(1, (TEXT("######## Error Erasing block %d!\n"), blockID));
//FMD_WRITE_PORT_UCHAR((PUCHAR) NAND_CS_PORT,(UCHAR)1); // disable chip
return FALSE;
}
SetKMode(bLastMode);
return(TRUE);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_PowerUp()
Description: Restores power to the Flash memory device (if applicable).
Returns: None.
------------------------------------------------------------------------------*/
VOID FMD_PowerUp(VOID)
{
return;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_PowerDown()
Description: Suspends power to the Flash memory device (if applicable).
Returns: None.
------------------------------------------------------------------------------*/
VOID FMD_PowerDown(VOID)
{
return;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Function: FMD_OEMIoControl()
Description: Implements user-defined (a.k.a. application specific) commands
for the Flash memory device
Returns: None.
------------------------------------------------------------------------------*/
BOOL FMD_OEMIoControl(DWORD dwIoControlCode, PBYTE pInBuf, DWORD nInBufSize,
PBYTE pOutBuf, DWORD nOutBufSize, PDWORD pBytesReturned)
{
return(TRUE);
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?