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

📄 lpc177x_8x_mci.c

📁 NXPl788上lwip的无操作系统移植,基于Embest开发板
💻 C
📖 第 1 页 / 共 5 页
字号:
 * @brief 		Do initialization for the card in the slot
 *
 * @details		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. <<<KHOA_110708: checking>>>
 *
 *				This is followed Figure 4-2: Card Initialization and
 *				Identification Flow (SD mode) in Physical Layer Simplified
 *				Specification Version 2.00 document		
 *
 * @param		None
 *
 * @return 		MCI_FUNC_OK if success
 ****************************************************************************/
int32_t MCI_CardInit( void )
{
	uint32_t i;
	int32_t 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) /* Ver2.00 or later*/
	{
		//Check in case of High Capacity Supporting Host
		if ((retval = MCI_Acmd_SendOpCond(1)) == MCI_FUNC_OK)
		{
            MCI_CardType = MCI_SDSC_V2_CARD;//SDSC
            
            if(CCS )
            {
    			MCI_CardType = MCI_SDHC_SDXC_CARD;//SDHC or SDXC 
            }

			return MCI_FUNC_OK;	/* Found the card, it's a hD */
		}
	}

	if(retval != MCI_FUNC_OK) /* voltage mismatch (ver2.00)or ver1.X SD Card or not SD Card*/
	{
		
		//Check in case of Standard Capacity Supporting Host
		if ((retval = MCI_Acmd_SendOpCond(0)) == MCI_FUNC_OK)
		{
			MCI_CardType = MCI_SDSC_V1_CARD;//Support Standard Capacity only

			return MCI_FUNC_OK;	/* 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_FUNC_OK;	/* Found the card, it's a MMC */
		}
	}

	/* tried both MMC and SD card, give up */
	return MCI_FUNC_OK;
}


/************************************************************************//**
 * @brief 		Get the type of card that is currently used in the slot
 *
 * @param		None
 *
 * @return 		Card Type: MMC Card or SD card
 ****************************************************************************/
en_Mci_CardType MCI_GetCardType(void)
{
	return MCI_CardType;
}


/************************************************************************//**
 * @brief 		Get the all the Identifier (CID) of the card by sending the 
 *				CMD2 (ALL_SEND_CID) command. Then parse 4-byte data obtained
 *				from the card by the CID meaning.	
 *
 * @param[out]	cidValue the CID Result after parsing the data from the card
 *
 * @return 		MCI_FUNC_OK if all success
 ****************************************************************************/
int32_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], ALLOW_CMD_TIMER);

		/* 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], ALLOW_CMD_TIMER);

		/* 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;
}


/************************************************************************//**
 * @brief 		Set the address for the card in the slot by sending CMD3 
 *				(SET_RELATIVE_ADDR) command. To get the address of the card
 *				currently in used, needs to call MCI_GetCardAddress()
 *
 * @param		None
 *
 * @return 		MCI_FUNC_OK if all success
 ****************************************************************************/
int32_t MCI_SetCardAddress( void )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue;
	uint32_t CmdArgument;

	int32_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_SDSC_V1_CARD) ||
		(MCI_CardType == MCI_SDSC_V2_CARD) ||
		(MCI_CardType == MCI_SDHC_SDXC_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, CmdArgument, EXPECT_SHORT_RESP, &respValue, ALLOW_CMD_TIMER);

		if(respStatus & MCI_CMD_TIMEOUT)
		{
			retval = MCI_FUNC_TIMEOUT;
		}
		else if(!(XSHIFT_(respValue, MCI_CARDSTATUS_READYFORDATA_P0S) & 0x01))
		{
			retval = MCI_FUNC_NOT_READY;
		}
		else if((CARDSTATEOF(respValue) != MCI_CARDSTATE_IDENDTIFIED))
		{
			retval = MCI_FUNC_ERR_STATE;
		}
		else
		{
			CardRCA = respValue & 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;
}


