/******************************************************************************* * 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) ******************************************************************************/