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

📄 lpc177x_8x_mci.c

📁 LPC1788的USBHOST的FATFS移植
💻 C
📖 第 1 页 / 共 4 页
字号:
** Function name:		MCI_GetCardStatus
**
** Descriptions:		CMD13, SEND_STATUS, the most important cmd to
**						debug the state machine of the card.
**
** parameters:			None
** Returned value:		Response value(card status), true if the ready bit
**						is set in the card status register, if timeout, return
**						INVALID_RESPONSE 0xFFFFFFFF.
**
******************************************************************************/
uint32_t MCI_GetCardStatus(uint32_t* cardStatus)
{
	uint32_t 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;
	}

	/* 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 = 0x2000;

	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], 0);

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

	return retval;
}

/******************************************************************************
** Function name:		MCI_SetBlockLen
**
** Descriptions:		CMD16, SET_BLOCKLEN, called after CMD7(SELECT_CARD)
**						called in the TRANS state.
**
** parameters:			The length of the data block to be written or read.
** Returned value:		true or false, return TRUE if ready bit is set, and it's
**						in TRANS state.
**
******************************************************************************/
uint32_t MCI_SetBlockLen(uint32_t blockLength)
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	uint32_t retval = MCI_FUNC_FAILED;

	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(CMD16_SET_BLOCK_LEN, blockLength, 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_TRAN))
		{
			retval = MCI_FUNC_ERR_STATE;
		}
		else
		{
			return MCI_FUNC_OK;
		}

		for ( i = 0; i < 0x20; i++ );

		retryCount--;
	}

	return retval;
}

/******************************************************************************
** Function name:		MCI_Cmd_SendAcmdBusWidth
**
** Descriptions:		ACMD6, SET_BUS_WIDTH, if it's SD card, we can
**						use the 4-bit bus instead of 1-bit. This cmd
**						can only be called during TRANS state.
**						Since it's a ACMD, CMD55 APP_CMD needs to be
**						sent out first.
**
** parameters:			Bus width value, 1-bit is 0, 4-bit is 10
** Returned value:		true or false, true if the card is still in the
**						TRANS state after the cmd.
**
******************************************************************************/
uint32_t MCI_Cmd_SendAcmdBusWidth( uint32_t buswidth )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	uint32_t retval = MCI_FUNC_FAILED;

	retryCount = 0x20;			/* reset retry counter */

	while ( retryCount > 0 )
	{
		if (MCI_Cmd_SendACMD() == MCI_FUNC_OK)
		{
			respStatus = MCI_CmdResp(CMD6_SET_ACMD_BUS_WIDTH, buswidth, 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_TRAN))
			{
				retval = MCI_FUNC_ERR_STATE;
			}
			else
			{
				return MCI_FUNC_OK;
			}
		}

		for ( i = 0; i < 0x20; i++ );

		retryCount--;
	}

	return retval;
}

/******************************************************************************
** Function name:		MCI_GetCardType
**
** Descriptions:
**
** parameters:			None
** Returned value:		Card type.
**
******************************************************************************/
uint32_t MCI_GetBlockEndFlag(void)
{
	return MCI_Block_End_Flag;
}


/******************************************************************************
** Function name:		MCI_Cmd_StopTransmission
**
** Descriptions:		CMD12, STOP_TRANSMISSION. if that happens, the card is
**						maybe in a unknown state that need a warm reset.
**
** parameters:			None
** Returned value:		true or false, true if, at least, the card status
**						shows ready bit is set.
**
******************************************************************************/
uint32_t MCI_Cmd_StopTransmission( void )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	uint32_t retval = MCI_FUNC_FAILED;

	retryCount = 0x20;

	while ( retryCount > 0 )
	{
		LPC_MCI->CLEAR = 0x7FF;

		respStatus = MCI_CmdResp(CMD12_STOP_TRANSMISSION, 0x00000000, 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
		{
			return MCI_FUNC_OK;
		}

		for ( i = 0; i < 0x20; i++ );

		retryCount--;
	}

	return retval;
}

/******************************************************************************
** Function name:		MCI_Cmd_WriteBlock
**
** Descriptions:		CMD24, WRITE_BLOCK, send this cmd in the TRANS state
**						to write a block of data to the card.
**
** parameters:			block number
** Returned value:		Response value
**
******************************************************************************/
uint32_t MCI_Cmd_WriteBlock( uint32_t blockNum )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	uint32_t retval = MCI_FUNC_FAILED;

	retryCount = 0x20;
	while ( retryCount > 0 )
	{
		LPC_MCI->CLEAR = 0x7FF;

		respStatus = MCI_CmdResp(CMD24_WRITE_BLOCK, blockNum * BLOCK_LENGTH, 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_TRAN))
		{
			retval = MCI_FUNC_ERR_STATE;
		}
		else
		{
			/* ready and in TRAN state */
			return MCI_FUNC_OK;
		}

		for ( i = 0; i < 0x20; i++ );

		retryCount--;
	}

	return retval;				/* Fatal error */
}

/******************************************************************************
** Function name:		MCI_Cmd_ReadSingleBlock
**
** Descriptions:		CMD17, CMD17_READ_SINGLE_BLOCK, send this cmd in the TRANS
**						state to read a block of data from the card.
**
** parameters:			block number
** Returned value:		Response value
**
******************************************************************************/
uint32_t MCI_Cmd_ReadSingleBlock( uint32_t blockNum )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	uint32_t retval = MCI_FUNC_FAILED;

	retryCount = 0x20;
	while ( retryCount > 0 )
	{
		LPC_MCI->CLEAR = 0x7FF;

		respStatus = MCI_CmdResp(CMD17_READ_SINGLE_BLOCK, blockNum * BLOCK_LENGTH, 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_TRAN))
		{
			retval = MCI_FUNC_ERR_STATE;
		}
		else
		{
			/* ready and in TRAN state */
			return MCI_FUNC_OK;
		}

		for ( i = 0; i < 0x20; i++ );

		retryCount--;
	}

	return retval;					/* Fatal error */
}


/******************************************************************************
** Function name:		MCI_WriteBlock
**
** Descriptions:		Set MCI data control register, data length and data
**						timeout, send WRITE_BLOCK cmd, finally, enable
**						interrupt. On completion of WRITE_BLOCK cmd, TX_ACTIVE
**						interrupt will occurs, data can be written continuously
**						into the FIFO until the block data length is reached.
**
** parameters:			block number
** Returned value:		true or false, if cmd times out, return false and no
**						need to continue.
**
******************************************************************************/
uint32_t MCI_WriteBlock(uint8_t* memblock, uint32_t blockNum )
{
	uint32_t i;
	uint32_t DataCtrl = 0;

#if MCI_DMA_ENABLED
	GPDMA_Channel_CFG_Type GPDMACfg;
#endif

	dataSrcBlock = memblock;

	LPC_MCI->CLEAR = 0x7FF;

	LPC_MCI->DATACTRL = 0;

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

	/* Below status check is redundant, but ensure card is in TRANS state
	before writing and reading to from the card. */
	if (MCI_CheckStatus() != MCI_FUNC_OK)
	{
		MCI_Cmd_StopTransmission();

		return(MCI_FUNC_FAILED);
	}

	LPC_MCI->DATATMR = DATA_TIMER_VALUE;

	LPC_MCI->DATALEN = BLOCK_LENGTH;

	MCI_Block_End_Flag = 1;

	MCI_TXEnable();

	if (MCI_Cmd_WriteBlock( blockNum ) != MCI_FUNC_OK)
	{
		return ( MCI_FUNC_FAILED );
	}

#if MCI_DMA_ENABLED
	GPDMACfg.ChannelNum = MCI_DMA_WRITE_CHANNEL;
	// Source memory
	GPDMACfg.SrcMemAddr = (uint32_t)dataSrcBlock;
	// Destination memory
	GPDMACfg.DstMemAddr = 0;
	// Transfer size
	GPDMACfg.TransferSize = DMA_MCI_SIZE;
	// Transfer width
	GPDMACfg.TransferWidth = GPDMA_WIDTH_WORD;
	// Transfer type
	GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
	// Source connection - unused
	GPDMACfg.SrcConn = 0;
	// Destination connection - unused
	GPDMACfg.DstConn = GPDMA_CONN_MCI;
	// Linker List Item - unused
	GPDMACfg.DMALLI = 0;

	// Setup channel with given parameter
	GPDMA_Setup(&GPDMACfg);

	/* Reset terminal counter */
	dmaWrCh_TermianalCnt = 0;

	/* Reset Error counter */
	dmaWrCh_ErrorCnt = 0;

	// Enable GPDMA channel
	GPDMA_ChannelCmd(MCI_DMA_WRITE_CHANNEL, ENABLE);

	//LPC_GPDMACH0->CConfig |= 0xC001 | (0x00 << 1) | (0x01 << 6) | (0x05 << 11);

	/* Write, block transfer, DMA, and data length */
	DataCtrl |= ((1 << 0) | (1 << 3) | (DATA_BLOCK_LEN << 4));
#else
	/* Write, block transfer, and data length */
	DataCtrl |= ((1 << 0) | (DATA_BLOCK_LEN << 4));
#endif

	LPC_MCI->DATACTRL = DataCtrl;

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

	return MCI_FUNC_OK;
}

/******************************************************************************
** Function name:		MCI_ReadBlock
**
** Descriptions:		Set MCI data control register, data length and data
**						timeout, send CMD17_READ_SINGLE_BLOCK cmd, finally, enable
**						interrupt. On completion of READ_SINGLE_BLOCK cmd,
**						RX_ACTIVE interrupt will occurs, data can be read
**						continuously into the FIFO until the block data
**						length is reached.
**
** parameters:			block number
** Returned value:		true or false, if cmd times out, return false and no
**						need to continue.
**
**
******************************************************************************/
uint32_t MCI_ReadBlock(uint8_t* destBlock, uint32_t blockNum )
{
	uint32_t i;
	uint32_t DataCtrl = 0;

#if MCI_DMA_ENABLED
	GPDMA_Channel_CFG_Type GPDMACfg;
#endif

	dataDestBlock = destBlock;

	LPC_MCI->CLEAR = 0x7FF;

	LPC_MCI->DATACTRL = 0;

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

	/* Below status check is redundant, but ensure card is in TRANS state
	before writing and reading to from the card. */
	if ( MCI_CheckStatus() != MCI_FUNC_OK )
	{
		MCI_Cmd_StopTransmission();

		return(MCI_FUNC_FAILED);
	}

	MCI_RXEnable();

	LPC_MCI->DATATMR = DATA_TIMER_VALUE;

	LPC_MCI->DATALEN = BLOCK_LENGTH;

	MCI_Block_End_Flag = 1;

	if ( MCI_Cmd_ReadSingleBlock( blockNum ) != MCI_FUNC_OK )
	{
		return MCI_FUNC_FAILED;
	}

#if MCI_DMA_ENABLED
	GPDMACfg.ChannelNum = MCI_DMA_READ_CHANNEL;
	// Source memory
	GPDMACfg.SrcMemAddr = 0;
	// Destination memory
	GPDMACfg.DstMemAddr = (uint32_t)dataDestBlock;
	// Transfer size
	GPDMACfg.TransferSize = DMA_MCI_SIZE;
	// Transfer width
	GPDMACfg.TransferWidth = GPDMA_WIDTH_WORD;
	// Transfer type
	GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_P2M;
	// Source connection - unused
	GPDMACfg.SrcConn = GPDMA_CONN_MCI;
	// Destination connection - unused
	GPDMACfg.DstConn = 0;
	// Linker List Item - unused
	GPDMACfg.DMALLI = 0;

	// Setup channel with given parameter
	GPDMA_Setup(&GPDMACfg);

	/* Reset terminal counter */
	dmaWrCh_TermianalCnt = 0;

	/* Reset Error counter */
	dmaWrCh_ErrorCnt = 0;

	// Enable GPDMA channel
	GPDMA_ChannelCmd(MCI_DMA_WRITE_CHANNEL, ENABLE);

	//LPC_GPDMACH1->CConfig |= 0xC001 | (0x01 << 1) | (0x00 << 6) | (0x06 << 11);

	/* Write, block transfer, DMA, and data length */
	DataCtrl |= ((1 << 0) | (1 << 1) | (1 << 3) | (DATA_BLOCK_LEN << 4));
#else
	/* Read, enable, block transfer, and data length */
	DataCtrl |= ((1 << 0) | (1 << 1) | (DATA_BLOCK_LEN << 4));
#endif

	LPC_MCI->DATACTRL = DataCtrl;

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

	return MCI_FUNC_OK;
}

/*****************************************************************************
**                            End Of File
******************************************************************************/

⌨️ 快捷键说明

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