⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lpc177x_8x_mci.c

📁 LPC1788的USBHOST的FATFS移植
💻 C
📖 第 1 页 / 共 4 页
字号:
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 + -