📄 lpc177x_8x_mci.c
字号:
}
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 + -