📄 mmc_samplecode.txt
字号:
for (ij = 0; ij < 0x200; ij++ )
{
dStatus = getMMCStatus();
if ( dStatus & END_CMD_RES )
{
break;
}
}
/* Ramp-up time */
OS_WAIT(55);
}
/*******************************************************************************
* Name: mmcReset - Initialize the card
*
* Description:
* Resets the cards and the MMC or SPI HW port.
* It must be called after power on before any other commands.
*
* This function sends reset command (CMD0) to the card and waits for the
* card to complete the initialization process by polling its status using
* send_op_condition command (CMD1) to complete its reset process.
*
* In MMC mode, this function can be used to query a card stack for the
* the common voltage range or to set a voltage range and initialize
* the cards to be ready.
*
*
*
* Input:
* setupInfo In MMC mode, Host operating voltage range.
*
* Output:
* Initialization process is finished.
*
* Returns:
* Completion code
*
********************************************************************************/
MMC_CC mmcReset( PDEVICE_CONTROLLER pc, ULONG setupInfo )
{
MMC_CC resErr = 0;
UINT32 cardType;
UINT16 sdFlag;
UINT16 readyFlag;
UINT16 i;
pc->timer = (RESET_DELAY << 2);
cardType = NO;
readyFlag = NO;
/* Reset all devices on the bus. */
mmcCommandAndResponse ( pc,
0L,
GO_IDLE_STATE,
0,
R0 );
for (i = 0; i < (CID_BYTE_LENGTH/2); pc->LastResponse[i++] = 0); /* Clear buffer */
/* Delay it for awhile */
OS_WAIT(25);
sdFlag = NO;
/* Wait for all cards to be ready */
while (pc->timer)
{
/* There is no way to tell what type of the card is at this
point. The command CMD1 is sent first to test the card.
Because the MMC card is always responded to CMD1, if there
is no response, or an error, on the return, we could assume
that the card is not MMC card, the application command ACMD41
will be sent next to test for SD card.
*/
/* Now, check for MMC card. SD do not support CMD1 in MMC mode. */
if (!sdFlag) /* The current card may be an MMC card */
{
/* Check for MMC card. */
resErr = mmcCommandAndResponse ( pc,
setupInfo,
SEND_OP_COND,
0,
R3 );
/* Check if the card is an MMC card. */
if (resErr == MMC_NO_ERROR)
{
/* Got the response from the card. */
/* The card is indeed an MMC card. */
cardType = MMC_TYPE;
readyFlag = to_WORD((UCHAR *)&pc->LastResponse[0]);
}
/* CMD1 failed. There are two ways to explain this:
1. SD card seems not to respond to CMD1 at all (MMC mode).
Therefore, based on the error, this could be an SD card.
Try ACMD41 command to verify this claim.
2. There is no card in the slot.
*/
/* Try SD application command. This application command should
return an error. It is unclear why the card returns an error
after CMD1. Is it a firmware bug? or...
Whatever that error is, just ignore it.
You can tell very much the card is an SD card because of this
error.
*/
else if (resErr == MMC_CARD_IS_NOT_RESPONDING)
{
/* If no card presents, the error should be MMC_CARD_IS_NOT_RESPONDING. */
if (resErr == MMC_CARD_IS_NOT_RESPONDING)
{
/* No card present, just return */
pc->error_code = MMC_INTERFACE_ERROR;
return MMC_INTERFACE_ERROR;
}
}
else
{
/* For other errors, just return. */
pc->error_code = MMC_INTERFACE_ERROR;
return MMC_INTERFACE_ERROR;
}
}
/* Time out error on card response. There may be no card presented. */
if (resErr == MMC_CARD_IS_NOT_RESPONDING)
{
pc->error_code = MMC_INTERFACE_ERROR;
return MMC_INTERFACE_ERROR;
}
if ( resErr == MMC_NO_ERROR ) /* If no error */
{
/* Make sure all cards are ready */
if ( (readyFlag & CARD_READY_FLAG) )
{
break;
}
pc->timer--;
OS_WAIT(1); /* Delay it for awhile */
if ( !pc->timer )
{
pc->error_code = MMC_CARD_IS_NOT_READY;
return MMC_CARD_IS_NOT_READY;
}
}
}
/* Assign IDs to all devices found */
i = NO;
for (;;)
{
/* Get device information and assign an RCA to it. */
if ( mmcIdentify (pc, cardType, i) != MMC_NO_ERROR )
{
/* There isn't any more device found */
break;
}
/* Check for SD card */
if (cardType == SD_TYPE)
{
/* The RCA is returned in pc->LastResponse[4] */
pc->drive[i].RCA = pc->LastResponse[4];
}
else
{
/* For MMC card in MMC mode, the RCA is the (drive number + 1) */
pc->drive[i].RCA = (UINT16)((UINT16)i + 1);
}
/* Save the card type */
pc->drive[i].drv_type = cardType;
i++; /* Next device */
if (i >= (UINT16)drvs_per_controller[pc->controller_number])
break;
MMCSelectController(pc->controller_number, i);
}
/* Make sure there is at least one card on the bus */
if ( i == NO )
{
/* No card found */
return MMC_INTERFACE_ERROR;
}
pc->error_code = MMC_NO_ERROR;
return MMC_NO_ERROR;
}
/***********************************************************************************
* Name: mmcIdentify
*
* Description:
* Available in MMC mode only. Identifiies and assigns an RCA
* for a selected MMC card on the bus.
*
* This function starts card identification cycle and (if a
* valid response is received) assigns the RCA of the identified
* card.
*
* Input:
* pc Device controller structure
* cardID Card number for the identified card.
* cardType Type of the card (MMC, SD, etc.)
*
* Output:
* The card is assigned with an RCA.
*
* Returns:
* Completion code
*
************************************************************************************/
MMC_CC mmcIdentify (PDEVICE_CONTROLLER pc, UINT32 cardType, UINT16 cardID)
{
MMC_CC resErr;
/* Request any card to send the CID information */
resErr = mmcCommandAndResponse ( pc,
0L,
ALL_SEND_CID,
0,
R2 );
if ( resErr != MMC_NO_ERROR )
{
pc->error_code = (UINT16)resErr;
return resErr;
}
/* Check for SD card */
if (cardType == SD_TYPE)
{
/* For SD card, the relative address is sent back
in the response pc->LastResponse. If the command
is executed correctly, the RCA is at offset 4
from the starting address of the response.
*/
resErr = mmcCommandAndResponse ( pc,
0L,
SET_RELATIVE_ADDR,
0,
R6);
/* The RCA is returned in pc->LastResponse[4] */
}
else
{
/* Assgin an ID to the device. The assigned RCA can be choose
as any 16-bit integer number. To make this assignment as
simplest as possible, the RCA assignment is calculating
by adding an 1 to the given cardID. The formula is shown
below:
assigned RCA = cardId + 1
*/
resErr = mmcCommandAndResponse ( pc,
((((ULONG)cardID) + 1L) << 16),
SET_RELATIVE_ADDR,
0,
R1 );
}
pc->error_code = (UINT16)resErr;
return resErr;
}
/***************************************************************************
* Name: MMCCommandAndResponse - Send the command to the MMC card
*
* Description:
* Send the command to the MMC card
*
* Input:
* pc Device information structure
* Cmd MMC Command
* Arg MMC Argument
* noBlocks Number of blocks to transfer
* Resp Response Type
*
* Output:
* Command is sent and Response is analyzed
*
* Return:
* MMC Completion Code
*
***************************************************************************/
MMC_CC mmcCommandAndResponse(PDEVICE_CONTROLLER pc, UINT32 Arg, UINT16 Cmd, UINT16 noBlocks, RESP_TYPE Resp )
{
MMC_CC resErr;
INT16 i;
/* Setup the command */
if ( Resp == R6 )
{
if ( !MMCPrepareAndSetup(Arg, Cmd, noBlocks, R1) )
return MMC_INTERFACE_ERROR;
}
else
{
if ( !MMCPrepareAndSetup(Arg, Cmd, noBlocks, (UINT16)Resp) )
return MMC_INTERFACE_ERROR;
}
if ( !Resp ) /* Command without response (R0) */
return MMC_NO_ERROR;
for (i = 0; i < (CID_BYTE_LENGTH>>1); i++)
pc->LastResponse[i] = 0;/* Clear buffer */
/* Check the response */
resErr = MMCReceivedResponse( pc, Resp );
if ( resErr == MMC_NO_ERROR)
{
if ( (Resp == R1) || (Resp == R6) )
resErr = MMCAnalysisResponse(pc, Resp);
}
return resErr;
}
SDBOOL MMCPrepareAndSetup(UINT32 Arg, UINT16 Cmd, UINT16 noBlocks, UINT16 Resp)
{
UINT16 crcDATA;
crcDATA = calculateCmdCRC(Arg, Cmd);
/* Setup the command */
MMCSendCommand( Arg, Cmd, crcDATA );
return YES;
}
/***************************************************************************
* Name: MMCSendCommand
*
* Description:
*
* Input:
* portAddress Base Address
* cmd Command index
* arg Argument
*
* Output:
* 6-byte command is sent to the card
*
* Return:
* Complete code
*
* Function: send the command to MMC card. CRC is not needed for
* the FPGA controller.
*
***************************************************************************/
SDVOID MMCSendCommand( UINT32 Arg, UINT16 Cmd, UINT16 crcDATA)
{
UINT16 dtmp;
dtmp = (UINT16)crcDATA;
/* Set up the argument. */
dtmp = (UINT16)(Arg >> 16);
SDWRITE_DATA16((portAddress+ARGUMENT_HI_REG), dtmp);
dtmp = (UINT16)(Arg & 0xFFFF);
SDWRITE_DATA16((portAddress+ARGUMENT_LO_REG), dtmp);
/* Set up the command. */
dtmp = (UINT16)(Cmd & 0x7F);
SDWRITE_DATA16((portAddress+CMD_REG), dtmp);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -