📄 lpc177x_8x_mci.c
字号:
uint32_t MCI_Cmd_SendACMD( void )
{
uint32_t i, retryCount;
uint32_t CmdArgument;
uint32_t respStatus;
uint32_t respValue[4];
uint32_t retval = MCI_FUNC_FAILED;
if (MCI_CardType == MCI_SD_CARD)
{
CmdArgument = CardRCA; /* Use the address from SET_RELATIVE_ADDR cmd */
}
else /* if MMC or unknown card type, use 0x0. */
{
CmdArgument = 0x00000000;
}
retryCount = 20;
while ( retryCount > 0 )
{
respStatus = MCI_CmdResp(CMD55_APP_CMD, CmdArgument, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], 0);
if(respStatus != 0)
{
retval = MCI_FUNC_FAILED;
}
else if (respValue[0] & CARD_STATUS_ACMD_ENABLE)
{
retval = MCI_FUNC_OK;
break;
}
else
{
retval = MCI_FUNC_NOT_READY;
}
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return retval;
}
/******************************************************************************
** Function name: MCI_Cmd_SendAcmdOpCond
**
** Descriptions: If Send_OP_Cond is timeout, it's not a MMC card, try
** this combination to see if we can communicate with
** a SD card.
**
** parameters: hcsVal: to input the Host Capacity Support
** Returned value: true or false, true if card has been initialized.
**
******************************************************************************/
uint32_t MCI_Cmd_SendAcmdOpCond(uint8_t hcsVal)
{
uint32_t i, retryCount;
uint32_t respStatus, argument;
uint32_t respValue[4];
uint32_t retval = MCI_FUNC_FAILED;
argument = OCR_INDEX | (argument << MCI_ACMD41_HCS_POS);
/* timeout on SEND_OP_COND command on MMC, now, try SEND_APP_OP_COND
command to SD */
retryCount = 0x200; /* reset retry counter */
while ( retryCount > 0 )
{
/* Clear Open Drain output control for SD */
MCI_SetOutputMode(MCI_OUTPUT_MODE_PUSHPULL);
for ( i = 0; i < 0x3000; i++ );
if ((retval = MCI_Cmd_SendACMD()) == MCI_FUNC_OK)
{
respStatus = MCI_CmdResp(ACMD41_SEND_APP_OP_COND, argument, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], 0);
if(respStatus & MCI_CMD_TIMEOUT)
{
retval = MCI_FUNC_TIMEOUT;
}
else if (!(respValue[0] & 0x80000000))
{
retval = MCI_FUNC_BUS_NOT_IDLE;
}
else
{
retval = MCI_FUNC_OK;
break;
}
}
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return retval;
}
#if 0
/******************************************************************************
** Function name: MCI_CardInit
**
** Descriptions: Try CMD1 first for MMC, if it's timeout, try CMD55
** and CMD41 for SD, if both failed, initialization faliure,
** bailout with unknown card type. Otherwise, return the
** card type, either MMC or SD.
**
** parameters: None
** Returned value: Card type.
**
******************************************************************************/
uint32_t MCI_CardInit( void )
{
uint32_t i, retval = MCI_FUNC_FAILED;
MCI_CardType = MCI_CARD_UNKNOWN;
if (MCI_CardReset() != MCI_FUNC_OK)
{
return MCI_FUNC_FAILED;
}
/* Set Open Drain output control for MMC */
MCI_SetOutputMode(MCI_OUTPUT_MODE_OPENDRAIN);
for ( i = 0; i < 0x3000; i++ );
/* Try CMD1 first for MMC, if it's timeout, try CMD55 and CMD41 for SD,
if both failed, initialization faIlure, bailout. */
if (MCI_Cmd_SendOpCond() == MCI_FUNC_OK)
{
MCI_CardType = MCI_MMC_CARD;
return MCI_CardType; /* Found the card, it's a MMC */
}
/* Clear Open Drain output control for SD */
MCI_SetOutputMode(MCI_OUTPUT_MODE_PUSHPULL);
if (MCI_Cmd_SendAcmdOpCond(0) == MCI_FUNC_OK)
{
MCI_CardType = MCI_SD_CARD;
return MCI_CardType; /* Found the card, it's a SD */
}
/* tried both MMC and SD card, give up */
return MCI_CardType;
}
#else
/******************************************************************************
** Function name: MCI_CardInit
**
** Descriptions: Try CMD1 first for MMC, if it's timeout, try CMD55
** and CMD41 for SD, if both failed, initialization faliure,
** bailout with unknown card type. Otherwise, return the
** card type, either MMC or SD.
** This is followed Figure 4-2: Card Initialization and
** Identification Flow (SD mode) in Physical Layer Simplified
** Specification Version 2.00 document
**
** parameters: None
** Returned value: Card type.
**
******************************************************************************/
uint32_t MCI_CardInit( void )
{
uint32_t CmdArgument;
uint32_t i, retval = MCI_FUNC_FAILED;
MCI_CardType = MCI_CARD_UNKNOWN;
if (MCI_CardReset() != MCI_FUNC_OK)
{
return MCI_FUNC_FAILED;
}
/* Clear Open Drain output control for SD */
MCI_SetOutputMode(MCI_OUTPUT_MODE_PUSHPULL);
for ( i = 0; i < 0x3000; i++ );
retval = MCI_Cmd_SendIfCond();
if(retval == MCI_FUNC_BAD_PARAMETERS)
{
//Unknow card is unusable
return retval;
}
if(retval == MCI_FUNC_OK)
{
//Check in case of High Capacity Supporting Host
if ((retval = MCI_Cmd_SendAcmdOpCond(1)) == MCI_FUNC_OK)
{
MCI_CardType = MCI_SD_CARD;//Support High Capacity
return MCI_CardType; /* Found the card, it's a hD */
}
}
if(retval != MCI_FUNC_OK)
{
//Check in case of Standard Capacity Supporting Host
if ((retval = MCI_Cmd_SendAcmdOpCond(0)) == MCI_FUNC_OK)
{
MCI_CardType = MCI_SD_CARD;//Support Standard Capacity only
return MCI_CardType; /* Found the card, it's a SD */
}
}
if(retval != MCI_FUNC_OK)
{
/* Set Open Drain output control for MMC */
MCI_SetOutputMode(MCI_OUTPUT_MODE_OPENDRAIN);
for ( i = 0; i < 0x3000; i++ );
/* Try CMD1 first for MMC, if it's timeout, try CMD55 and CMD41 for SD,
if both failed, initialization faIlure, bailout. */
if (MCI_Cmd_SendOpCond() == MCI_FUNC_OK)
{
MCI_CardType = MCI_MMC_CARD;
return MCI_CardType; /* Found the card, it's a MMC */
}
}
/* tried both MMC and SD card, give up */
return MCI_CardType;
}
#endif
/******************************************************************************
** Function name: MCI_GetCardType
**
** Descriptions:
**
** parameters: None
** Returned value: Card type.
**
******************************************************************************/
en_Mci_CardType MCI_GetCardType(void)
{
return MCI_CardType;
}
/******************************************************************************
** Function name: MCI_GetCID
**
** Descriptions: Send CMD2, CMD2_ALL_SEND_CID
**
** parameters: None
** Returned value: If not timeout, return true.
**
******************************************************************************/
uint32_t MCI_GetCID(st_Mci_CardId* cidValue)
{
uint32_t i, retryCount;
uint32_t respStatus;
uint32_t respValue[4];
/* This command is normally after CMD1(MMC) or ACMD41(SD). */
retryCount = 0x200;// 0x20; /* reset retry counter */
while ( retryCount > 0 )
{
#if 1
respStatus = MCI_CmdResp(CMD2_ALL_SEND_CID, 0, EXPECT_LONG_RESP, (uint32_t *)&respValue[0], 0);
/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
//if ((!(respStatus & MCI_CMD_TIMEOUT)) && (!(respStatus & MCI_CMD_CRC_FAIL)))
if (!(respStatus & MCI_CMD_TIMEOUT))
{
// Parsing the data retrieved
if(cidValue != NULL)
{
cidValue->MID = (respValue[0] >> MCI_CID_MANUFACTURER_ID_WPOS) & MCI_CID_MANUFACTURER_ID_WBMASK;
cidValue->OID = (respValue[0] >> MCI_CID_OEMAPPLICATION_ID_WPOS) & MCI_CID_OEMAPPLICATION_ID_WBMASK;
cidValue->PNM_H = (respValue[0] >> MCI_CID_PRODUCTNAME_ID_H_WPOS) & MCI_CID_PRODUCTNAME_ID_H_WBMASK;
cidValue->PNM_L = (respValue[1] >> MCI_CID_PRODUCTNAME_ID_L_WPOS) & MCI_CID_PRODUCTNAME_ID_L_WBMASK;
cidValue->PRV = (respValue[2] >> MCI_CID_PRODUCTREVISION_ID_WPOS) & MCI_CID_PRODUCTREVISION_ID_WBMASK;
cidValue->PSN = (((respValue[2] >> MCI_CID_PRODUCTSERIALNUM_ID_H_WPOS) & MCI_CID_PRODUCTSERIALNUM_ID_H_WBMASK) << 8)
| (respValue[3] >> MCI_CID_PRODUCTSERIALNUM_ID_L_WPOS) & MCI_CID_PRODUCTSERIALNUM_ID_L_WBMASK;
cidValue->reserved = (respValue[3] >> MCI_CID_RESERVED_ID_WPOS) & MCI_CID_RESERVED_ID_WBMASK;
cidValue->MDT = (respValue[3] >> MCI_CID_MANUFACTURINGDATE_ID_WPOS) & MCI_CID_MANUFACTURINGDATE_ID_WBMASK;
cidValue->CRC = (respValue[3] >> MCI_CID_CHECKSUM_ID_WPOS) & MCI_CID_CHECKSUM_ID_WBMASK;
cidValue->unused = (respValue[3] >> MCI_CID_UNUSED_ID_WPOS) & MCI_CID_UNUSED_ID_WBMASK;
}
return MCI_FUNC_OK; /* response is back and correct. */
}
#else
respCmdValue[0] = 0x00000000;
respCmdValue[1] = 0x00000000;
respCmdValue[2] = 0x00000000;
respCmdValue[3] = 0x00000000;
respStatus = MCI_CmdResp(CMD2_ALL_SEND_CID, 0, EXPECT_LONG_RESP, (uint32_t *)&respCmdValue[0], 0);
/* bit 0 and bit 2 must be zero, or it's timeout or CRC error */
if (!(respStatus & MCI_CMD_TIMEOUT))
{
// Parsing the data retrieved
if(cidValue != NULL)
{
cidValue->MID = (respCmdValue[0] >> MCI_CID_MANUFACTURER_ID_WPOS) & MCI_CID_MANUFACTURER_ID_WBMASK;
cidValue->OID = (respCmdValue[0] >> MCI_CID_OEMAPPLICATION_ID_WPOS) & MCI_CID_OEMAPPLICATION_ID_WBMASK;
cidValue->PNM_H = (respCmdValue[0] >> MCI_CID_PRODUCTNAME_ID_H_WPOS) & MCI_CID_PRODUCTNAME_ID_H_WBMASK;
cidValue->PNM_L = (respCmdValue[1] >> MCI_CID_PRODUCTNAME_ID_L_WPOS) & MCI_CID_PRODUCTNAME_ID_L_WBMASK;
cidValue->PRV = (respCmdValue[2] >> MCI_CID_PRODUCTREVISION_ID_WPOS) & MCI_CID_PRODUCTREVISION_ID_WBMASK;
cidValue->PSN = (((respCmdValue[2] >> MCI_CID_PRODUCTSERIALNUM_ID_H_WPOS) & MCI_CID_PRODUCTSERIALNUM_ID_H_WBMASK) << 8)
| (respCmdValue[3] >> MCI_CID_PRODUCTSERIALNUM_ID_L_WPOS) & MCI_CID_PRODUCTSERIALNUM_ID_L_WBMASK;
cidValue->reserved = (respCmdValue[3] >> MCI_CID_RESERVED_ID_WPOS) & MCI_CID_RESERVED_ID_WBMASK;
cidValue->MDT = (respCmdValue[3] >> MCI_CID_MANUFACTURINGDATE_ID_WPOS) & MCI_CID_MANUFACTURINGDATE_ID_WBMASK;
cidValue->CRC = (respCmdValue[3] >> MCI_CID_CHECKSUM_ID_WPOS) & MCI_CID_CHECKSUM_ID_WBMASK;
cidValue->unused = (respCmdValue[3] >> MCI_CID_UNUSED_ID_WPOS) & MCI_CID_UNUSED_ID_WBMASK;
}
return MCI_FUNC_OK; /* response is back and correct. */
}
#endif
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return MCI_FUNC_TIMEOUT;
}
/******************************************************************************
** Function name: MCI_SetCardAddress
**
** Descriptions: Send CMD3, STE_RELATIVE_ADDR, should after CMD2
**
** parameters: None
** Returned value: TRUE if response is back before timeout.
**
******************************************************************************/
uint32_t MCI_SetCardAddress( void )
{
uint32_t i, retryCount;
uint32_t respStatus;
uint32_t respValue[4];
uint32_t CmdArgument;
uint32_t retval = MCI_FUNC_FAILED;
/* If it's a SD card, SET_RELATIVE_ADDR is to get the address
from the card and use this value in RCA, if it's a MMC, set default
RCA addr. 0x00010000. */
if (MCI_CardType == MCI_SD_CARD)
{
CmdArgument = 0;
}
else /* If it's unknown or MMC_CARD, fix the RCA address */
{
CmdArgument = 0x00010000;
}
retryCount = 0x20; /* reset retry counter */
while ( retryCount > 0 )
{
/* Send CMD3 command repeatedly until the response is back correctly */
respStatus = MCI_CmdResp(CMD3_SET_RELATIVE_ADDR, 0, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], 0);
if(respStatus & MCI_CMD_TIMEOUT)
{
retval = MCI_FUNC_TIMEOUT;
}
else if(!(respValue[0] & _SHIFT(MCI_CARDSTATUS_READYFORDATA_P0S)))
{
retval = MCI_FUNC_NOT_READY;
}
else if((CARDSTATEOF(respValue[0]) != MCI_CARDSTATE_IDENDTIFIED))
{
retval = MCI_FUNC_ERR_STATE;
}
else
{
CardRCA = respValue[0] & 0xFFFF0000; /* Save the RCA value from SD card */
return (MCI_FUNC_OK); /* response is back and correct. */
}
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return retval;
}
/******************************************************************************
** Function name: MCI_GetCSD
**
** Descriptions: CMD9, SEND_CSD cmd, it should be sent only at
** STBY state and after CMD3. See MMC and SD spec. state
** diagram.
**
** parameters: None
** Returned value: Response value
**
******************************************************************************/
uint32_t MCI_GetCSD(uint32_t* csdVal)
{
uint32_t i, retryCount;
uint32_t respStatus;
uint32_t respValue[4];
uint32_t CmdArgument;
if (MCI_CardType == MCI_SD_CARD)
{
CmdArgument = CardRCA;
}
else /* if MMC or unknown card type, use default RCA addr. */
{
CmdArgument = 0x00010000;
}
retryCount = 0x20;
while ( retryCount > 0 )
{
/* Send SET_BLOCK_LEN command before read and write */
LPC_MCI->CLEAR |= (MCI_CMD_TIMEOUT | MCI_CMD_CRC_FAIL | MCI_CMD_RESP_END);
respStatus = MCI_CmdResp(CMD9_SEND_CSD, CmdArgument, EXPECT_LONG_RESP, (uint32_t *)&respValue[0], 0);
if ( !respStatus )
{
if(csdVal != NULL)
{
csdVal[0] = respValue[0];
csdVal[1] = respValue[1];
csdVal[2] = respValue[2];
csdVal[3] = respValue[3];
}
return (MCI_FUNC_OK);
}
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return (MCI_FUNC_FAILED);
}
/******************************************************************************
** Function name: MCI_Cmd_SelectCard
**
** Descriptions: CMD7, SELECT_CARD, should be after CMD9, the state
** will be inter-changed between STBY and TRANS after
** this cmd.
**
** parameters: None
** Returned value: return false if response times out.
**
******************************************************************************/
uint32_t MCI_Cmd_SelectCard( void )
{
uint32_t i, retryCount;
uint32_t respStatus;
uint32_t respValue[4];
uint32_t CmdArgument;
uint32_t retval = MCI_FUNC_FAILED;
if (MCI_CardType == MCI_SD_CARD)
{
CmdArgument = CardRCA;
}
else /* if MMC or unknown card type, use default RCA addr. */
{
CmdArgument = 0x00010000;
}
retryCount = 0x20;
while ( retryCount > 0 )
{
/* Send CMD7_SELECT_CARD command before read and write */
LPC_MCI->CLEAR |= (MCI_CMD_TIMEOUT | MCI_CMD_CRC_FAIL | MCI_CMD_RESP_END);
respStatus = MCI_CmdResp(CMD7_SELECT_CARD, CmdArgument, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], 0);
if(respStatus)
{
retval = MCI_FUNC_FAILED;
}
else if(!(respValue[0] & _SHIFT(MCI_CARDSTATUS_READYFORDATA_P0S)))
{
retval = MCI_FUNC_NOT_READY;
}
else if(CARDSTATEOF(respValue[0]) != MCI_CARDSTATE_STBY)
{
/* Should be in STANDBY state now and ready */
retval = MCI_FUNC_ERR_STATE;
}
else
{
return MCI_FUNC_OK;
}
for ( i = 0; i < 0x20; i++ );
retryCount--;
}
return retval;
}
/******************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -