528 lines
20 KiB
C
528 lines
20 KiB
C
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @file hal_sdio.c
|
|||
|
/// @author AE TEAM
|
|||
|
/// @brief THIS FILE PROVIDES ALL THE SDIO FIRMWARE FUNCTIONS.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @attention
|
|||
|
///
|
|||
|
/// THE EXISTING FIRMWARE IS ONLY FOR REFERENCE, WHICH IS DESIGNED TO PROVIDE
|
|||
|
/// CUSTOMERS WITH CODING INFORMATION ABOUT THEIR PRODUCTS SO THEY CAN SAVE
|
|||
|
/// TIME. THEREFORE, MINDMOTION SHALL NOT BE LIABLE FOR ANY DIRECT, INDIRECT OR
|
|||
|
/// CONSEQUENTIAL DAMAGES ABOUT ANY CLAIMS ARISING OUT OF THE CONTENT OF SUCH
|
|||
|
/// HARDWARE AND/OR THE USE OF THE CODING INFORMATION CONTAINED HEREIN IN
|
|||
|
/// CONNECTION WITH PRODUCTS MADE BY CUSTOMERS.
|
|||
|
///
|
|||
|
/// <H2><CENTER>© COPYRIGHT MINDMOTION </CENTER></H2>
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
// Define to prevent recursive inclusion
|
|||
|
#define _HAL_SDIO_C_
|
|||
|
#include "reg_sdio.h"
|
|||
|
#include "hal_sdio.h"
|
|||
|
#include "hal_rcc.h"
|
|||
|
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @addtogroup MM32_Hardware_Abstract_Layer
|
|||
|
/// @{
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @addtogroup SDIO_HAL
|
|||
|
/// @{
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @addtogroup SDIO_Exported_Functions
|
|||
|
/// @{
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Deinitializes the SDIO peripheral registers to their default reset
|
|||
|
/// values.
|
|||
|
/// @param None.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_DeInit(void)
|
|||
|
{
|
|||
|
RCC_AHBPeriphResetCmd(RCC_AHBRSTR_SDIO, ENABLE);
|
|||
|
RCC_AHBPeriphResetCmd(RCC_AHBRSTR_SDIO, DISABLE);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Fills each SDIO_InitStruct member with its default value.
|
|||
|
/// @param SDIO_InitStruct: pointer to an SDIO_InitTypeDef structure which
|
|||
|
/// will be initialized.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_StructInit(SDIO_InitTypeDef* SDIO_InitStruct)
|
|||
|
{
|
|||
|
// SDIO_InitStruct members default value
|
|||
|
SDIO_InitStruct->SDIO_MDEN = 0;
|
|||
|
SDIO_InitStruct->SDIO_DATWT = 0;
|
|||
|
SDIO_InitStruct->SDIO_SelPTSM = 0;
|
|||
|
SDIO_InitStruct->SDIO_CLKSP = 0;
|
|||
|
SDIO_InitStruct->SDIO_OUTM = 0;
|
|||
|
SDIO_InitStruct->SDIO_SelSM = 0;
|
|||
|
SDIO_InitStruct->SDIO_OPMSel = 0;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///
|
|||
|
/// @brief Fills each SDIO_DataInitStruct member with its default value.
|
|||
|
/// @param SDIO_DataInitStruct: pointer to an SDIO_DataInitTypeDef structure which
|
|||
|
/// will be initialized.
|
|||
|
/// @retval None
|
|||
|
///
|
|||
|
void SDIO_DataStructInit(SDIO_DataInitTypeDef* SDIO_DataInitStruct)
|
|||
|
{
|
|||
|
/* SDIO_DataInitStruct members default value */
|
|||
|
SDIO_DataInitStruct->SDIO_DataTimeOut = 0xFFFFFFFF;
|
|||
|
SDIO_DataInitStruct->SDIO_DataLength = 0x00;
|
|||
|
SDIO_DataInitStruct->SDIO_DataBlockSize = SDIO_DataBlockSize_1b;
|
|||
|
SDIO_DataInitStruct->SDIO_TransferDir = SDIO_TransferDir_ToCard;
|
|||
|
// SDIO_DataInitStruct->SDIO_TransferMode = SDIO_TransferMode_Block;
|
|||
|
// SDIO_DataInitStruct->SDIO_DPSM = SDIO_DPSM_Disable;
|
|||
|
}
|
|||
|
|
|||
|
///
|
|||
|
/// @brief Initializes the SDIO data path according to the specified
|
|||
|
/// parameters in the SDIO_DataInitStruct.
|
|||
|
/// @param SDIO_DataInitStruct : pointer to a SDIO_DataInitTypeDef structure that
|
|||
|
/// contains the configuration information for the SDIO command.
|
|||
|
/// @retval None
|
|||
|
///
|
|||
|
//void SDIO_DataConfig(SDIO_DataInitTypeDef* SDIO_DataInitStruct)
|
|||
|
//{
|
|||
|
// u32 tmpreg = 0;
|
|||
|
|
|||
|
// /*---------------------------- SDIO DTIMER Configuration ---------------------*/
|
|||
|
// /* Set the SDIO Data TimeOut value */
|
|||
|
// SDIO->MMC_TIMEOUTCNT = SDIO_DataInitStruct->SDIO_DataTimeOut;
|
|||
|
|
|||
|
// /*---------------------------- SDIO DLEN Configuration -----------------------*/
|
|||
|
// /* Set the SDIO DataLength value */
|
|||
|
// SDIO->MMC_BYTECNTL = SDIO_DataInitStruct->SDIO_DataLength;
|
|||
|
|
|||
|
// /*---------------------------- SDIO DCTRL Configuration ----------------------*/
|
|||
|
// /* Get the SDIO DCTRL value */
|
|||
|
// tmpreg = SDIO->DCTRL;
|
|||
|
// /* Clear DEN, DTMODE, DTDIR and DBCKSIZE bits */
|
|||
|
// tmpreg &= DCTRL_CLEAR_MASK;
|
|||
|
// /* Set DEN bit according to SDIO_DPSM value */
|
|||
|
// /* Set DTMODE bit according to SDIO_TransferMode value */
|
|||
|
// /* Set DTDIR bit according to SDIO_TransferDir value */
|
|||
|
// /* Set DBCKSIZE bits according to SDIO_DataBlockSize value */
|
|||
|
// tmpreg |= (u32)SDIO_DataInitStruct->SDIO_DataBlockSize | SDIO_DataInitStruct->SDIO_TransferDir;//
|
|||
|
// //| SDIO_DataInitStruct->SDIO_TransferMode | SDIO_DataInitStruct->SDIO_DPSM;
|
|||
|
|
|||
|
// /* Write to SDIO DCTRL */
|
|||
|
// SDIO->DCTRL = tmpreg;
|
|||
|
//}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief The frequency division factor is configured to generate the SDIO clock.
|
|||
|
/// @param value : 1MHz = Fhclk/((mmc_cardsel[5 : 0] + 1) × 2)
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_ClockSet(u32 value)
|
|||
|
{
|
|||
|
// SDIO->MMC_CARDSEL &= ~SDIO_MMC_CARDSEL_MASK;
|
|||
|
SDIO->MMC_CARDSEL = (SDIO_MMC_CARDSEL_CTREN | SDIO_MMC_CARDSEL_ENPCLK | (value & 0x3F));
|
|||
|
// SDIO->MMC_CARDSEL = 0xC0+0x2F;//0xdf;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Initializes the SDIO peripheral according to the specified
|
|||
|
/// parameters in the SDIO_InitStruct.
|
|||
|
/// @param SDIO_InitStruct : pointer to a SDIO_InitTypeDef structure
|
|||
|
/// that contains the configuration information for the SDIO peripheral.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_Init(SDIO_InitTypeDef* SDIO_InitStruct)
|
|||
|
{
|
|||
|
SDIO->MMC_CTRL &= 0x700;
|
|||
|
SDIO->MMC_CTRL |= (SDIO_InitStruct->SDIO_OPMSel | SDIO_InitStruct->SDIO_SelSM |
|
|||
|
SDIO_InitStruct->SDIO_OUTM | SDIO_InitStruct->SDIO_CLKSP |
|
|||
|
SDIO_InitStruct->SDIO_SelPTSM | SDIO_InitStruct->SDIO_DATWT |
|
|||
|
SDIO_InitStruct->SDIO_MDEN);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Enables or disables the SDIO interrupts.
|
|||
|
/// @param SDIO_IT: specifies the SDIO interrupt sources to be enabled or disabled.
|
|||
|
/// state : new state of the specified SDIO interrupts.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_ITConfig(u32 SDIO_IT, FunctionalState state)
|
|||
|
{
|
|||
|
(state) ? (SDIO->MMC_INT_MASK |= SDIO_IT) : (SDIO->MMC_INT_MASK &= ~SDIO_IT);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Enables or disables the SDIO CRC.
|
|||
|
/// @param SDIO_CRC: specifies the SDIO CRC sources to be enabled or disabled.
|
|||
|
/// state : new state of the specified SDIO CRC.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_CRCConfig(u32 SDIO_CRC, FunctionalState state)
|
|||
|
{
|
|||
|
(state) ? (SDIO->MMC_CRCCTL |= SDIO_CRC) : (SDIO->MMC_CRCCTL &= ~SDIO_CRC);
|
|||
|
}
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Port transfer speed mode.
|
|||
|
/// @param clkdiv : High/low speed.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_Clock_Set(u8 clkdiv)
|
|||
|
{
|
|||
|
SDIO->MMC_CTRL &= ~SDIO_MMC_CTRL_SelPTSM;
|
|||
|
(clkdiv) ? (SDIO->MMC_CTRL |= SDIO_MMC_CTRL_SelPTSM) : (SDIO->MMC_CTRL &= ~SDIO_MMC_CTRL_SelPTSM);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Turn off the SDIO switch.
|
|||
|
/// @param None.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error SD_PowerOFF(void)
|
|||
|
{
|
|||
|
SDIO->MMC_CARDSEL &= ~(SDIO_MMC_CARDSEL_ENPCLK | SDIO_MMC_CARDSEL_CTREN);
|
|||
|
return SD_OK;
|
|||
|
}
|
|||
|
///
|
|||
|
/// @brief Fills each SDIO_CmdInitStruct member with its default value.
|
|||
|
/// @param SDIO_CmdInitStruct: pointer to an SDIO_CmdInitTypeDef
|
|||
|
/// structure which will be initialized.
|
|||
|
/// @retval None
|
|||
|
///
|
|||
|
void SDIO_CmdStructInit(SDIO_CmdInitTypeDef* SDIO_CmdInitStruct)
|
|||
|
{
|
|||
|
/* SDIO_CmdInitStruct members default value */
|
|||
|
SDIO_CmdInitStruct->SDIO_Argument = 0x00;
|
|||
|
SDIO_CmdInitStruct->SDIO_CmdIndex = 0x00;
|
|||
|
SDIO_CmdInitStruct->SDIO_Response = SDIO_Response_No;
|
|||
|
SDIO_CmdInitStruct->SDIO_Wait = SDIO_Wait_No;
|
|||
|
// SDIO_CmdInitStruct->SDIO_CPSM = SDIO_CPSM_Disable;
|
|||
|
}
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief SDIO sends command functions.
|
|||
|
/// @param cmdindex : Type the command.
|
|||
|
/// waitrsp : Expected correspondence.
|
|||
|
/// arg : parameter.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_Send_Cmd(u8 cmdindex, u8 waitrsp, u32 arg)
|
|||
|
{
|
|||
|
SDIO->CMD_BUF0 = (arg >> 0) & 0xFF;
|
|||
|
SDIO->CMD_BUF1 = (arg >> 8) & 0xFF;
|
|||
|
SDIO->CMD_BUF2 = (arg >> 16) & 0xFF;
|
|||
|
SDIO->CMD_BUF3 = (arg >> 24) & 0xFF;
|
|||
|
SDIO->CMD_BUF4 = 0x40 | cmdindex;
|
|||
|
SDIO->CLR_MMC_INT |= 0;
|
|||
|
SDIO->MMC_IO = SDIO_MMC_IO_AUTOTR;
|
|||
|
while(1) {
|
|||
|
if(SDIO->CLR_MMC_INT & SDIO_CLR_MMC_INT_CMDDMC) {
|
|||
|
SDIO->CLR_MMC_INT |= SDIO_CLR_MMC_INT_CMDDMC;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
if(waitrsp == SDIO_Response_Short) {
|
|||
|
SDIO->MMC_IO = SDIO_MMC_IO_AUTOCLKG | \
|
|||
|
SDIO_MMC_IO_AUTOTR | \
|
|||
|
SDIO_MMC_IO_RESPCMDSEL;
|
|||
|
}
|
|||
|
else if(waitrsp == SDIO_Response_Long) {
|
|||
|
SDIO->MMC_IO = SDIO_MMC_IO_AUTOCLKG | \
|
|||
|
SDIO_MMC_IO_AUTOTR | \
|
|||
|
SDIO_MMC_IO_RESPCMDSEL | \
|
|||
|
SDIO_MMC_IO_CID_CSDRD;
|
|||
|
}
|
|||
|
else {
|
|||
|
}
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Check the execution status of CMD0.
|
|||
|
/// @param None.
|
|||
|
/// @retval card error code.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error CmdError(void)
|
|||
|
{
|
|||
|
SD_Error errorstatus = SD_OK;
|
|||
|
u32 timeout = SDIO_CMD0TIMEOUT;
|
|||
|
while (timeout--) {
|
|||
|
if(((SDIO->MMC_IO & SDIO_MMC_IO_RESPCMDSEL) == 0) && ((SDIO->MMC_IO & SDIO_MMC_IO_AUTOTR) == 0))
|
|||
|
break;
|
|||
|
}
|
|||
|
if (timeout == 0)
|
|||
|
return SD_CMD_RSP_TIMEOUT;
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_MASK;
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Check the error status of the R1 response.
|
|||
|
/// @param cmd : Current command.
|
|||
|
/// @retval card error code.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error CmdResp1Error(u8 cmd)
|
|||
|
{
|
|||
|
u32 status;
|
|||
|
u32 response;
|
|||
|
while(1) {
|
|||
|
status = SDIO->CLR_MMC_INT ;
|
|||
|
if(status & (SDIO_CLR_MMC_INT_CRCEMC | SDIO_CLR_MMC_INT_CRNTMC | SDIO_CLR_MMC_INT_CMDDMC))
|
|||
|
break;
|
|||
|
}
|
|||
|
if(status & SDIO_CLR_MMC_INT_CRNTMC) {
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRNTMC;
|
|||
|
return SD_CMD_RSP_TIMEOUT;
|
|||
|
}
|
|||
|
if(status & (SDIO_CLR_MMC_INT_CRCEMC)) {
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRCEMC;
|
|||
|
return SD_CMD_CRC_FAIL;
|
|||
|
}
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_MASK;
|
|||
|
|
|||
|
if((SDIO->CMD_BUF4 & 0x3F) != cmd) {
|
|||
|
return SD_ILLEGAL_CMD;
|
|||
|
}
|
|||
|
response = SDIO->CMD_BUF3 << 24 | SDIO->CMD_BUF2 << 16 | SDIO->CMD_BUF1 << 8 | SDIO->CMD_BUF0;
|
|||
|
return (SD_Error)(response & SD_OCR_ERRORBITS);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Check the execution status of CMD2.
|
|||
|
/// @param None.
|
|||
|
/// @retval card error code.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error CmdResp2Error(void)
|
|||
|
{
|
|||
|
SD_Error errorstatus = SD_OK;
|
|||
|
u32 status;
|
|||
|
u32 timeout = SDIO_CMD0TIMEOUT;
|
|||
|
while(timeout--) {
|
|||
|
status = SDIO->CLR_MMC_INT ;
|
|||
|
if(status & (SDIO_CLR_MMC_INT_CRCEMC | SDIO_CLR_MMC_INT_CRNTMC | SDIO_CLR_MMC_INT_CMDDMC))
|
|||
|
break;
|
|||
|
}
|
|||
|
if((timeout == 0) || (status & SDIO_CLR_MMC_INT_CRNTMC)) {
|
|||
|
errorstatus = SD_CMD_RSP_TIMEOUT;
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRNTMC;
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
if(status & SDIO_CLR_MMC_INT_CRCEMC) {
|
|||
|
errorstatus = SD_CMD_CRC_FAIL;
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRCEMC;
|
|||
|
}
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_MASK;
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Check the execution status of CMD3.
|
|||
|
/// @param None.
|
|||
|
/// @retval card error code.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error CmdResp3Error(void)
|
|||
|
{
|
|||
|
u32 status;
|
|||
|
while(1) {
|
|||
|
status = SDIO->CLR_MMC_INT ;
|
|||
|
if(status & (SDIO_CLR_MMC_INT_CRCEMC | SDIO_CLR_MMC_INT_CRNTMC | SDIO_CLR_MMC_INT_CMDDMC))
|
|||
|
break;
|
|||
|
}
|
|||
|
if(status & SDIO_CLR_MMC_INT_CRNTMC) {
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRNTMC;
|
|||
|
return SD_CMD_RSP_TIMEOUT;
|
|||
|
}
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_MASK;
|
|||
|
return SD_OK;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Check the execution status of CMD6.
|
|||
|
/// @param None.
|
|||
|
/// @retval card error code.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error CmdResp6Error(u8 cmd, u16* prca)
|
|||
|
{
|
|||
|
SD_Error errorstatus = SD_OK;
|
|||
|
u32 status;
|
|||
|
u32 rspr1;
|
|||
|
while(1) {
|
|||
|
status = SDIO->CLR_MMC_INT ;
|
|||
|
if(status & (SDIO_CLR_MMC_INT_CRCEMC | SDIO_CLR_MMC_INT_CRNTMC | SDIO_CLR_MMC_INT_CMDDMC))
|
|||
|
break;
|
|||
|
}
|
|||
|
if(status & SDIO_CLR_MMC_INT_CRNTMC) {
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRNTMC;
|
|||
|
return SD_CMD_RSP_TIMEOUT;
|
|||
|
}
|
|||
|
if(status & SDIO_CLR_MMC_INT_CRCEMC) {
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRCEMC;
|
|||
|
return SD_CMD_CRC_FAIL;
|
|||
|
}
|
|||
|
if((SDIO->CMD_BUF4 & 0x3F) != cmd) {
|
|||
|
return SD_ILLEGAL_CMD;
|
|||
|
}
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_MASK;
|
|||
|
rspr1 = SDIO->CMD_BUF3 << 24 | SDIO->CMD_BUF2 << 16 | SDIO->CMD_BUF1 << 8 | SDIO->CMD_BUF0;
|
|||
|
if(SD_ALLZERO == (rspr1 & (SD_R6_GENERAL_UNKNOWN_ERROR | SD_R6_ILLEGAL_CMD | SD_R6_COM_CRC_FAILED))) {
|
|||
|
*prca = (u16)(rspr1 >> 16);
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
if(rspr1 & SD_R6_GENERAL_UNKNOWN_ERROR) {
|
|||
|
return SD_GENERAL_UNKNOWN_ERROR;
|
|||
|
}
|
|||
|
if(rspr1 & SD_R6_ILLEGAL_CMD) {
|
|||
|
return SD_ILLEGAL_CMD;
|
|||
|
}
|
|||
|
if(rspr1 & SD_R6_COM_CRC_FAILED) {
|
|||
|
return SD_COM_CRC_FAILED;
|
|||
|
}
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Check the execution status of CMD7.
|
|||
|
/// @param None.
|
|||
|
/// @retval card error code.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
SD_Error CmdResp7Error(void)
|
|||
|
{
|
|||
|
SD_Error errorstatus = SD_OK;
|
|||
|
u32 status;
|
|||
|
u32 timeout = SDIO_CMD0TIMEOUT;
|
|||
|
while(timeout--) {
|
|||
|
status = SDIO->CLR_MMC_INT ;
|
|||
|
if(status & (SDIO_CLR_MMC_INT_CRCEMC | SDIO_CLR_MMC_INT_CRNTMC | SDIO_CLR_MMC_INT_CMDDMC))
|
|||
|
break;
|
|||
|
}
|
|||
|
if((timeout == 0) || (status & SDIO_CLR_MMC_INT_CRNTMC)) { //timeout
|
|||
|
errorstatus = SD_CMD_RSP_TIMEOUT;
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CRNTMC;
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
if(status & SDIO_CLR_MMC_INT_CMDDMC) {
|
|||
|
errorstatus = SD_OK;
|
|||
|
SDIO->CLR_MMC_INT = SDIO_CLR_MMC_INT_CMDDMC;
|
|||
|
}
|
|||
|
return errorstatus;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Write data direction block size configuration.
|
|||
|
/// @param datatimeout : maximum latency.
|
|||
|
/// datalen : data len
|
|||
|
/// blksize : block count.
|
|||
|
/// dir : direction
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_Send_Data_Cfg(u32 datatimeout, u32 datalen, u8 blksize, u8 dir)
|
|||
|
{
|
|||
|
u32 tmpreg, tmpreg1, tmpreg2 = 0;
|
|||
|
tmpreg = SDIO->MMC_IO_MBCTL;
|
|||
|
tmpreg1 = SDIO->MMC_IO;
|
|||
|
tmpreg &= ~(SDIO_MMC_IO_MBCTL_BTSSel | SDIO_MMC_IO_MBCTL_SPMBDTR | SDIO_MMC_IO_MBCTL_SMBDTD);
|
|||
|
if (datatimeout < 100) {
|
|||
|
SDIO->MMC_TIMEOUTCNT = datatimeout;
|
|||
|
}
|
|||
|
else if (datatimeout < 10000) {
|
|||
|
SDIO->MMC_TIMEOUTCNT = datatimeout / 100;
|
|||
|
tmpreg |= SDIO_MMC_IO_MBCTL_BTSSel;
|
|||
|
}
|
|||
|
else if (datatimeout < 1000000) {
|
|||
|
SDIO->MMC_TIMEOUTCNT = datatimeout / 10000;
|
|||
|
tmpreg |= SDIO_MMC_IO_MBCTL_BTSSel_2;
|
|||
|
}
|
|||
|
else {
|
|||
|
SDIO->MMC_TIMEOUTCNT = datatimeout / 1000000;
|
|||
|
tmpreg |= SDIO_MMC_IO_MBCTL_BTSSel;
|
|||
|
}
|
|||
|
SDIO->MMC_BYTECNTL = datalen & 0x1FFFFFF; ;
|
|||
|
SDIO->MMC_BLOCKCNT = blksize;
|
|||
|
if (dir == 0) {
|
|||
|
tmpreg |= SDIO_MMC_IO_MBCTL_SMBDTD;
|
|||
|
tmpreg1 |= SDIO_MMC_IO_TRANSFDIR;
|
|||
|
tmpreg2 |= SDIO_BUF_CTLL_SBAD;
|
|||
|
}
|
|||
|
else {
|
|||
|
tmpreg &= ~(SDIO_MMC_IO_MBCTL_SMBDTD);
|
|||
|
tmpreg1 &= ~(SDIO_MMC_IO_TRANSFDIR);
|
|||
|
tmpreg2 &= ~(SDIO_BUF_CTLL_SBAD);
|
|||
|
}
|
|||
|
SDIO->MMC_IO_MBCTL = tmpreg;
|
|||
|
SDIO->MMC_IO = tmpreg1;
|
|||
|
SDIO->BUF_CTL = tmpreg2;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Clears the SDIO's Flag pending bits.
|
|||
|
/// @param SDIO_IT: specifies the flag pending bit to clear.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_ClearFlag(u32 SDIO_FLAG)
|
|||
|
{
|
|||
|
SDIO->CLR_MMC_INT |= SDIO_FLAG;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Clears the SDIO's interrupt pending bits.
|
|||
|
/// @param SDIO_IT: specifies the interrupt pending bit to clear.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_ClearITPendingBit(u32 SDIO_IT)
|
|||
|
{
|
|||
|
SDIO->CLR_MMC_INT |= SDIO_IT;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Checks whether the specified SDIO flag is set or not.
|
|||
|
/// @param SDIO_FLAG: specifies the flag to check.
|
|||
|
/// @retval The new state of SDIO_FLAG (SET or RESET).
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
FlagStatus SDIO_GetFlagStatus(u32 SDIO_FLAG)
|
|||
|
{
|
|||
|
return ((SDIO->CLR_MMC_INT & SDIO_FLAG) ? SET : RESET);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Reads the value of the data transfer timeout count
|
|||
|
/// @param None.
|
|||
|
/// @retval timeout count.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
u32 SDIO_GetTimeOutCounter(void)
|
|||
|
{
|
|||
|
return (SDIO->MMC_TIMEOUTCNT & 0xFF);
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Read one data word from FIFO.
|
|||
|
/// @param None.
|
|||
|
/// @retval Data received.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
u32 SDIO_ReadData(void)
|
|||
|
{
|
|||
|
return SDIO->FIFO;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Write one data word to FIFO.
|
|||
|
/// @param tempbuff : Write data.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_WriteData(u32 tempbuff)
|
|||
|
{
|
|||
|
SDIO->FIFO = tempbuff;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Returns number of remaining data bytes to be transferred.
|
|||
|
/// @param None
|
|||
|
/// @retval Number of remaining data bytes to be transferred
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
u32 SDIO_GetDataCounter(void)
|
|||
|
{
|
|||
|
return SDIO->MMC_BYTECNTL;
|
|||
|
}
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
/// @brief Enable or Dsiable DMA .
|
|||
|
/// @param tempbuff : Write data.
|
|||
|
/// @retval None.
|
|||
|
////////////////////////////////////////////////////////////////////////////////
|
|||
|
void SDIO_DMACmd(FunctionalState state)
|
|||
|
{
|
|||
|
(state) ? ((SDIO->BUF_CTL |= SDIO_BUF_CTLL_DMAHEN), SDIO->BUF_CTL &= (~(SDIO_BUF_CTLL_DRM))) : (SDIO->BUF_CTL &= ~SDIO_BUF_CTLL_DMAHEN);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/// @}
|
|||
|
|
|||
|
/// @}
|
|||
|
|
|||
|
/// @}
|
|||
|
|