📄 mmcoem.c
字号:
#ifdef NMD_DEBUG
RETAILMSG(1, (TEXT("getMMCResponseInfo> %x\r\n"),v_pMMCReg->MMC_STAT));
#endif
/* Timer count for an MMC response */
dtimer = 0x0FFF;
/* Clear the FIFO buffer */
while ( dtimer )
{
/* Read status and wait for proper response */
dtmp = v_pMMCReg->MMC_STAT;
dtimer--;
/* Check for TIME OUT on response */
if ( dtmp & TIME_OUT_RESPONSE )
{
return MMC_CARD_IS_NOT_RESPONDING;
}
/* Check for CRC on response */
else if ( dtmp & RESP_CRC_ERR)
{
return (MMC_CMD_CRC_ERROR );
}
else if ( dtmp & CRC_WR_ERR )
{
return MMC_DATA_STATUS_CRC_ERROR;
}
/* Check for CRC read error */
else if ( dtmp & CRC_RD_ERR )
{
return MMC_DATA_STATUS_CRC_ERROR;
}
/* Check for command response */
else if ( dtmp & END_CMD_RES )
{
/* Get the command response information */
dtmp = (respLength + 1) & 0xFE;
respLength = dtmp;
i = 0;
while ( i < respLength )
{
dtmp = dtmp = v_pMMCReg->MMC_RES;
respBuff[i] = (UCHAR)(dtmp >> 8);
i++;
respBuff[i] = (UCHAR)(dtmp & 0xFF);
i++;
}
msWait(5);
/* No error return */
return MMC_NO_ERROR;
}
}
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("getMMCResponseInfo %x\r\n"), dtmp));
#endif
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("getMMCResponseInfo<-\r\n")));
#endif
return (MMC_CARD_IS_NOT_RESPONDING);
}
/***************************************************************************
* Name: MMCTransmit - Handle data from host to device
*
* Description:
* Write data to the device. This routine handles single
* block (WRITE SINGLE BLOCK command) or multiple blocks
* (WRITE MULTIPLE BLOCK command) data transfer.
*
* Input:
* pc Device controller structure
* dataLength Data block length
* noBLocks Number of sectors to transfer
* xferMode Single or mulitiple mode transfer
*
* Output:
* Data is written to the device.
*
* Return:
* MMC Status code
*
***************************************************************************/
MMC_CC MMCTransmit(UCHAR *dBuf, UINT16 dataLength, UINT16 noBlocks, UINT16 xferMode)
{
UINT32 *dBufPtr;
UINT16 dLength;
UINT16 y;
UINT16 i;
UINT32 starttime=0, endtime=0, diff=0;
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("MMCTransmit>\r\n")));
#endif
// starttime = v_pOSTReg->oscr0;
// Set up the buffer
dBufPtr = (UINT32 *)dBuf;
//dLength = dataLength;
data_trans_flag = 1;
v_pMMCReg->MMC_I_MASK &= ~0x40;
for (i=0; i<noBlocks; i++)
{
dLength = dataLength;
while(dLength)
{
// RETAILMSG(1, (TEXT("1Before enter write FIFO\r\n")));
// while(!(v_pMMCReg->MMC_I_REG & 0x40))
// {
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
// }
// RETAILMSG(1, (TEXT("after enter write FIFO\r\n")));
if(dLength%32==0)
{
for(y = 0; y<8; y++)
{
v_pMMCReg->MB_TXFIFO = *dBufPtr;
// RETAILMSG(1, (TEXT("MMCTransmit -- get data dBufPtr[%d] = 0x%x\r\n"), y, *dBufPtr));
dBufPtr++;
dLength-=4;
}
InterruptDone(SYSINTR_SDMMC);
}
else
{ v_pMMCReg->MMC_PRTBUF= BUFF_PARTIAL_FULL;
for(y = 0; y<dLength; y++)
{
v_pMMCReg->MB_TXFIFO = *dBufPtr;
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("MMCTransmit!! -- get data dBufPtr[%d] = 0x%x\r\n"), y, *dBufPtr));
#endif
dBufPtr++;
dLength-=4;
}
}
}
} //for
v_pMMCReg->MMC_I_MASK |= 0x40; //disable this tranmit request interrupt
v_pMMCReg->MMC_I_MASK &=~0x1; // Data Transfer Done
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
v_pMMCReg->MMC_I_MASK |=0x1;
InterruptDone(SYSINTR_SDMMC);
// MMC Prog Done
v_pMMCReg->MMC_I_MASK &=~0x2;
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
v_pMMCReg->MMC_I_MASK = 0xFF;
InterruptDone(SYSINTR_SDMMC);
// RETAILMSG(1, (TEXT( "DATA_TRAN_DONE done!!!\r\n")));
data_trans_flag = 0;
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("MMCTransmit<\r\n")));
#endif
//endtime = v_pOSTReg->oscr0;
/*
if(endtime<starttime)
diff = (0xffffffff - starttime) + endtime;
else
diff = endtime-starttime;
total += diff;
NKDbgPrintfW(TEXT("total is %d\r\n"),total);
*/
return MMC_NO_ERROR;
}
/***************************************************************************
* Name: MMCReceive - Handle data from target to host
*
* Description:
* Read data from the device. This routine handles single
* block (READ SINGLE BLOCK command) or multiple blocks (READ
* MULTIPLE BLOCK command) data transfer.
*
* Input:
* pc Controller structure
* dataLength Data block length
* noBLocks Number of sectors to transfer
* xferMode Single or mulitiple mode transfer
*
* Output:
* Data Buffer is filled
*
* Return:
* MMC status code
*
***************************************************************************/
MMC_CC MMCReceive(UCHAR *dBuf, UINT16 dataLength, UINT16 noBlocks, UINT16 xferMode)
{
volatile UCHAR *pBuf;
UINT16 dLength;
int i;
int alignment;
pBuf = (UCHAR *)dBuf;
v_pMMCReg->MMC_I_MASK &= ~0x20;
data_trans_flag = 1;
for (i=0; i<noBlocks; i++)
{
dLength = dataLength;
while (dLength)
{
alignment = (DWORD)pBuf & 0x3;
// If the buffer not 32-bit aligned, we need to align the buffers, then continue with 32-bit copies
if ((alignment == 1) || (alignment == 5))
{
if (dLength >= 32)
{
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
*pBuf = *pMMC_RX_Fifo; // 1 BYTE
*(UINT16 *)(pBuf + 1) = *(UINT16 *)pMMC_RX_Fifo; // 2 BYTES
*(UINT32 *)(pBuf + 3) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 7) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0xb) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0xf) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x13)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x17)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x1b)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(pBuf + 0x1f) = *pMMC_RX_Fifo; // 1 BYTE
pBuf += 32;
dLength-= 32;
InterruptDone(SYSINTR_SDMMC);
} else
{
while (dLength > 0)
{
*pBuf++ = *pMMC_RX_Fifo;
dLength--;
}
}
} else if ((alignment == 3) || (alignment == 7))
{
if (dLength >= 32)
{
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
*pBuf = *pMMC_RX_Fifo; // 1 BYTE
*(UINT32 *)(pBuf + 1) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 5) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 9) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0xd) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x11)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x15)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x19)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT16 *)(pBuf + 0x1d)= *(UINT16 *)pMMC_RX_Fifo; // 2 BYTES
*(pBuf + 0x1f) = *pMMC_RX_Fifo; // 1 BYTE
pBuf += 32;
dLength-= 32;
InterruptDone(SYSINTR_SDMMC);
} else
{
while (dLength > 0)
{
*pBuf++ = *pMMC_RX_Fifo;
dLength--;
}
}
}else if ((alignment == 2) || (alignment == 6))
{
if (dLength >= 32)
{
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
*(UINT16 *)pBuf = *(UINT16 *)pMMC_RX_Fifo; // 2 BYTES
*(UINT32 *)(pBuf + 2) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 6) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0xa) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0xe) = *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x12)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x16)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT32 *)(pBuf + 0x1a)= *(UINT32 *)pMMC_RX_Fifo; // 4 BYTES
*(UINT16 *)(pBuf + 0x1e)= *(UINT16 *)pMMC_RX_Fifo; // 2 BYTES
pBuf += 32;
dLength-= 32;
InterruptDone(SYSINTR_SDMMC);
} else
{
while (dLength > 0)
{
*pBuf++ = *pMMC_RX_Fifo;
dLength--;
}
}
}
else
{
if (dLength >= 32)
{
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
*(UINT32 *) pBuf = *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 4) = *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 8) = *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 0xc) = *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 0x10)= *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 0x14)= *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 0x18)= *(UINT32 *)pMMC_RX_Fifo;
*(UINT32 *)(pBuf + 0x1C)= *(UINT32 *)pMMC_RX_Fifo;
pBuf += 32;
dLength -= 32;
InterruptDone(SYSINTR_SDMMC);
} else
{
while (dLength > 0)
{
*pBuf++ = *pMMC_RX_Fifo;
dLength--;
}
}
}
}
}
v_pMMCReg->MMC_I_MASK |= 0x20;
v_pMMCReg->MMC_I_MASK &= ~0x1; // Data Transfer Done
WaitForSingleObject(gSDMMCIntrEvent, INFINITE);
v_pMMCReg->MMC_I_MASK = 0xFF;
InterruptDone(SYSINTR_SDMMC);
// NKDbgPrintfW(TEXT("MMCReceive -- data transfer done interrupt\r\n"));
// v_pMMCReg->MMC_STRPCL = STOP_CLOCK; // stop clock
// while((v_pMMCReg->MMC_STAT & CLOCK_ENABLE )); // wait for clock to stop
data_trans_flag = 0;
// NKDbgPrintfW(TEXT("MMCReceive -- wait for STOP_CLOCK %x\r\n"), v_pMMCReg->MMC_STAT);
return MMC_NO_ERROR;
}
/***************************************************************************
* Name: MMCSetupXfer
*
* Description:
* Set up information and configure the MMC controller
*
* Input:
* pc Device controller structure
* cmdIndex Command index
* noBlocks Number of blocks to transfer
* respType Type of response
*
* Output:
* All related Registers are update
*
* Return:
* None
*
***************************************************************************/
SDVOID MMCSetupXfer( UINT16 cmdIndex, UINT16 nBlocks, UINT16 respType)
{
UINT16 cmdDatContReg;
UINT16 blkLength;
UINT16 noBlocks = nBlocks;
cmdDatContReg = NO;
blkLength = 0;
setupMMcHostDataRegister(cmdIndex, &cmdDatContReg, &noBlocks, &blkLength);
if (cmdIndex != SSTOP_TRANSMISSION)
{
/* If None Data Transfer type, just skip */
if ( cmdDatContReg != NO )
{
/* BLOCK LENGTH */
v_pMMCReg->MMC_BLKLEN = blkLength;
/* NUMBER OF BLOCK */
v_pMMCReg->MMC_NUMBLK = noBlocks;
}
}
/* COMMAND DATA */
cmdDatContReg |= respType;
/* Set up the hardware */
v_pMMCReg->MMC_CMDAT = cmdDatContReg;
}
/***************************************************************************
* Name: MMCPrepareAndSetup
*
* Description:
* Set up information and Send the command to MMC card
*
* Input:
* pc Device controller structure
* Cmd Command index
* Arg Argument
* noBlocks Number of blocks to transfer
* respType Type of response
*
* Output:
* Command is written to the device
*
* Return:
* MMC status code
*
***************************************************************************/
SDBOOL MMCPrepareAndSetup(UINT32 Arg, UINT16 Cmd, UINT16 noBlocks, UINT16 Resp)
{
/* Stop the clock to set up the requested information */
// if ( !stopMMCClock() )
// return NO;
#ifdef NMD_DEBUG
RETAILMSG(1, (TEXT("MMCPrepareAndSetup>cmd %x arg %x HW_PWRUP %x\r\n"), Cmd, Arg,HW_PWRUP ));
#endif
if (HW_PWRUP == TRUE)
{
HW_PWRUP= FALSE;
mmc_init_setup();
}
if( (Cmd == XLLP_MMC_CMD11) ||
(Cmd == XLLP_MMC_SPICMD17) ||
(Cmd == XLLP_MMC_CMD18) ||
(Cmd == XLLP_SD_ACMD13 ) ||
(Cmd == XLLP_SD_ACMD51) ||
(Cmd == XLLP_MMC_CMD20) ||
(Cmd == XLLP_MMC_SPICMD24) ||
(Cmd == XLLP_MMC_CMD25) )
{
if(Cmd == XLLP_SD_ACMD13)
XllpMmcSdSetupXCmd(v_pMMCReg, (XLLP_INT32_T)(DEFAULT_BLK_LENGTH >> 3), (XLLP_INT32_T)(DEFAULT_BLK_LENGTH >> 3), 0xFFFF);
else
if(Cmd == XLLP_SD_ACMD51)
XllpMmcSdSetupXCmd(v_pMMCReg, (XLLP_INT32_T)8, (XLLP_INT32_T)8, 0xFFFF);
else
XllpMmcSdSetupXCmd(v_pMMCReg, (XLLP_INT32_T)(noBlocks * 512), (XLLP_INT32_T)512, 0xFFFF);
}
XllpMmcSdSetupCmd(v_pMMCReg, Cmd, Arg, 64, FALSE);
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("MMCPrepareAndSetup<\r\n")));
#endif
return YES;
}
/***************************************************************************
* Name: checkCardBusy
*
* Description:
* Test the READY/BUSY status of the MMC card.
*
* Input:
* UINT16 inData not used
*
* Output:
* None
*
* Return:
* True or False
*
***************************************************************************/
SDBOOL checkCardBusy(UINT16 inData)
{
UINT32 dStatus, dtimer;
#ifdef NMD_DEBUG
RETAILMSG(1, (TEXT("checkCardBusy>\r\n")));
#endif
dtimer = 0x200;
/*
Wait for BUSY to go off before the next transfer. The
device may very well be programmed data into the flash memory.
*/
while ( dtimer )
{
/* Get status */
dStatus = v_pMMCReg->MMC_STAT;
/* Check for the availability of the device for next transfer */
if ((dStatus & DONE_PROG_RDWR) || (dStatus & DONE_WDATA_XFER) )
return YES;
dtimer--;
}
#ifdef NMD_DEBUG1
RETAILMSG(1, (TEXT("checkCardBusy<\r\n")));
#endif
/* The device is busy ... */
return NO;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -