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

📄 lpc177x_8x_mci.c

📁 NXPl788上lwip的无操作系统移植,基于Embest开发板
💻 C
📖 第 1 页 / 共 5 页
字号:
	}

	return retval;
}

/************************************************************************//**
 * @brief 		Set the length for the blocks in the next action on data 
 *				manipulation (as read, write, erase). This function is to
 *				send CMD16 (SET_BLOCK_LEN) to cards.
 *
 * @param[in]	blockLength the value for the length of block will be handled
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		CMD16 command should be sent after the card is selected by CMD7 
 *				(SELECT_CARD).
 ****************************************************************************/
int32_t MCI_SetBlockLen(uint32_t blockLength)
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

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

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

		retryCount--;
	}

	return retval;
}


/************************************************************************//**
 * @brief 		Set bus-width (1 bit or 4 bit) to work with the card by command
 *				CMD6 (SET_ACMD_BUS_WIDTH).
 *
 * @param[in]	buswidth The value represented for bus-width
 *				- 0b00: 1-bit bus-width
 *				- 0b10: 4-bit bus-width
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		
 *				- If SD card is currently in used, it's possible to enable 4-bit
 *				bus-width instead of 1-bit to speed up.
 *				- This command can only be transferred during TRANS state.
 *				- Since, it's a ACMD, CMD55 (APP_CMD) needs to be sent out first
 ****************************************************************************/
int32_t MCI_Acmd_SendBusWidth( uint32_t buswidth )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	int32_t retval = MCI_FUNC_FAILED;

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

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

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

		retryCount--;
	}

	return retval;
}


/************************************************************************//**
 * @brief 		Get the state of  data transfer to see if it is ended or not
 *
 * @param		None
 *
 * @return 		Transfer state (stored by Mci_Data_Xfer_End variable)
 ****************************************************************************/
uint32_t MCI_GetDataXferEndState(void)
{
	return Mci_Data_Xfer_End;
}
/************************************************************************//**
 * @brief 		Get the error state of  the lastest data transfer
 *
 * @param		None
 *
 * @return 		Error state (stored by Mci_Data_Xfer_ERR variable)
 ****************************************************************************/
uint32_t MCI_GetXferErrState(void)
{
    return Mci_Data_Xfer_ERR;
}

/************************************************************************//**
 * @brief 		Stop the current transmission on the bus by sending command CMD12
 *				(STOP_TRANSMISSION). In this case, the card may be in a unknown
 *				state. So that it need a warm reset for normal operation.
 *
 * @param[in]	None
 *
 * @return 		MCI_FUNC_OK if all success
 ****************************************************************************/
int32_t MCI_Cmd_StopTransmission( void )
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

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

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


/************************************************************************//**
 * @brief 		Write blocks to card by sending command CMD24 (WRITE_BLOCK) or
 *				command CMD25 (WRITE_MULTIPLE_BLOCK) followed by the blocks of
 *				data to be written.
 *
 * @param[in]	blockNum The block number to start writting
 *
 * @param[in]	numOfBlock Determine how many blocks will be written (from the
 *				starting block)
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		These commands should be sent in TRANS state.
 ****************************************************************************/
int32_t MCI_Cmd_WriteBlock(uint32_t blockNum, uint32_t numOfBlock)
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];

	uint32_t commandID;

	int32_t retval = MCI_FUNC_FAILED;

	if (numOfBlock > 1)
	{
		commandID = CMD25_WRITE_MULTIPLE_BLOCK;
	}
	else
	{
		commandID = CMD24_WRITE_BLOCK;
	}
	
	retryCount = 0x20;
	while ( retryCount > 0 )
	{
		LPC_MCI->CLEAR = 0x7FF;

		respStatus = MCI_CmdResp(commandID, blockNum * BLOCK_LENGTH, EXPECT_SHORT_RESP, (uint32_t *)&respValue[0], ALLOW_CMD_TIMER);

		if(respStatus)
		{
			retval = MCI_FUNC_FAILED;
		}
		else if(!(XSHIFT_(respValue[0], MCI_CARDSTATUS_READYFORDATA_P0S) & 0x01))
		{
			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 */
}




/************************************************************************//**
 * @brief 		Read blocks to card by sending CMD17 (READ_SINGLE_BLOCK) or
 *				CMD18 (READ_MULTIPLE_BLOCK) commands followed by the blocks of
 *				data to be read.
 *
 * @param[in]	blockNum The block number to start reading
 *
 * @param[in]	numOfBlock Determine how many blocks will be read (from the
 *				starting block)
 *
 * @return 		MCI_FUNC_OK if all success
 *
 * @note		These commands should be sent in TRANS state.
 ****************************************************************************/
int32_t MCI_Cmd_ReadBlock(uint32_t blockNum, uint32_t numOfBlock)
{
	uint32_t i, retryCount;
	uint32_t respStatus;
	uint32_t respValue[4];
	uint32_t commandID;

	int32_t retval = MCI_FUNC_FAILED;

	// To Do: Read Multi-Block
	if (numOfBlock > 1)
		commandID = CMD18_READ_MULTIPLE_BLOCK;
	else
		commandID = CMD17_READ_SINGLE_BLOCK;

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

		respStatus = MCI_CmdResp(commandID, blockNum * BLOCK_LENGTH, 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_TRAN))//((CARDSTATEOF(respValue[0]) != MCI_CARDSTATE_READY))
		{
			retval = MCI_FUNC_ERR_STATE;
		}
		else
		{
			/* ready and in TRAN state */
			return MCI_FUNC_OK;
		}

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

		retryCount--;
	}

	return retval;
}


/************************************************************************//**
 * @brief 		Write data at a specific address to starting block with number
 *				of blocks will be written from first block
 * @details		
 *				- At preparation
 *					- Set MCI data control register, data length and data timeout
 *					- Send CMD24 (WRITE_BLOCK) or CMD25 (WRITE_MULTIPLE_BLOCK)
 *					commands to card
 *					- Enable interupt for MCI component
 *				- At completion
 *					- TX_ACTIVE interrupt is occured
 *					- Write data to FIFO register continuously until the data block
 *					length is reached
 *
 * @param[in]	*memblock The pointer to location stored required data to be
 *				written to card
 *
 * @param[in]	blockNum The block number to start writting
 *
 * @param[in]	numOfBlock Determine how many blocks will be written (from the
 *				starting block)
 *
 * @return 		MCI_FUNC_OK if all success
 ****************************************************************************/
int32_t MCI_WriteBlock(uint8_t* memblock, uint32_t blockNum, uint32_t numOfBlock)
{
	uint32_t i;
	uint32_t DataCtrl = 0;

	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*numOfBlock;

	Mci_Data_Xfer_End = 1;
    Mci_Data_Xfer_ERR = 0;
    fifo_plane = 0;

	txBlockCnt = 0;

	MCI_TXEnable();

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

	//for(blockCnt = 0; blockCnt < numOfBlock; blockCnt++)
	{
#if MCI_DMA_ENABLED
		MCI_SettingDma((uint8_t*) dataSrcBlock, MCI_DMA_WRITE_CHANNEL, GPDMA_TRANSFERTYPE_M2P_DEST_CTRL);
		
		/* Write, block transfer, DMA, and data length */
		DataCtrl |= MCI_DATACTRL_ENABLE | MCI_DATACTRL_DIR_TO_CARD 
						| MCI_DATACTRL_DMA_ENABLE | MCI_DTATCTRL_BLOCKSIZE(DATA_BLOCK_LEN);
#else
		/* Write, block transfer, and data length */
		DataCtrl |= MCI_DATACTRL_ENABLE  | MCI_DATACTRL_DIR_TO_CARD  | MCI_DTATCTRL_BLOCKSIZE(DATA_BLOCK_LEN);
#endif
	}

	LPC_MCI->DATACTRL = DataCtrl;

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

	return MCI_FUNC_OK;
}


/************************************************************************//**
 * @brief 		Read data at a specific address to starting block with number
 *				of blocks will be read from first block
 *
 * @details		
 *				- At preparation
 *					- Set MCI data control register, data length and data timeout
 *					- Send CMD17 (READ_SINGLE_BLOCK) or CMD18 (READ_MULTIPLE_BLOCK)
 *					commands to card
 *					- Enable interupt for MCI component
 *				- At completion
 *					- RX_ACTIVE interrupt is occured
 *					- Read data from FIFO register continuously until the data block
 *					length is reached to retrieve needed data
 *
 * @param[in]	*destBlock The pointer to location will captured data read
 *				from card
 *
 * @param[in]	blockNum The block number to start reading
 *
 * @param[in]	numOfBlock Determine how many blocks will be read (from the
 *				starting block)
 *
 * @return 		MCI_FUNC_OK if all success
 ****************************************************************************/
int32_t MCI_ReadBlock(uint8_t* destBlock, uint32_t blockNum, uint32_t numOfBlock)
{
	uint32_t i;
	uint32_t DataCtrl = 0;

	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*numOfBlock;

	Mci_Data_Xfer_End = 1;
    Mci_Data_Xfer_ERR = 0;
	rxBlockCnt = 0;
    fifo_plane = 0;

	if ( MCI_Cmd_ReadBlock(blockNum, numOfBlock) != MCI_FUNC_OK )
	{
		return MCI_FUNC_FAILED;
	}

	//for(blockCnt = 0; blockCnt < numOfBlock; blockCnt++)
	{		
#if MCI_DMA_ENABLED
		MCI_SettingDma((uint8_t*) dataDestBlock, MCI_DMA_READ_CHANNEL, GPDMA_TRANSFERTYPE_P2M_SRC_CTRL);

		/* Write, block transfer, DMA, and data length */
		DataCtrl |= MCI_DATACTRL_ENABLE | MCI_DATACTRL_DIR_FROM_CARD
						| MCI_DATACTRL_DMA_ENABLE | MCI_DTATCTRL_BLOCKSIZE(DATA_BLOCK_LEN);
#else
		//Retrieving the result after reading the card is don

⌨️ 快捷键说明

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