/************************************************************************//**
 * @brief 		Get the address for the card in the slot
 *
 * @param		None
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		This function must be called after MCI_SetCardAddress() executing
 ****************************************************************************/
uint32_t MCI_GetCardAddress(void)
{
	return CardRCA;
}


/************************************************************************//**
 * @brief 		Get the Card-Specific Data of in-slot card by sending CMD9
 *				(SEND_CSD) command
 *
 * @param[out]	csdVal a buffer stored the value of CSD obtained from the card
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		CMD9 (SEND_CSD) command should be sent only at standby state 
 *				(STBY) after CMD3
 ****************************************************************************/
int32_t MCI_GetCSD(uint32_t* csdVal)
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];
	uint32_t CmdArgument;

	if ((MCI_CardType == MCI_SDSC_V1_CARD) ||
		(MCI_CardType == MCI_SDSC_V2_CARD) ||
		(MCI_CardType == MCI_SDHC_SDXC_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], ALLOW_CMD_TIMER);

		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);
}


/************************************************************************//**
 * @brief 		Select the card by the specified address. This is done by sending
 *				out the CMD7 with the address argument to needed card
 *
 * @param		None
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		CMD7 (SELECT_CARD) command should be sent after CMD9 ((SEND_CSD).
 *				The state will be inter-changed between STBY to TRANS by this 
 *				CMD7 command
 ****************************************************************************/
int32_t MCI_Cmd_SelectCard( void )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];
	uint32_t CmdArgument;

	int32_t retval = MCI_FUNC_FAILED;

	if ((MCI_CardType == MCI_SDSC_V1_CARD) ||
			(MCI_CardType == MCI_SDSC_V2_CARD) ||
			(MCI_CardType == MCI_SDHC_SDXC_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], ALLOW_CMD_TIMER);

		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;
}


/************************************************************************//**
 * @brief 		Get the status of the card. The return is from the card.
 *				By sending CMD13 (SEND_STATUS), the status of the card
 *				will be responded from card addressed
 *
 * @param[out]	cardStatus the status returned from the card
 *
 * @return 		MCI_FUNC_OK if all success
 ****************************************************************************/
int32_t MCI_GetCardStatus(int32_t* cardStatus)
{
	uint32_t i;
	uint32_t retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];
	uint32_t CmdArgument;

	int32_t retval = MCI_FUNC_FAILED;

	if ((MCI_CardType == MCI_SDSC_V1_CARD) ||
		(MCI_CardType == MCI_SDSC_V2_CARD) ||
		(MCI_CardType == MCI_SDHC_SDXC_CARD)) 
	{
		CmdArgument = CardRCA;
	}
	else			/* if MMC or unknown card type, use default RCA addr. */
	{
		CmdArgument = 0x00010000;
	}

	/* Note that, since it's called after the block write and read, this timeout
	is important based on the clock you set for the data communication. */
	retryCount = 0x20;

	while ( retryCount > 0 )
	{
		/* Send SELECT_CARD command before read and write */
		LPC_MCI->CLEAR |= (MCI_CMD_TIMEOUT | MCI_CMD_CRC_FAIL | MCI_CMD_RESP_END);

		respStatus = MCI_CmdResp(CMD13_SEND_STATUS, CmdArgument, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], ALLOW_CMD_TIMER);

		if(respStatus)
		{
			retval = MCI_FUNC_FAILED;
		}
		else if(!(respValue[0] & _SHIFT(MCI_CARDSTATUS_READYFORDATA_P0S)))
		{
			retval = MCI_FUNC_NOT_READY;
		}
		else
		{
			/* The ready bit should be set, it should be in either TRAN or RCV state now */
			if(cardStatus != NULL)
			{
				*cardStatus = respValue[0];
			}

			return MCI_FUNC_OK;
		}

		retryCount--;
		for ( i = 0; i < 0x10; i++ );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -