rt-thread/bsp/hc32f460/Libraries/HC32F460_StdPeriph_Driver/src/hc32f460_sdioc.c

2223 lines
94 KiB
C
Raw Normal View History

/*******************************************************************************
* Copyright (C) 2020, Huada Semiconductor Co., Ltd. All rights reserved.
*
* This software component is licensed by HDSC under BSD 3-Clause license
* (the "License"); You may not use this file except in compliance with the
* License. You may obtain a copy of the License at:
* opensource.org/licenses/BSD-3-Clause
*/
/******************************************************************************/
/** \file hc32f460_sdioc.c
**
** A detailed description is available at
** @link SdiocGroup SDIOC description @endlink
**
** - 2018-11-11 CDT First version for Device Driver Library of SDIOC.
**
******************************************************************************/
/*******************************************************************************
* Include files
******************************************************************************/
#include "hc32f460_sdioc.h"
#include "hc32f460_utility.h"
#if (DDL_SDIOC_ENABLE == DDL_ON)
/**
*******************************************************************************
** \addtogroup SdiocGroup
******************************************************************************/
//@{
/*******************************************************************************
* Local type definitions ('typedef')
******************************************************************************/
/**
*******************************************************************************
** \brief SDIOC internal data
**
******************************************************************************/
typedef struct stc_sdioc_intern_data
{
stc_sdioc_normal_irq_cb_t stcNormalIrqCb; ///< Normal irq callback function structure
stc_sdioc_error_irq_cb_t stcErrorIrqCb; ///< Error irq callback function structure
} stc_sdioc_intern_data_t;
/**
*******************************************************************************
** \brief SDIOC instance data
**
******************************************************************************/
typedef struct stc_sdioc_instance_data
{
const M4_SDIOC_TypeDef *SDIOCx; ///< pointer to registers of an instance
stc_sdioc_intern_data_t stcInternData; ///< module internal data of instance
} stc_sdioc_instance_data_t;
/*******************************************************************************
* Local pre-processor symbols/macros ('#define')
******************************************************************************/
/*!< Parameter valid check for SDIOC Instances. */
#define IS_VALID_SDIOC(__SDIOCx__) \
( (M4_SDIOC1 == (__SDIOCx__)) || \
(M4_SDIOC2 == (__SDIOCx__)))
/*!< Parameter valid check for SDIOC mode. */
#define IS_VALID_SDIOC_MODE(x) \
( (SdiocModeSD == (x)) || \
(SdiocModeMMC == (x)))
/*!< Parameter valid check for SDIOC Response Register. */
#define IS_VALID_SDIOC_RESP(x) \
( (SdiocRegResp01 == (x)) || \
(SdiocRegResp23 == (x)) || \
(SdiocRegResp45 == (x)) || \
(SdiocRegResp67 == (x)))
/*!< Parameter valid check for SDIOC bus width. */
#define IS_VALID_SDIOC_BUS_WIDTH(x) \
( (SdiocBusWidth1Bit == (x)) || \
(SdiocBusWidth4Bit == (x)) || \
(SdiocBusWidth8Bit == (x)))
/*!< Parameter valid check for SDIOC speed mode. */
#define IS_VALID_SDIOC_SPEED_MODE(x) \
( (SdiocHighSpeedMode == (x)) || \
(SdiocNormalSpeedMode == (x)))
/*!< Parameter valid check for SDIOC Clock division. */
#define IS_VALID_SDIOC_CLK_DIV(x) \
( (SdiocClkDiv_1 == (x)) || \
(SdiocClkDiv_2 == (x)) || \
(SdiocClkDiv_4 == (x)) || \
(SdiocClkDiv_8 == (x)) || \
(SdiocClkDiv_16 == (x)) || \
(SdiocClkDiv_32 == (x)) || \
(SdiocClkDiv_64 == (x)) || \
(SdiocClkDiv_128 == (x)) || \
(SdiocClkDiv_256 == (x)))
/*!< Parameter valid check for SDIOC command type. */
#define IS_VALID_SDIOC_CMD_TYPE(x) \
( (SdiocCmdAbort == (x)) || \
(SdiocCmdResume == (x)) || \
(SdiocCmdNormal == (x)) || \
(SdiocCmdSuspend == (x)))
/*!< Parameter valid check for SDIOC data transfer direction. */
#define IS_VALID_SDIOC_TRANSFER_DIR(x) \
( (SdiocTransferToCard == (x)) || \
(SdiocTransferToHost == (x)))
/*!< Parameter valid check for SDIOC software reset type. */
#define IS_VALID_SDIOC_SWRESETTYPE(x) \
( (SdiocSwResetAll == (x)) || \
(SdiocSwResetCmdLine == (x)) || \
(SdiocSwResetDatLine == (x)))
/*!< Parameter valid check for SDIOC data transfer mode. */
#define IS_VALID_SDIOC_TRANSFER_MODE(x) \
( (SdiocTransferSingle == (x)) || \
(SdiocTransferInfinite == (x)) || \
(SdiocTransferMultiple == (x)) || \
(SdiocTransferStopMultiple == (x)))
/*!< Parameter valid check for SDIOC data timeout. */
#define IS_VALID_SDIOC_DATA_TIMEOUT(x) \
( (SdiocDtoSdclk_2_13 == (x)) || \
(SdiocDtoSdclk_2_14 == (x)) || \
(SdiocDtoSdclk_2_15 == (x)) || \
(SdiocDtoSdclk_2_16 == (x)) || \
(SdiocDtoSdclk_2_17 == (x)) || \
(SdiocDtoSdclk_2_18 == (x)) || \
(SdiocDtoSdclk_2_19 == (x)) || \
(SdiocDtoSdclk_2_20 == (x)) || \
(SdiocDtoSdclk_2_21 == (x)) || \
(SdiocDtoSdclk_2_22 == (x)) || \
(SdiocDtoSdclk_2_23 == (x)) || \
(SdiocDtoSdclk_2_24 == (x)) || \
(SdiocDtoSdclk_2_25 == (x)) || \
(SdiocDtoSdclk_2_26 == (x)) || \
(SdiocDtoSdclk_2_27 == (x)))
/*!< Parameter valid check for SDIOC Response type name. */
#define IS_VALID_SDIOC_RESP_TYPE_NAME(x) \
( (SdiocCmdRspR1 == (x)) || \
(SdiocCmdRspR1b == (x)) || \
(SdiocCmdRspR2 == (x)) || \
(SdiocCmdRspR3 == (x)) || \
(SdiocCmdRspR4 == (x)) || \
(SdiocCmdRspR5 == (x)) || \
(SdiocCmdRspR5b == (x)) || \
(SdiocCmdRspR6 == (x)) || \
(SdiocCmdRspR7 == (x)) || \
(SdiocCmdNoRsp == (x)))
/*!< Parameter valid check for SDIOC data timeout. */
#define IS_VALID_SDIOC_HOST_STATUS(x) \
( (SdiocCmdPinLvl == (x)) || \
(SdiocData0PinLvl == (x)) || \
(SdiocData1PinLvl == (x)) || \
(SdiocData2PinLvl == (x)) || \
(SdiocData3PinLvl == (x)) || \
(SdiocCardInserted == (x)) || \
(SdiocDataLineActive == (x)) || \
(SdiocCardStateStable == (x)) || \
(SdiocBufferReadEnble == (x)) || \
(SdiocBufferWriteEnble == (x)) || \
(SdiocCardDetectPinLvl == (x)) || \
(SdiocCommandInhibitCmd == (x)) || \
(SdiocWriteProtectPinLvl == (x)) || \
(SdiocCommandInhibitData == (x)) || \
(SdiocReadTransferActive == (x)) || \
(SdiocWriteTransferActive == (x)))
/*!< Parameter valid check for SDIOC normal interrupt. */
#define IS_VALID_SDIOC_NOR_INT(x) \
( (SdiocCardInt == (x)) || \
(SdiocErrorInt == (x)) || \
(SdiocCardRemoval == (x)) || \
(SdiocBlockGapEvent == (x)) || \
(SdiocCardInsertedInt == (x)) || \
(SdiocCommandComplete == (x)) || \
(SdiocBufferReadReady == (x)) || \
(SdiocBufferWriteReady == (x)) || \
(SdiocTransferComplete == (x)))
/*!< Parameter valid check for SDIOC error interrupt. */
#define IS_VALID_SDIOC_ERR_INT(x) \
( (SdiocCmdCrcErr == (x)) || \
(SdiocDataCrcErr == (x)) || \
(SdiocCmdIndexErr == (x)) || \
(SdiocCmdEndBitErr == (x)) || \
(SdiocAutoCmd12Err == (x)) || \
(SdiocCmdTimeoutErr == (x)) || \
(SdiocDataEndBitErr == (x)) || \
(SdiocDataTimeoutErr == (x)))
/*!< Parameter valid check for SDIOC auto CMD12 error status. */
#define IS_VALID_SDIOC_AUTOCMD_ERR(x) \
( (SdiocCmdNotIssuedErr == (x)) || \
(SdiocAutoCmd12CrcErr == (x)) || \
(SdiocAutoCmd12Timeout == (x)) || \
(SdiocAutoCmd12IndexErr == (x)) || \
(SdiocAutoCmd12EndBitErr == (x)) || \
(SdiocAutoCmd12NotExecuted == (x)))
/*!< Parameter valid check for SDIOC detect card signal. */
#define IS_VALID_SDIOC_DETECT_SIG(x) \
( (SdiocSdcdPinLevel == (x)) || \
(SdiocCardDetectTestLevel == (x)))
/*!< Parameter valid check for SDIOC data block count value. */
#define IS_VALID_SDIOC_BLKCNT(x) ((x) != 0u)
/*!< Parameter valid check for SDIOC data block size value. */
#define IS_VALID_SDIOC_BLKSIZE(x) (!((x) & 0xF000ul))
/*!< Parameter valid check for SDIOC command value. */
#define IS_VALID_SDIOC_CMD_VAL(x) (!(0xC0u & (x)))
/*!< Parameter valid check for buffer address. */
#define IS_VALID_TRANSFER_BUF_ALIGN(x) (!((SDIOC_BUF_ALIGN_SIZE-1ul) & ((uint32_t)(x))))
/*!< Parameter valid check for SDIOC command value. */
#define IS_VALID_TRANSFER_BUF_LEN(x) (!((SDIOC_BUF_ALIGN_SIZE-1ul) & ((uint32_t)(x))))
/*!< SDIOC unit max count value. */
#define SDIOC_UNIT_MAX_CNT (ARRAY_SZ(m_astcSdiocInstanceDataLut))
/*!< SDIOC default sdclk frequency. */
#define SDIOC_SDCLK_400K (400000ul)
/*!< Get the specified register address of the specified SDIOC unit */
#define SDIOC_ARG01(__SDIOCx__) ((uint32_t)(&((__SDIOCx__)->ARG0)))
#define SDIOC_BUF01(__SDIOCx__) ((uint32_t)(&((__SDIOCx__)->BUF0)))
#define SDIOC_RESPx(__SDIOCx__, RESP_REG) ((uint32_t)(&((__SDIOCx__)->RESP0)) + (uint32_t)(RESP_REG))
/* SDIOC buffer align size */
#define SDIOC_BUF_ALIGN_SIZE (4ul)
/*******************************************************************************
* Global variable definitions (declared in header file with 'extern')
******************************************************************************/
/*******************************************************************************
* Local function prototypes ('static')
******************************************************************************/
static en_sdioc_clk_div_t SdiocGetClkDiv(uint32_t u32Exclk,
uint32_t u32SdiocClkFreq);
static stc_sdioc_intern_data_t* SdiocGetInternDataPtr(const M4_SDIOC_TypeDef *SDIOCx);
/*******************************************************************************
* Local variable definitions ('static')
******************************************************************************/
/*******************************************************************************
* Function implementation - global ('extern') and local ('static')
******************************************************************************/
/**
*******************************************************************************
** \brief Get SDIOC clock division.
**
** \param [in] u32Exclk Exclk frequency
** \param [in] u32ClkFreq SDIOC clock frequency
**
** \retval SdiocClkDiv_1 EXCLK/1
** \retval SdiocClkDiv_2 EXCLK/2
** \retval SdiocClkDiv_4 EXCLK/4
** \retval SdiocClkDiv_8 EXCLK/8
** \retval SdiocClkDiv_16 EXCLK/16
** \retval SdiocClkDiv_32 EXCLK/32
** \retval SdiocClkDiv_64 EXCLK/64
** \retval SdiocClkDiv_128 EXCLK/128
** \retval SdiocClkDiv_256 EXCLK/256
**
******************************************************************************/
static en_sdioc_clk_div_t SdiocGetClkDiv(uint32_t u32Exclk,
uint32_t u32ClkFreq)
{
uint32_t u32SdClkDiv = 0ul;
en_sdioc_clk_div_t enClockDiv = SdiocClkDiv_256;
if(0ul != u32ClkFreq)
{
u32SdClkDiv = u32Exclk / u32ClkFreq;
if (u32Exclk % u32ClkFreq)
{
u32SdClkDiv++;
}
if ((128ul < u32SdClkDiv) && (u32SdClkDiv <= 256ul))
{
enClockDiv = SdiocClkDiv_256;
}
else if ((64ul < u32SdClkDiv) && (u32SdClkDiv <= 128ul))
{
enClockDiv = SdiocClkDiv_128;
}
else if ((32ul < u32SdClkDiv) && (u32SdClkDiv <= 64ul))
{
enClockDiv = SdiocClkDiv_64;
}
else if ((16ul < u32SdClkDiv) && (u32SdClkDiv <= 32ul))
{
enClockDiv = SdiocClkDiv_32;
}
else if ((16ul < u32SdClkDiv) && (u32SdClkDiv <= 32ul))
{
enClockDiv = SdiocClkDiv_32;
}
else if ((8ul < u32SdClkDiv) && (u32SdClkDiv <= 16ul))
{
enClockDiv = SdiocClkDiv_16;
}
else if ((4ul < u32SdClkDiv) && (u32SdClkDiv <= 8ul))
{
enClockDiv = SdiocClkDiv_8;
}
else if ((2ul < u32SdClkDiv) && (u32SdClkDiv <= 4ul))
{
enClockDiv = SdiocClkDiv_4;
}
else if ((1ul < u32SdClkDiv) && (u32SdClkDiv <= 2ul))
{
enClockDiv = SdiocClkDiv_2;
}
else
{
enClockDiv = SdiocClkDiv_1;
}
}
return enClockDiv;
}
/**
*******************************************************************************
** \brief Return the internal data for a certain SDIOC instance.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval Pointer to internal data or NULL if instance is not enabled (or not known)
**
******************************************************************************/
static stc_sdioc_intern_data_t* SdiocGetInternDataPtr(const M4_SDIOC_TypeDef *SDIOCx)
{
uint8_t i;
stc_sdioc_intern_data_t *pstcInternData = NULL;
static stc_sdioc_instance_data_t m_astcSdiocInstanceDataLut[2];
m_astcSdiocInstanceDataLut[0].SDIOCx = M4_SDIOC1;
m_astcSdiocInstanceDataLut[1].SDIOCx = M4_SDIOC2;
if (NULL != SDIOCx)
{
for (i = 0u; i < SDIOC_UNIT_MAX_CNT; i++)
{
if (SDIOCx == m_astcSdiocInstanceDataLut[i].SDIOCx)
{
pstcInternData = &m_astcSdiocInstanceDataLut[i].stcInternData;
break;
}
}
}
return pstcInternData;
}
/**
*******************************************************************************
** \brief SDIOC instance interrupt service routine
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval None
**
******************************************************************************/
void SDIOC_IrqHandler(M4_SDIOC_TypeDef *SDIOCx)
{
stc_sdioc_intern_data_t *pstcSdiocInternData = SdiocGetInternDataPtr(SDIOCx);
/* Check for NULL pointer */
if (NULL != pstcSdiocInternData)
{
/**************** Normal interrupt handler ****************/
if (1u == SDIOCx->NORINTST_f.CC) /* Command complete */
{
SDIOCx->NORINTST_f.CC = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnCommandCompleteIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnCommandCompleteIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.TC) /* Transfer complete */
{
SDIOCx->NORINTST_f.TC = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnTransferCompleteIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnTransferCompleteIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.BGE) /* Block gap event */
{
SDIOCx->NORINTST_f.BGE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnBlockGapIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnBlockGapIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.BWR) /* Buffer write ready */
{
SDIOCx->NORINTST_f.BWR = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnBufferWriteReadyIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnBufferWriteReadyIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.BRR) /* Buffer read ready */
{
SDIOCx->NORINTST_f.BRR = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnBufferReadReadyIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnBufferReadReadyIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.CIST) /* Card insertion */
{
SDIOCx->NORINTST_f.CIST = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnCardInsertIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnCardInsertIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.CRM) /* Card removal */
{
SDIOCx->NORINTST_f.CRM = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnCardRemovalIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnCardRemovalIrqCb();
}
}
if (1u == SDIOCx->NORINTST_f.CINT) /* Card interrupt */
{
SDIOCx->NORINTST_f.CINT = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcNormalIrqCb.pfnCardIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnCardIrqCb();
}
}
/**************** Error interrupt handler ****************/
if (1u == SDIOCx->ERRINTST_f.CTOE) /* Command timeout error */
{
SDIOCx->ERRINTST_f.CTOE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnCmdTimeoutErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnCmdTimeoutErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.CCE) /* Command CRC error */
{
SDIOCx->ERRINTST_f.CCE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnCmdCrcErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnCmdCrcErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.CEBE) /* Command end bit error */
{
SDIOCx->ERRINTST_f.CEBE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnCmdEndBitErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnCmdEndBitErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.CIE) /* Command index error */
{
SDIOCx->ERRINTST_f.CIE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnCmdIndexErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnCmdIndexErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.DTOE) /* Data timeout error */
{
SDIOCx->ERRINTST_f.DTOE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnDataTimeoutErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnDataTimeoutErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.DEBE) /* Data end bit error */
{
SDIOCx->ERRINTST_f.DEBE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnDataEndBitErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnDataEndBitErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.DCE) /* Data CRC error */
{
SDIOCx->ERRINTST_f.DCE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnDataCrcErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnDataCrcErrIrqCb();
}
}
if (1u == SDIOCx->ERRINTST_f.ACE) /* Auto CMD12 error */
{
SDIOCx->ERRINTST_f.ACE = 1u; /* Clear interrupt flag */
if (NULL != pstcSdiocInternData->stcErrorIrqCb.pfnAutoCmdErrIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnAutoCmdErrIrqCb();
}
}
}
}
/**
*******************************************************************************
** \brief Initializes a SDIOC.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] pstcInitCfg Pointer to SDIOC configure structure
** \arg This parameter detail refer @ref stc_sdioc_init_t
**
** \retval Ok SDIOC initialized normally
** \retval ErrorTimeout SDIOCx reset timeout
** \retval ErrorInvalidParameter If one of following cases matches:
** - SDIOCx is invalid
** - pstcInitCfg == NULL
** - Other invalid configuration
**
******************************************************************************/
en_result_t SDIOC_Init(M4_SDIOC_TypeDef *SDIOCx,
const stc_sdioc_init_t *pstcInitCfg)
{
__IO uint32_t i = 0ul;
uint32_t u32Exclk = 0ul;
uint32_t u32Cnt = SystemCoreClock / 100ul;
en_result_t enRet = ErrorInvalidParameter;
stc_sdioc_intern_data_t *pstcSdiocInternData = NULL;
/* Get pointer to internal data structure. */
pstcSdiocInternData = SdiocGetInternDataPtr(SDIOCx);
if (NULL != pstcSdiocInternData) /* Check for instance available or not */
{
/* Reset all */
SDIOCx->SFTRST_f.RSTA = 1u;
while (0u != SDIOCx->SFTRST_f.RSTA) /* Wait until reset finish */
{
if (i++ > u32Cnt)
{
break;
}
}
if (i < u32Cnt)
{
/* Get EXCLK frequency */
u32Exclk = SystemCoreClock / (1ul << M4_SYSREG->CMU_SCFGR_f.EXCKS);
SDIOCx->CLKCON_f.FS = SdiocGetClkDiv(u32Exclk, SdiocClk400K);
SDIOCx->CLKCON_f.CE = (uint16_t)1u;
SDIOCx->CLKCON_f.ICE = (uint16_t)1u;
SDIOCx->PWRCON_f.PWON = (uint8_t)1u; /* Power on */
/* Enable all status */
SDIOCx->ERRINTST = (uint16_t)0x017Fu; /* Clear Error interrupt status */
SDIOCx->ERRINTSTEN = (uint16_t)0x017Fu; /* Enable Error interrupt status */
SDIOCx->NORINTST = (uint16_t)0x00F7u; /* Clear Normal interrupt status */
SDIOCx->NORINTSTEN = (uint16_t)0x01F7u; /* Enable Normal interrupt status */
/* Enable normal interrupt signal */
if (NULL != pstcInitCfg)
{
if (NULL != pstcInitCfg->pstcNormalIrqEn)
{
SDIOCx->NORINTSGEN = pstcInitCfg->pstcNormalIrqEn->u16NormalIntsgEn;
}
/* Set normal interrupt callback functions */
if (NULL != pstcInitCfg->pstcNormalIrqCb)
{
pstcSdiocInternData->stcNormalIrqCb.pfnCommandCompleteIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnCommandCompleteIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnTransferCompleteIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnTransferCompleteIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnBlockGapIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnBlockGapIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnBufferWriteReadyIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnBufferWriteReadyIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnBufferReadReadyIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnBufferReadReadyIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnCardInsertIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnCardInsertIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnCardRemovalIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnCardRemovalIrqCb;
pstcSdiocInternData->stcNormalIrqCb.pfnCardIrqCb = pstcInitCfg->pstcNormalIrqCb->pfnCardIrqCb;
}
/* Enable error interrupt signal */
if (NULL != pstcInitCfg->pstcErrorIrqEn)
{
SDIOCx->ERRINTSGEN = pstcInitCfg->pstcErrorIrqEn->u16ErrorIntsgEn;
}
/* Set error interrupt callback functions */
if (NULL != pstcInitCfg->pstcErrorIrqCb)
{
pstcSdiocInternData->stcErrorIrqCb.pfnCmdTimeoutErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnCmdTimeoutErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnCmdCrcErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnCmdCrcErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnCmdEndBitErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnCmdEndBitErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnCmdIndexErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnCmdIndexErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnDataTimeoutErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnDataTimeoutErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnDataEndBitErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnDataEndBitErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnDataCrcErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnDataCrcErrIrqCb;
pstcSdiocInternData->stcErrorIrqCb.pfnAutoCmdErrIrqCb = pstcInitCfg->pstcErrorIrqCb->pfnAutoCmdErrIrqCb;
}
}
enRet = Ok;
}
else
{
enRet = ErrorTimeout;
}
}
return enRet;
}
/**
*******************************************************************************
** \brief De-Initializes the specified SDIOC unit.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval Ok De-Initialize successfully.
** \retval ErrorTimeout SDIOCx reset timeout.
** \retval ErrorInvalidParameter SDIOCx is invalid.
**
******************************************************************************/
en_result_t SDIOC_DeInit(M4_SDIOC_TypeDef *SDIOCx)
{
__IO uint32_t i = 0ul;
uint32_t u32Cnt = SystemCoreClock / 100ul;
en_result_t enRet = ErrorInvalidParameter;
stc_sdioc_intern_data_t *pstcSdiocInternData = NULL;
/* Get pointer to internal data structure. */
pstcSdiocInternData = SdiocGetInternDataPtr(SDIOCx);
if (NULL != pstcSdiocInternData) /* Check for instance available or not */
{
/* Reset all */
SDIOCx->SFTRST_f.RSTA = 1u;
while (0u != SDIOCx->SFTRST_f.RSTA) /* Wait until reset finish */
{
if (i++ > u32Cnt)
{
break;
}
}
if (i < u32Cnt)
{
/* Set normal interrupt callback functions */
pstcSdiocInternData->stcNormalIrqCb.pfnCommandCompleteIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnTransferCompleteIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnBlockGapIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnBufferWriteReadyIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnBufferReadReadyIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnCardInsertIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnCardRemovalIrqCb = NULL;
pstcSdiocInternData->stcNormalIrqCb.pfnCardIrqCb = NULL;
/* Set error interrupt callback functions */
pstcSdiocInternData->stcErrorIrqCb.pfnCmdTimeoutErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnCmdCrcErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnCmdEndBitErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnCmdIndexErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnDataTimeoutErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnDataEndBitErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnDataCrcErrIrqCb = NULL;
pstcSdiocInternData->stcErrorIrqCb.pfnAutoCmdErrIrqCb = NULL;
enRet = Ok;
}
else
{
enRet = ErrorTimeout;
}
}
return enRet;
}
/**
* @brief Set SDIOC mode.
* @param [in] SDIOCx Pointer to SDIOC instance register base
* This parameter can be one of the following values:
* @arg M4_SDIOC1: SDIOC unit 1 instance register base
* @arg M4_SDIOC2: SDIOC unit 2 instance register base
* @param [in] enMode SDIOCx mode
* @arg SdiocModeSD: SD mode
* @arg SdiocModeMMC: MMC mode
*/
void SDIOC_SetMode(const M4_SDIOC_TypeDef *SDIOCx, en_sdioc_mode_t enMode)
{
/* Check parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
DDL_ASSERT(IS_VALID_SDIOC_MODE(enMode));
if (M4_SDIOC1 == SDIOCx)
{
M4_PERIC->SDIOC_SYCTLREG_f.SELMMC1 = (uint32_t)enMode;
}
else
{
M4_PERIC->SDIOC_SYCTLREG_f.SELMMC2 = (uint32_t)enMode;
}
}
/**
*******************************************************************************
** \brief Send SD command
**
** This function sends command on CMD line
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] pstcCmdCfg Pointer to command transfer configuration structure.
** \arg This parameter detail refer @ref stc_sdioc_cmd_cfg_t
**
** \retval Ok Command sent normally
** \retval ErrorInvalidParameter If one of following cases matches:
** - SDIOCx is invalid
** - pstcCmdCfg == NULL
**
******************************************************************************/
en_result_t SDIOC_SendCommand(M4_SDIOC_TypeDef *SDIOCx,
const stc_sdioc_cmd_cfg_t *pstcCmdCfg)
{
uint32_t u32Addr;
stc_sdioc_cmd_field_t stcCmdField;
en_result_t enRet = ErrorInvalidParameter;
/* Check for NULL pointer */
if ((IS_VALID_SDIOC(SDIOCx)) && (NULL != pstcCmdCfg))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_CMD_VAL(pstcCmdCfg->u8CmdIndex));
DDL_ASSERT(IS_VALID_SDIOC_CMD_TYPE(pstcCmdCfg->enCmdType));
DDL_ASSERT(IS_FUNCTIONAL_STATE(pstcCmdCfg->enDataPresentEnable));
DDL_ASSERT(IS_VALID_SDIOC_RESP_TYPE_NAME(pstcCmdCfg->enRspIndex));
enRet = Ok;
switch (pstcCmdCfg->enRspIndex)
{
case SdiocCmdNoRsp:
stcCmdField.RESTYP = SdiocResponseNoneBit;
stcCmdField.CCE = 0u;
stcCmdField.ICE = 0u;
break;
case SdiocCmdRspR2:
stcCmdField.RESTYP = SdiocResponse136Bit;
stcCmdField.CCE = 1u;
stcCmdField.ICE = 0u;
break;
case SdiocCmdRspR3:
case SdiocCmdRspR4:
stcCmdField.RESTYP = SdiocResponse48Bit;
stcCmdField.CCE = 0u;
stcCmdField.ICE = 0u;
break;
case SdiocCmdRspR1:
case SdiocCmdRspR5:
case SdiocCmdRspR6:
case SdiocCmdRspR7:
stcCmdField.RESTYP = SdiocResponse48Bit;
stcCmdField.CCE = 1u;
stcCmdField.ICE = 1u;
break;
case SdiocCmdRspR1b:
case SdiocCmdRspR5b:
stcCmdField.RESTYP = SdiocResponse48BitCheckBusy;
stcCmdField.CCE = 1u;
stcCmdField.ICE = 1u;
break;
default:
enRet = ErrorInvalidParameter;
break;
}
if (enRet == Ok)
{
stcCmdField.RESERVED2 = (uint16_t)0u;
stcCmdField.TYP = (uint16_t)pstcCmdCfg->enCmdType;
stcCmdField.IDX = (uint16_t)pstcCmdCfg->u8CmdIndex;
stcCmdField.DAT = (uint16_t)(pstcCmdCfg->enDataPresentEnable);
u32Addr = SDIOC_ARG01(SDIOCx);
*(__IO uint32_t *)u32Addr = pstcCmdCfg->u32Argument;
u32Addr = (uint32_t)&stcCmdField;
SDIOCx->CMD = *(uint16_t *)u32Addr;
}
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the response received from the card for the last command
**
** This function sends command on CMD line
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enRespReg Response Specifies the SDIOC response register.
** \arg SdiocRegResp01 Response0 and Response1 Register
** \arg SdiocRegResp23 Response2 and Response3 Register
** \arg SdiocRegResp45 Response4 and Response5 Register
** \arg SdiocRegResp67 Response6 and Response7 Register
**
** \retval The Corresponding response register value
**
******************************************************************************/
uint32_t SDIOC_GetResponse(const M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_response_reg_t enRespReg)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
DDL_ASSERT(IS_VALID_SDIOC_RESP(enRespReg));
return *(__IO uint32_t *)SDIOC_RESPx(SDIOCx, enRespReg) ;
}
/**
*******************************************************************************
** \brief Read data from SDIOCx data buffer
**
** This function reads 32-bit data from data buffer
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] au8Data Buffer which will store SDIOC_BUFFER data
** \param [in] u32Len Data length
**
** \retval Ok Data is read normally
** \retval ErrorInvalidParameter If one of following cases matches:
** - SDIOCx is invalid
** - pu32Data == NULL
**
******************************************************************************/
en_result_t SDIOC_ReadBuffer(M4_SDIOC_TypeDef *SDIOCx,
uint8_t au8Data[],
uint32_t u32Len)
{
uint32_t i = 0ul;
uint32_t u32Temp = 0ul;;
__IO uint32_t *SDIO_BUF_REG = NULL;
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx && pu8Data pointer */
if ((NULL != au8Data) && \
(IS_VALID_SDIOC(SDIOCx)) && \
(IS_VALID_TRANSFER_BUF_LEN(u32Len)))
{
SDIO_BUF_REG = (__IO uint32_t *)SDIOC_BUF01(SDIOCx);
while (i < u32Len)
{
u32Temp = *SDIO_BUF_REG;
au8Data[i++] = (uint8_t)((u32Temp >> 0ul) & 0x000000FF);
au8Data[i++] = (uint8_t)((u32Temp >> 8ul) & 0x000000FF);
au8Data[i++] = (uint8_t)((u32Temp >> 16ul) & 0x000000FF);
au8Data[i++] = (uint8_t)((u32Temp >> 24ul) & 0x000000FF);
}
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Write data to SDIOCx data buffer
**
** This function writes 32-bit data to data buffer
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] au8Data Buffer which will be wrote to SDIOC_BUFFER
** \param [in] u32Len Data length
**
** \retval Ok Data is written normally
** \retval ErrorInvalidParameter If one of following cases matches:
** - SDIOCx is invalid
** - pu8Data == NULL
**
******************************************************************************/
en_result_t SDIOC_WriteBuffer(M4_SDIOC_TypeDef *SDIOCx,
uint8_t au8Data[],
uint32_t u32Len)
{
uint32_t i = 0ul;
uint32_t u32Temp = 0ul;
__IO uint32_t *SDIO_BUF_REG = NULL;
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx && pu8Data pointer */
if ((NULL != au8Data) && \
(IS_VALID_SDIOC(SDIOCx)) && \
(IS_VALID_TRANSFER_BUF_LEN(u32Len)))
{
SDIO_BUF_REG = (__IO uint32_t *)SDIOC_BUF01(SDIOCx);
while (i < u32Len)
{
u32Temp = (((uint32_t)au8Data[i++]) << 0ul) & 0x000000FFul;
u32Temp += (((uint32_t)au8Data[i++]) << 8ul) & 0x0000FF00ul;
u32Temp += (((uint32_t)au8Data[i++]) << 16ul) & 0x00FF0000ul;
u32Temp += (((uint32_t)au8Data[i++]) << 24ul) & 0xFF000000ul;
*SDIO_BUF_REG = u32Temp;
}
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Configure SDIOCx data parameters
**
** This function writes 32-bit data to data buffer
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] pstcDataCfg Pointer to SDIOC data transfer configuration structure
** \arg This parameter detail refer @ref stc_sdioc_data_cfg_t
**
** \retval Ok configure normally
** \retval ErrorInvalidParameter If one of following cases matches:
** - SDIOCx is invalid
** - pstcDataCfg == NULL
**
******************************************************************************/
en_result_t SDIOC_ConfigData(M4_SDIOC_TypeDef *SDIOCx,
const stc_sdioc_data_cfg_t *pstcDataCfg)
{
uint16_t u16BlkCnt = (uint16_t)0;
uint32_t u32Addr;
stc_sdioc_transmode_field_t stcTransModeField = {0};
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx && pstcDataCfg pointer */
if ((IS_VALID_SDIOC(SDIOCx)) && (NULL != pstcDataCfg))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_BLKCNT(pstcDataCfg->u16BlkCnt));
DDL_ASSERT(IS_VALID_SDIOC_BLKSIZE(pstcDataCfg->u16BlkSize));
DDL_ASSERT(IS_FUNCTIONAL_STATE(pstcDataCfg->enAutoCmd12Enable));
DDL_ASSERT(IS_VALID_SDIOC_DATA_TIMEOUT(pstcDataCfg->enDataTimeOut));
DDL_ASSERT(IS_VALID_SDIOC_TRANSFER_DIR(pstcDataCfg->enTransferDir));
DDL_ASSERT(IS_VALID_SDIOC_TRANSFER_MODE(pstcDataCfg->enTransferMode));
enRet = Ok;
switch (pstcDataCfg->enTransferMode)
{
case SdiocTransferSingle:
stcTransModeField.MULB = 0u;
stcTransModeField.BCE = 0u;
break;
case SdiocTransferInfinite:
stcTransModeField.MULB = 1u;
stcTransModeField.BCE = 0u;
break;
case SdiocTransferMultiple:
u16BlkCnt = pstcDataCfg->u16BlkCnt;
stcTransModeField.MULB = 1u;
stcTransModeField.BCE = 1u;
break;
case SdiocTransferStopMultiple:
stcTransModeField.MULB = 1u;
stcTransModeField.BCE = 1u;
break;
default:
enRet = ErrorInvalidParameter;
break;
}
if (enRet == Ok)
{
stcTransModeField.RESERVED0 = (uint16_t)0u;
stcTransModeField.DDIR = (uint16_t)(pstcDataCfg->enTransferDir);
stcTransModeField.ATCEN = (uint16_t)(pstcDataCfg->enAutoCmd12Enable);
/* Set the SDIOC Data Transfer Timeout value */
SDIOCx->TOUTCON = (uint8_t)(pstcDataCfg->enDataTimeOut);
/* Set the SDIOC Block Count value */
SDIOCx->BLKCNT = u16BlkCnt;
/* Set the SDIOC Block Size value */
SDIOCx->BLKSIZE = pstcDataCfg->u16BlkSize;
/* Set the SDIOC Data Transfer Mode */
u32Addr = (uint32_t)&stcTransModeField;
SDIOCx->TRANSMODE = *(uint16_t *)u32Addr;
}
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable SDCLK output
**
** SD host drives SDCLK line.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enCmd The SDCLK functional state command
** \arg Enable Enable SDCLK function
** \arg Disable Disable SDCLK function
**
** \retval Ok SDCLK output of SDIOCx enabled normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_SdclkCmd(M4_SDIOC_TypeDef *SDIOCx,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
SDIOCx->CLKCON_f.CE = (uint16_t)(enCmd);
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Set the clock division of SD clock
**
** This function changes the SD clock division.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enClkDiv SDIOC clock division value
** \arg SdiocClkDiv_1 EXCLK/1
** \arg SdiocClkDiv_2 EXCLK/2
** \arg SdiocClkDiv_4 EXCLK/4
** \arg SdiocClkDiv_8 EXCLK/8
** \arg SdiocClkDiv_16 EXCLK/16
** \arg SdiocClkDiv_32 EXCLK/32
** \arg SdiocClkDiv_64 EXCLK/64
** \arg SdiocClkDiv_128 EXCLK/128
** \arg SdiocClkDiv_256 EXCLK/256
**
** \retval Ok SDIOC clock division is changed normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_SetClkDiv(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_clk_div_t enClkDiv)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_CLK_DIV(enClkDiv));
/* Set clock division */
SDIOCx->CLKCON_f.FS = (uint16_t)enClkDiv;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the clock division of SD clock
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval SdiocClkDiv_1 EXCLK/1
** \retval SdiocClkDiv_2 EXCLK/2
** \retval SdiocClkDiv_4 EXCLK/4
** \retval SdiocClkDiv_8 EXCLK/8
** \retval SdiocClkDiv_16 EXCLK/16
** \retval SdiocClkDiv_32 EXCLK/32
** \retval SdiocClkDiv_64 EXCLK/64
** \retval SdiocClkDiv_128 EXCLK/128
**
******************************************************************************/
en_sdioc_clk_div_t SDIOC_GetClkDiv(M4_SDIOC_TypeDef *SDIOCx)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
return ((en_sdioc_clk_div_t)SDIOCx->CLKCON_f.FS);
}
/**
*******************************************************************************
** \brief Get the clock division of SD clock
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] u32ClkFreq SDIOC clock frequency
**
** \retval Ok Set successfully.
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_SetClk(M4_SDIOC_TypeDef *SDIOCx, uint32_t u32ClkFreq)
{
uint32_t u32Exclk = 0ul;
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Get EXCLK frequency */
u32Exclk = SystemCoreClock / (1ul << M4_SYSREG->CMU_SCFGR_f.EXCKS);
SDIOCx->CLKCON_f.CE = (uint16_t)0u;
SDIOCx->CLKCON_f.FS = (uint16_t)SdiocGetClkDiv(u32Exclk, u32ClkFreq);
SDIOCx->CLKCON_f.CE = (uint16_t)1u;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Set the bus width of SD Bus
**
** This function changes the SD bus width.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enBusWidth Bus width
** \arg SdiocBusWidth1Bit The SDIOC bus width 1 bit
** \arg SdiocBusWidth4Bit The SDIOC bus width 4 bit
** \arg SdiocBusWidth8Bit The SDIOC bus width 8 bit
**
** \retval Ok Bus width is set normally
** \retval ErrorInvalidParameter If one of following conditions are met:
** - SDIOCx is invalid
** - enBusWidth is invalid
**
******************************************************************************/
en_result_t SDIOC_SetBusWidth(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_bus_width_t enBusWidth)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_BUS_WIDTH(enBusWidth));
enRet = Ok;
switch (enBusWidth)
{
case SdiocBusWidth1Bit:
SDIOCx->HOSTCON_f.EXDW = 0u;
SDIOCx->HOSTCON_f.DW = 0u;
break;
case SdiocBusWidth4Bit:
SDIOCx->HOSTCON_f.EXDW = 0u;
SDIOCx->HOSTCON_f.DW = 1u;
break;
case SdiocBusWidth8Bit:
SDIOCx->HOSTCON_f.EXDW = 1u;
break;
default:
enRet = ErrorInvalidParameter;
break;
}
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the bus width of SD Bus
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval SdiocBusWidth1Bit The SDIOC bus width 1 bit
** \retval SdiocBusWidth4Bit The SDIOC bus width 4 bit
** \retval SdiocBusWidth8Bit The SDIOC bus width 8 bit
**
******************************************************************************/
en_sdioc_bus_width_t SDIOC_GetBusWidth(M4_SDIOC_TypeDef *SDIOCx)
{
en_sdioc_bus_width_t enBusWidth = SdiocBusWidth4Bit;
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
if (0u == SDIOCx->HOSTCON_f.EXDW)
{
if (0u == SDIOCx->HOSTCON_f.DW)
{
enBusWidth = SdiocBusWidth1Bit;
}
}
else
{
enBusWidth = SdiocBusWidth8Bit;
}
return enBusWidth;
}
/**
*******************************************************************************
** \brief Set the bus speed mode of SD Bus
**
** This function changes the SD bus speed mode.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enSpeedMode Speed mode
** \arg SdiocHighSpeedMode High speed mode
** \arg SdiocNormalSpeedMode Normal speed mode
**
** \retval Ok Bus speed is set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_SetSpeedMode(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_speed_mode_t enSpeedMode)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_SPEED_MODE(enSpeedMode));
/* Set high speed mode */
SDIOCx->HOSTCON_f.HSEN = ((SdiocHighSpeedMode == enSpeedMode) ? 1u : 0u);
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the bus speed mode of SD Bus
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval SdiocHighSpeedMode High speed mode
** \retval SdiocNormalSpeedMode Normal speed mode
**
******************************************************************************/
en_sdioc_speed_mode_t SDIOC_GetSpeedMode(M4_SDIOC_TypeDef *SDIOCx)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
return ((SDIOCx->HOSTCON_f.HSEN) ? SdiocHighSpeedMode : SdiocNormalSpeedMode);
}
/**
*******************************************************************************
** \brief Set data timeout counter value
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enTimeout Data timeout count value
** \arg SdiocDtoSdclk_2_13 Timeout time: SDCLK*2^13
** \arg SdiocDtoSdclk_2_14 Timeout time: SDCLK*2^14
** \arg SdiocDtoSdclk_2_15 Timeout time: SDCLK*2^15
** \arg SdiocDtoSdclk_2_16 Timeout time: SDCLK*2^16
** \arg SdiocDtoSdclk_2_17 Timeout time: SDCLK*2^17
** \arg SdiocDtoSdclk_2_18 Timeout time: SDCLK*2^18
** \arg SdiocDtoSdclk_2_19 Timeout time: SDCLK*2^19
** \arg SdiocDtoSdclk_2_20 Timeout time: SDCLK*2^20
** \arg SdiocDtoSdclk_2_21 Timeout time: SDCLK*2^21
** \arg SdiocDtoSdclk_2_22 Timeout time: SDCLK*2^22
** \arg SdiocDtoSdclk_2_23 Timeout time: SDCLK*2^23
** \arg SdiocDtoSdclk_2_24 Timeout time: SDCLK*2^24
** \arg SdiocDtoSdclk_2_25 Timeout time: SDCLK*2^25
** \arg SdiocDtoSdclk_2_26 Timeout time: SDCLK*2^26
** \arg SdiocDtoSdclk_2_27 Timeout time: SDCLK*2^27
**
** \retval Ok Bus speed is set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_SetDataTimeout(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_data_timeout_t enTimeout)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_DATA_TIMEOUT(enTimeout));
/* Set data timeout */
SDIOCx->TOUTCON_f.DTO = (uint8_t)enTimeout;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get data timeout counter value
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval SdiocDtoSdclk_2_13 Timeout time: SDCLK*2^13
** \retval SdiocDtoSdclk_2_14 Timeout time: SDCLK*2^14
** \retval SdiocDtoSdclk_2_15 Timeout time: SDCLK*2^15
** \retval SdiocDtoSdclk_2_16 Timeout time: SDCLK*2^16
** \retval SdiocDtoSdclk_2_17 Timeout time: SDCLK*2^17
** \retval SdiocDtoSdclk_2_18 Timeout time: SDCLK*2^18
** \retval SdiocDtoSdclk_2_19 Timeout time: SDCLK*2^19
** \retval SdiocDtoSdclk_2_20 Timeout time: SDCLK*2^20
** \retval SdiocDtoSdclk_2_21 Timeout time: SDCLK*2^21
** \retval SdiocDtoSdclk_2_22 Timeout time: SDCLK*2^22
** \retval SdiocDtoSdclk_2_23 Timeout time: SDCLK*2^23
** \retval SdiocDtoSdclk_2_24 Timeout time: SDCLK*2^24
** \retval SdiocDtoSdclk_2_25 Timeout time: SDCLK*2^25
** \retval SdiocDtoSdclk_2_26 Timeout time: SDCLK*2^26
** \retval SdiocDtoSdclk_2_27 Timeout time: SDCLK*2^27
**
******************************************************************************/
en_sdioc_data_timeout_t SDIOC_GetDataTimeout(M4_SDIOC_TypeDef *SDIOCx)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
return (en_sdioc_data_timeout_t)(SDIOCx->TOUTCON_f.DTO);
}
/**
*******************************************************************************
** \brief Set the card detect signal
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enDetectSignal Card detect signal
** \arg SdiocSdcdPinLevel SDCD# is selected (for normal use)
** \arg SdiocCardDetectTestLevel The Card Detect Test Level is selected(for test purpose)
**
** \retval Ok Set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_SetCardDetectSignal(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_detect_signal_t enDetectSignal)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_DETECT_SIG(enDetectSignal));
SDIOCx->HOSTCON_f.CDSS = (uint8_t)enDetectSignal;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get card inserted or not.
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval Set Card Inserted
** \retval Reset No Card
**
** \note This bit is enabled while the Card Detect Signal Selection is set to 1
** and it indicates card inserted or not.
**
******************************************************************************/
en_flag_status_t SDIOC_GetCardDetectTestLevel(M4_SDIOC_TypeDef *SDIOCx)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
return (en_flag_status_t)(SDIOCx->HOSTCON_f.CDTL);
}
/**
*******************************************************************************
** \brief Power on SD bus power
**
** This function starts power supply on SD bus
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval Ok Power on normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_BusPowerOn(M4_SDIOC_TypeDef *SDIOCx)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
SDIOCx->PWRCON_f.PWON = 1u;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Power off SD bus power
**
** This function stops power supply on SD bus
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval Ok Power off normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_BusPowerOff(M4_SDIOC_TypeDef *SDIOCx)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
SDIOCx->PWRCON_f.PWON = 0u;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable the function of Stop At Block Gap Request during block gap
**
** This function is used to stop data trasnfer of multi-block transfer
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enCmd SDIOC Stop At Block Gap Request functional state
** \arg Enable Enable the function of Stop At Block Gap Request
** \arg Disable Disable the function of Stop At Block Gap Request
**
** \retval Ok Set successfully
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_StopAtBlockGapCmd(M4_SDIOC_TypeDef *SDIOCx,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
SDIOCx->BLKGPCON_f.SABGR = (uint8_t)(enCmd);
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Restart data transfer
**
** This function is used to restart data transfer when transfer is pending
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
**
** \retval Ok Set successfully
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_RestartTransfer(M4_SDIOC_TypeDef *SDIOCx)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
SDIOCx->BLKGPCON_f.CR = 1u;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable the function of Read Wait Control
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enCmd SDIOC Read Wait Control functional state
** \arg Enable Enable the Read Wait Control function
** \arg Disable Disable the Read Wait Control function
**
** \retval Ok Set successfully
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ReadWaitCmd(M4_SDIOC_TypeDef *SDIOCx,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
SDIOCx->BLKGPCON_f.RWC = (uint8_t)(enCmd);
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable the function of Interrupt At Block Gap
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enCmd SDIOC Interrupt At Block Gap functional state
** \arg Enable Enable the function of Interrupt At Block Gap
** \arg Disable Disable the function of Interrupt At Block Gap
**
** \retval Ok Set successfully
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_InterruptAtBlockGapCmd(M4_SDIOC_TypeDef *SDIOCx,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
SDIOCx->BLKGPCON_f.IABG = (uint8_t)(enCmd);
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Generate software reset to SD card
**
** This function generates software reset all command to SD card
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enSwResetType Software reset type
** \arg SdiocSwResetAll This reset affects the entire Host Controller except for the card detection circuit.
** \arg SdiocSwResetCmdLine Only part of command circuit is reset.
** \arg SdiocSwResetDataLine Only part of data circuit is reset.
**
** \retval Ok Software reset is done normally
** \retval ErrorTimeout SDIOCx reset timeout
** \retval ErrorInvalidParameter If one of following conditions are met:
** - SDIOCx is invalid
** - enSwResetType is invalid
**
******************************************************************************/
en_result_t SDIOC_SoftwareReset(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_sw_reset_t enSwResetType)
{
__IO uint32_t i = 0ul;
uint32_t u32Cnt = SystemCoreClock / 100ul;
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_SWRESETTYPE(enSwResetType));
enRet = Ok;
switch (enSwResetType)
{
case SdiocSwResetAll:
SDIOCx->SFTRST_f.RSTA = (uint8_t)1u;
while(0u != SDIOCx->SFTRST_f.RSTA) /* Wait until reset finish */
{
if (i++ > u32Cnt)
{
break;
}
}
break;
case SdiocSwResetCmdLine:
SDIOCx->SFTRST_f.RSTC = (uint8_t)1u;
while(0u != SDIOCx->SFTRST_f.RSTC) /* Wait until reset finish */
{
if (i++ > u32Cnt)
{
break;
}
}
break;
case SdiocSwResetDatLine:
SDIOCx->SFTRST_f.RSTD = (uint8_t)1u;
while(0u != SDIOCx->SFTRST_f.RSTD) /* Wait until reset finish */
{
if (i++ > u32Cnt)
{
break;
}
}
break;
default:
enRet = ErrorInvalidParameter;
break;
}
}
if (i > u32Cnt)
{
enRet = ErrorTimeout;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the status of SDIOC host controller
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enHostStatus SDIOC host status
** \arg SdiocCommandInhibitCmd Command Inhibit(CMD). 1: Cannot issue command; 0:Can issue command using only CMD line
** \arg SdiocCommandInhibitData Command Inhibit(DAT). 1: Cannot issue command which uses the DAT line; 0:Can issue command which uses the DAT line
** \arg SdiocDataLineActive 1: DAT Line Active; 0: DAT Line Inactive
** \arg SdiocWriteTransferActive Write Transfer Active.1: Transferring data; 0: No valid data
** \arg SdiocReadTransferActive Read Transfer Active.1: Transferring data; 0: No valid data
** \arg SdiocBufferWriteEnble 1: Write enable; 0: Write Disable
** \arg SdiocBufferReadEnble 1: Read enable; 0: Read Disable
** \arg SdiocCardInserted 1: Card Inserted; 0: Reset or Debouncing or No Card
** \arg SdiocCardStateStable 1: No Card or Inserted; 0: Reset or Debouncing
** \arg SdiocCardDetectPinLvl 1: Card present; 0: No card present
** \arg SdiocWriteProtectPinLvl 1: Write enabled; 0: Write protected
** \arg SdiocData0PinLvl 1: DAT0 line signal level high; 0: DAT0 line signal level low
** \arg SdiocData1PinLvl 1: DAT1 line signal level high; 0: DAT1 line signal level low
** \arg SdiocData2PinLvl 1: DAT2 line signal level high; 0: DAT2 line signal level low
** \arg SdiocData3PinLvl 1: DAT3 line signal level high; 0: DAT3 line signal level low
** \arg SdiocCmdPinLvl 1: CMD line signal level high; 0: CMD line signal level low
**
** \retval Set The specified status is set
** \retval Reset The specified status is zero
**
******************************************************************************/
en_flag_status_t SDIOC_GetStatus(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_host_status_t enHostStatus)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
DDL_ASSERT(IS_VALID_SDIOC_HOST_STATUS(enHostStatus));
return ((SDIOCx->PSTAT & ((uint32_t)enHostStatus)) ? Set : Reset);
}
/**
*******************************************************************************
** \brief Enable/Disable the specified signal of SDIOC normal interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enNorInt SDIOC normal interrupt
** \arg SdiocCommandComplete Command Complete. 1: Command complete; 0:No command complete
** \arg SdiocTransferComplete Transfer Complete. 1: Data transfer complete; 0:No transfer complete
** \arg SdiocBlockGapEvent Block Gap Event. 1: Transaction stopped at block gap; 0: No Block Gap Event
** \arg SdiocBufferWriteReady Buffer Write Ready. 1: Ready to Write buffer; 0: No ready to Write buffer
** \arg SdiocBufferReadReady Buffer Read Ready. 1: Ready to read buffer; 0: No ready to read buffer
** \arg SdiocCardInsertedInt Write Transfer Active.1: Transferring data; 0: No valid data
** \arg SdiocCardRemoval Card Removal. 1: Card removed; 0: Card state stable or Debouncing
** \arg SdiocCardInt Card Interrupt. 1: Generate Card Interrupt; 0: No Card Interrupt
** \arg SdiocErrorInt Error Interrupt. 1: Error; 0: No Error
** \param [in] enCmd SDIOC normal interrupt signal functional state
** \arg Enable Enable the specified signal of SD normal interrupt
** \arg Disable Disable the specified signal of SD normal interrupt
**
** \retval Ok Set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_NormalIrqSignalCmd(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_nor_int_sel_t enNorInt,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
DDL_ASSERT(IS_VALID_SDIOC_NOR_INT(enNorInt));
if (Enable == enCmd)
{
SDIOCx->NORINTSGEN |= (uint16_t)enNorInt;
}
else
{
SDIOCx->NORINTSGEN &= (uint16_t)(~((uint16_t)enNorInt));
}
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable the status of SDIOC normal interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enNorInt SDIOC normal interrupt
** \arg SdiocCommandComplete Command Complete. 1: Command complete; 0:No command complete
** \arg SdiocTransferComplete Transfer Complete. 1: Data transfer complete; 0:No transfer complete
** \arg SdiocBlockGapEvent Block Gap Event. 1: Transaction stopped at block gap; 0: No Block Gap Event
** \arg SdiocBufferWriteReady Buffer Write Ready. 1: Ready to Write buffer; 0: No ready to Write buffer
** \arg SdiocBufferReadReady Buffer Read Ready. 1: Ready to read buffer; 0: No ready to read buffer
** \arg SdiocCardInsertedInt Write Transfer Active.1: Transferring data; 0: No valid data
** \arg SdiocCardRemoval Card Removal. 1: Card removed; 0: Card state stable or Debouncing
** \arg SdiocCardInt Card Interrupt. 1: Generate Card Interrupt; 0: No Card Interrupt
** \arg SdiocErrorInt Error Interrupt. 1: Error; 0: No Error
** \param [in] enCmd SDIOC normal interrupt status functional state
** \arg Enable Enable the specified status of SD normal interrupt
** \arg Disable Disable the specified status of SD normal interrupt
**
** \retval Ok Set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_NormalIrqStatusCmd(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_nor_int_sel_t enNorInt,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
DDL_ASSERT(IS_VALID_SDIOC_NOR_INT(enNorInt));
if (Enable == enCmd)
{
SDIOCx->NORINTSTEN |= (uint16_t)enNorInt;
}
else
{
SDIOCx->NORINTSTEN &= (uint16_t)(~((uint16_t)enNorInt));
}
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the flag of SD normal interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enNorInt SDIOC normal interrupt
** \arg SdiocCommandComplete Command Complete. 1: Command complete; 0:No command complete
** \arg SdiocTransferComplete Transfer Complete. 1: Data transfer complete; 0:No transfer complete
** \arg SdiocBlockGapEvent Block Gap Event. 1: Transaction stopped at block gap; 0: No Block Gap Event
** \arg SdiocBufferWriteReady Buffer Write Ready. 1: Ready to Write buffer; 0: No ready to Write buffer
** \arg SdiocBufferReadReady Buffer Read Ready. 1: Ready to read buffer; 0: No ready to read buffer
** \arg SdiocCardInsertedInt Write Transfer Active.1: Transferring data; 0: No valid data
** \arg SdiocCardRemoval Card Removal. 1: Card removed; 0: Card state stable or Debouncing
** \arg SdiocCardInt Card Interrupt. 1: Generate Card Interrupt; 0: No Card Interrupt
** \arg SdiocErrorInt Error Interrupt. 1: Error; 0: No Error
**
** \retval Set The specified interupt flag is set
** \retval Reset The specified interupt flag is zero
**
******************************************************************************/
en_flag_status_t SDIOC_GetNormalIrqFlag(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_nor_int_flag_t enNorInt)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
DDL_ASSERT(IS_VALID_SDIOC_NOR_INT(enNorInt));
return ((SDIOCx->NORINTST & ((uint16_t)enNorInt)) ? Set : Reset);
}
/**
*******************************************************************************
** \brief Clear the flag of SD normal interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enNorInt SDIOC normal interrupt
** \arg SdiocCommandComplete Command Complete. 1: Command complete; 0:No command complete
** \arg SdiocTransferComplete Transfer Complete. 1: Data transfer complete; 0:No transfer complete
** \arg SdiocBlockGapEvent Block Gap Event. 1: Transaction stopped at block gap; 0: No Block Gap Event
** \arg SdiocBufferWriteReady Buffer Write Ready. 1: Ready to Write buffer; 0: No ready to Write buffer
** \arg SdiocBufferReadReady Buffer Read Ready. 1: Ready to read buffer; 0: No ready to read buffer
** \arg SdiocCardInsertedInt Write Transfer Active.1: Transferring data; 0: No valid data
** \arg SdiocCardRemoval Card Removal. 1: Card removed; 0: Card state stable or Debouncing
** \arg SdiocCardInt Card Interrupt. 1: Generate Card Interrupt; 0: No Card Interrupt
** \arg SdiocErrorInt Error Interrupt. 1: Error; 0: No Error
**
** \retval Ok Clear successfully.
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ClearNormalIrqFlag(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_nor_int_flag_t enNorInt)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_NOR_INT(enNorInt));
SDIOCx->NORINTST = (uint16_t)enNorInt;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable the signal of SD error interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enErrInt SDIOC error interrupt
** \arg SdiocCmdTimeoutErr Command Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocCmdCrcErr Command CRC Error. 1: Command CRC Error Generated; 0:No Error
** \arg SdiocCmdEndBitErr Command End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocCmdIndexErr Command Index Error. 1: Command Index Error Generatedr; 0:No Error
** \arg SdiocDataTimeoutErr Data Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocDataCrcErr Data CRC Error. 1: Data CRC Error Generated; 0:No Error
** \arg SdiocDataEndBitErr Data End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocAutoCmd12Err Auto CMD12 Error. 1: Error; 0:No Error
** \param [in] enCmd SDIOC error interrupt signal functional state
** \arg Enable Enable the specified signal of SD error interrupt
** \arg Disable Disable the specified signal of SD error interrupt
**
** \retval Ok Set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ErrIrqSignalCmd(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_err_int_sel_t enErrInt,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_ERR_INT(enErrInt));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
if (Enable == enCmd)
{
SDIOCx->ERRINTSGEN |= (uint16_t)enErrInt;
}
else
{
SDIOCx->ERRINTSGEN &= (uint16_t)enErrInt;
}
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Enable/Disable the status of SD error interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enErrInt SDIOC error interrupt
** \arg SdiocCmdTimeoutErr Command Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocCmdCrcErr Command CRC Error. 1: Command CRC Error Generated; 0:No Error
** \arg SdiocCmdEndBitErr Command End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocCmdIndexErr Command Index Error. 1: Command Index Error Generatedr; 0:No Error
** \arg SdiocDataTimeoutErr Data Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocDataCrcErr Data CRC Error. 1: Data CRC Error Generated; 0:No Error
** \arg SdiocDataEndBitErr Data End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocAutoCmd12Err Auto CMD12 Error. 1: Error; 0:No Error
** \param [in] enCmd SDIOC error interrupt status functional state
** \arg Enable Enable the specified status of SD error interrupt
** \arg Disable Disable the specified status of SD error interrupt
**
** \retval Ok Set normally
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ErrIrqStatusCmd(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_err_int_sel_t enErrInt,
en_functional_state_t enCmd)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_ERR_INT(enErrInt));
DDL_ASSERT(IS_FUNCTIONAL_STATE(enCmd));
if (Enable == enCmd)
{
SDIOCx->ERRINTSTEN |= (uint16_t)enErrInt;
}
else
{
SDIOCx->ERRINTSTEN &= (uint16_t)enErrInt;
}
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the flag of SD error interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enErrInt SDIOC error interrupt
** \arg SdiocCmdTimeoutErr Command Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocCmdCrcErr Command CRC Error. 1: Command CRC Error Generated; 0:No Error
** \arg SdiocCmdEndBitErr Command End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocCmdIndexErr Command Index Error. 1: Command Index Error Generatedr; 0:No Error
** \arg SdiocDataTimeoutErr Data Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocDataCrcErr Data CRC Error. 1: Data CRC Error Generated; 0:No Error
** \arg SdiocDataEndBitErr Data End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocAutoCmd12Err Auto CMD12 Error. 1: Error; 0:No Error
**
** \retval Set The specified interupt flag is set
** \retval Reset The specified interupt flag is zero
**
******************************************************************************/
en_flag_status_t SDIOC_GetErrIrqFlag(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_err_int_flag_t enErrInt)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
DDL_ASSERT(IS_VALID_SDIOC_ERR_INT(enErrInt));
return ((SDIOCx->ERRINTST & ((uint16_t)enErrInt)) ? Set : Reset);
}
/**
*******************************************************************************
** \brief Clear the flag of SD error interrupt
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enErrInt SDIOC error interrupt
** \arg SdiocCmdTimeoutErr Command Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocCmdCrcErr Command CRC Error. 1: Command CRC Error Generated; 0:No Error
** \arg SdiocCmdEndBitErr Command End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocCmdIndexErr Command Index Error. 1: Command Index Error Generatedr; 0:No Error
** \arg SdiocDataTimeoutErr Data Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocDataCrcErr Data CRC Error. 1: Data CRC Error Generated; 0:No Error
** \arg SdiocDataEndBitErr Data End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocAutoCmd12Err Auto CMD12 Error. 1: Error; 0:No Error
**
** \retval Ok Clear successfully.
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ClearErrIrqFlag(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_err_int_flag_t enErrInt)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_ERR_INT(enErrInt));
SDIOCx->ERRINTST = (uint16_t)enErrInt;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Force the specified error interrupt flag
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enErrInt SDIOC error interrupt
** \arg SdiocCmdTimeoutErr Command Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocCmdCrcErr Command CRC Error. 1: Command CRC Error Generated; 0:No Error
** \arg SdiocCmdEndBitErr Command End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocCmdIndexErr Command Index Error. 1: Command Index Error Generatedr; 0:No Error
** \arg SdiocDataTimeoutErr Data Timeout Error. 1: Timer out; 0:No Error
** \arg SdiocDataCrcErr Data CRC Error. 1: Data CRC Error Generated; 0:No Error
** \arg SdiocDataEndBitErr Data End Bit Error. 1: End Bit Error Generated; 0:No Error
** \arg SdiocAutoCmd12Err Auto CMD12 Error. 1: Error; 0:No Error
**
** \retval Ok Set successfully.
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ForceErrIrqFlag(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_err_int_sel_t enErrInt)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_ERR_INT(enErrInt));
SDIOCx->FEE |= (uint16_t)enErrInt;
enRet = Ok;
}
return enRet;
}
/**
*******************************************************************************
** \brief Get the status of auto CMD12 error
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enAutoCmdErr SDIOC auto cmd error status selection
** \arg SdiocAutoCmd12NotExecuted Auto CMD12 Not Executed. 1: Not executed; 0:Executed
** \arg SdiocAutoCmd12Timeout Auto CMD12 Timeout Error. 1: Time out; 0:No error
** \arg SdiocAutoCmd12CrcErr Auto CMD12 CRC Error. 1: CRC Error Generated; 0: No error
** \arg SdiocAutoCmd12EndBitErr Auto CMD12 End Bit Error. 1: End Bit Error Generated; 0: No error to Write buffer
** \arg SdiocAutoCmd12IndexErr Auto CMD12 Index Error. 1: Error; 0: No error
** \arg SdiocCmdNotIssuedErr Command Not Issued By Auto CMD12 Error.1: Not Issued; 0: No error
**
** \retval Set The specified status flag is set
** \retval Reset The specified status flag is zero
**
******************************************************************************/
en_flag_status_t SDIOC_GetAutoCmdErrStatus(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_atuo_cmd_err_status_t enAutoCmdErr)
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC(SDIOCx));
DDL_ASSERT(IS_VALID_SDIOC_AUTOCMD_ERR(enAutoCmdErr));
return ((SDIOCx->ATCERRST & ((uint16_t)enAutoCmdErr)) ? Set : Reset);
}
/**
*******************************************************************************
** \brief Force the specified auto CMD12 error
**
** \param [in] SDIOCx Pointer to SDIOC instance register base
** \arg M4_SDIOC1 SDIOC unit 1 instance register base
** \arg M4_SDIOC2 SDIOC unit 2 instance register base
** \param [in] enAutoCmdErr SDIOC auto cmd error selection
** \arg SdiocAutoCmd12NotExecuted Auto CMD12 Not Executed. 1: Not executed; 0:Executed
** \arg SdiocAutoCmd12Timeout Auto CMD12 Timeout Error. 1: Time out; 0:No error
** \arg SdiocAutoCmd12CrcErr Auto CMD12 CRC Error. 1: CRC Error Generated; 0: No error
** \arg SdiocAutoCmd12EndBitErr Auto CMD12 End Bit Error. 1: End Bit Error Generated; 0: No error to Write buffer
** \arg SdiocAutoCmd12IndexErr Auto CMD12 Index Error. 1: Error; 0: No error
** \arg SdiocCmdNotIssuedErr Command Not Issued By Auto CMD12 Error.1: Not Issued; 0: No error
**
** \retval Ok Set successfully.
** \retval ErrorInvalidParameter SDIOCx is invalid
**
******************************************************************************/
en_result_t SDIOC_ForceAutoCmdErr(M4_SDIOC_TypeDef *SDIOCx,
en_sdioc_atuo_cmd_err_sel_t enAutoCmdErr)
{
en_result_t enRet = ErrorInvalidParameter;
/* Check for SDIOCx pointer */
if (IS_VALID_SDIOC(SDIOCx))
{
/* Check the parameters */
DDL_ASSERT(IS_VALID_SDIOC_AUTOCMD_ERR(enAutoCmdErr));
SDIOCx->FEA |= (uint16_t)enAutoCmdErr;
enRet = Ok;
}
return enRet;
}
//@} // SdiocGroup
#endif /* DDL_SDIOC_ENABLE */
/*******************************************************************************
* EOF (not truncated)
******************************************************************************/