/*! * @file apm32f4Xx_sdio.c * * @brief This file provides all the SDIO firmware functions * * @version V1.0.2 * * @date 2022-06-23 * * @attention * * Copyright (C) 2021-2022 Geehy Semiconductor * * You may not use this file except in compliance with the * GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE). * * The program is only for reference, which is distributed in the hope * that it will be usefull and instructional for customers to develop * their software. Unless required by applicable law or agreed to in * writing, the program is distributed on an "AS IS" BASIS, WITHOUT * ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied. * See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions * and limitations under the License. */ #include "apm32f4Xx_sdio.h" #include "apm32f4Xx_rcm.h" /** @addtogroup APM32F4xx_StdPeriphDriver @{ */ /** @defgroup SDIO_Driver * @brief SDIO driver modules @{ */ /** @defgroup SDIO_Functions @{ */ /*! * @brief Reset sdio peripheral registers to their default reset values * * @param None * * @retval None */ void SDIO_Reset(void) { RCM_EnableAPB2PeriphReset(RCM_APB2_PERIPH_SDIO); RCM_DisableAPB2PeriphReset(RCM_APB2_PERIPH_SDIO); } /*! * @brief Config the SDIO peripheral according to the specified parameters in the sdioConfig * * @param sdioConfig: pointer to a SDIO_Config_T structure * * @retval None */ void SDIO_Config(SDIO_Config_T *sdioConfig) { SDIO->CLKCTRL_B.CLKDIV = sdioConfig->clockDiv; SDIO->CLKCTRL_B.PWRSAV = sdioConfig->clockPowerSave; SDIO->CLKCTRL_B.BYPASSEN = sdioConfig->clockBypass; SDIO->CLKCTRL_B.WBSEL = sdioConfig->busWide; SDIO->CLKCTRL_B.DEPSEL = sdioConfig->clockEdge; SDIO->CLKCTRL_B.HFCEN = sdioConfig->hardwareFlowControl; } /*! * @brief Fills each SDIO_Config_T member with its default value * * @param sdioConfig: pointer to a SDIO_Config_T structure * * @retval None */ void SDIO_ConfigStructInit(SDIO_Config_T *sdioConfig) { sdioConfig->clockDiv = 0x00; sdioConfig->clockEdge = SDIO_CLOCK_EDGE_RISING; sdioConfig->clockBypass = SDIO_CLOCK_BYPASS_DISABLE; sdioConfig->clockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE; sdioConfig->busWide = SDIO_BUS_WIDE_1B; sdioConfig->hardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE; } /*! * @brief Enables the SDIO clock * * @param None * * @retval None */ void SDIO_EnableClock(void) { SDIO->CLKCTRL_B.CLKEN = SET; } /*! * @brief Disables the SDIO clock * * @param None * * @retval None */ void SDIO_DisableClock(void) { SDIO->CLKCTRL_B.CLKEN = RESET; } /*! * @brief Sets the power status of the controller * * @param powerState: new state of the Power state * The parameter can be one of following values: * @arg SDIO_POWER_STATE_OFF : Power off * @arg SDIO_POWER_STATE_ON : Power on * * @retval None */ void SDIO_ConfigPowerState(SDIO_POWER_STATE_T powerState) { SDIO->PWRCTRL_B.PWRCTRL = powerState; } /*! * @brief Reads the SDIO power state * * @param None * * @retval The new state SDIO power * * @note 0x00:Power OFF, 0x02:Power UP, 0x03:Power ON */ uint32_t SDIO_ReadPowerState(void) { return (uint8_t)SDIO->PWRCTRL_B.PWRCTRL; } /*! * @brief Enables the SDIO DMA request * * @param None * * @retval None */ void SDIO_EnableDMA(void) { SDIO->DCTRL_B.DMAEN = SET; } /*! * @brief Disables the SDIO DMA request * * @param None * * @retval None */ void SDIO_DisableDMA(void) { SDIO->DCTRL_B.DMAEN = RESET; } /*! * @brief Configs the SDIO Command and send the command * * @param cmdConfig: pointer to a SDIO_CmdConfig_T structure * * @retval None */ void SDIO_TxCommand(SDIO_CmdConfig_T *cmdConfig) { uint32_t tempReg = 0; SDIO->ARG = cmdConfig->argument; tempReg = SDIO->CMD; /* Clear CMDINDEX, WAITRES, WAITINT, WENDDATA, CPSMEN bits */ tempReg &= ((uint32_t)0xFFFFF800); tempReg |= (uint32_t)(cmdConfig->cmdIndex) | (cmdConfig->response) << 6 | (cmdConfig->wait) << 8 | (cmdConfig->CPSM) << 10; SDIO->CMD = tempReg; } /*! * @brief Fills each cmdConfig member with its default value * * @param cmdConfig: pointer to a SDIO_CmdConfig_T structure * * @retval None */ void SDIO_TxCommandStructInit(SDIO_CmdConfig_T *cmdConfig) { cmdConfig->argument = 0x00; cmdConfig->cmdIndex = 0x00; cmdConfig->response = SDIO_RESPONSE_NO; cmdConfig->wait = SDIO_WAIT_NO; cmdConfig->CPSM = SDIO_CPSM_DISABLE; } /*! * @brief Reads the SDIO command response * * @param None * * @retval The command index of the last command response received */ uint8_t SDIO_ReadCommandResponse(void) { return (uint8_t)(SDIO->CMDRES); } /*! * @brief Reads the SDIO response * * @param res: Specifies the SDIO response register * The parameter can be one of following values: * @arg SDIO_RES1 : Response Register 1 * @arg SDIO_RES2 : Response Register 2 * @arg SDIO_RES3 : Response Register 3 * @arg SDIO_RES4 : Response Register 4 * * @retval The Corresponding response register value */ uint32_t SDIO_ReadResponse(SDIO_RES_T res) { __IO uint32_t tmp = 0; tmp = ((uint32_t)(SDIO_BASE + 0x14)) + res; return (*(__IO uint32_t *) tmp); } /*! * @brief Configs the SDIO Dataaccording to the specified parameters in the dataConfig * * @param dataConfig: pointer to a SDIO_DataConfig_T structure * * @retval None */ void SDIO_ConfigData(SDIO_DataConfig_T *dataConfig) { uint32_t tempReg = 0; SDIO->DATATIME = dataConfig->dataTimeOut; SDIO->DATALEN = dataConfig->dataLength; tempReg = SDIO->DCTRL; /* Clear DTEN, DTSEL, DTDRCFG and DBSIZE bits */ tempReg &= ((uint32_t)0xFFFFFF08); tempReg |= (uint32_t)(dataConfig->dataBlockSize) << 4 | (dataConfig->transferDir) << 1 | (dataConfig->transferMode) << 2 | (dataConfig->DPSM); SDIO->DCTRL = tempReg; } /*! * @brief Fills each SDIO_DataConfig_T member with its default value * * @param dataConfig: pointer to a SDIO_DataConfig_T structure * * @retval None */ void SDIO_ConfigDataStructInit(SDIO_DataConfig_T *dataConfig) { dataConfig->dataTimeOut = 0xFFFFFFFF; dataConfig->dataLength = 0x00; dataConfig->dataBlockSize = SDIO_DATA_BLOCKSIZE_1B; dataConfig->transferDir = SDIO_TRANSFER_DIR_TO_CARD; dataConfig->transferMode = SDIO_TRANSFER_MODE_BLOCK; dataConfig->DPSM = SDIO_DPSM_DISABLE; } /*! * @brief Reads the SDIO Data counter * * @param None * * @retval The SDIO Data counter value */ uint32_t SDIO_ReadDataCounter(void) { return SDIO->DCNT; } /*! * @brief Write the SDIO Data * * @param data : a 32-bit data to write * * @retval None */ void SDIO_WriteData(uint32_t data) { SDIO->FIFODATA = data; } /*! * @brief Reads the SDIO Data * * @param None * * @retval The SDIO FIFO Data value */ uint32_t SDIO_ReadData(void) { return SDIO->FIFODATA; } /*! * @brief Reads the SDIO FIFO count value * * @param None * * @retval The SDIO FIFO count value */ uint32_t SDIO_ReadFIFOCount(void) { return SDIO->FIFOCNT; } /*! * @brief Enables SDIO start read wait * * @param None * * @retval None */ void SDIO_EnableStartReadWait(void) { SDIO->DCTRL_B.RWSTR = SET; } /*! * @brief Disables SDIO stop read wait * * @param None * * @retval None */ void SDIO_DisableStartReadWait(void) { SDIO->DCTRL_B.RWSTR = RESET; } /*! * @brief Disables SDIO start read wait * * @param None * * @retval None */ void SDIO_DisableStopReadWait(void) { SDIO->DCTRL_B.RWSTOP = RESET; } /*! * @brief Enables SDIO stop read wait * * @param None * * @retval None */ void SDIO_EnableStopReadWait(void) { SDIO->DCTRL_B.RWSTOP = SET; } /*! * @brief Config the read wait interval * * @param readWaitMode: SDIO read Wait Mode * The parameter can be one of following values: * @arg SDIO_READ_WAIT_MODE_DATA2 : Read Wait control using SDIO_DATA2 * @arg SDIO_READ_WAIT_MODE_CLK : Read Wait control by stopping SDIOCLK * * @retval None * * @note */ void SDIO_ConfigSDIOReadWaitMode(SDIO_READ_WAIT_MODE_T readWaitMode) { SDIO->DCTRL_B.RDWAIT = readWaitMode; } /*! * @brief Enables SDIO SD I/O Mode Operation * * @param None * * @retval None */ void SDIO_EnableSDIO(void) { SDIO->DCTRL_B.SDIOF = SET; } /*! * @brief Disables SDIO SD I/O Mode Operation * * @param None * * @retval None */ void SDIO_DisableSDIO(void) { SDIO->DCTRL_B.SDIOF = RESET; } /*! * @brief Ensables SDIO SD I/O Mode suspend command sending * * @param None * * @retval None */ void SDIO_EnableTxSDIOSuspend(void) { SDIO->CMD_B.SDIOSC = SET; } /*! * @brief Disables SDIO SD I/O Mode suspend command sending * * @param None * * @retval None */ void SDIO_DisableTxSDIOSuspend(void) { SDIO->CMD_B.SDIOSC = RESET; } /*! * @brief Enables the command completion signal * * @param None * * @retval None */ void SDIO_EnableCommandCompletion(void) { SDIO->CMD_B.CMDCPEN = SET; } /*! * @brief Disables the command completion signal * * @param None * * @retval None */ void SDIO_DisableCommandCompletion(void) { SDIO->CMD_B.CMDCPEN = RESET; } /*! * @brief Enables the CE-ATA interrupt * * @param None * * @retval None */ void SDIO_EnableCEATAInterrupt(void) { SDIO->CMD_B.INTEN = RESET; } /*! * @brief Disables the CE-ATA interrupt * * @param None * * @retval None */ void SDIO_DisableCEATAInterrupt(void) { SDIO->CMD_B.INTEN = SET; } /*! * @brief Ensables Sends CE-ATA command * * @param None * * @retval None */ void SDIO_EnableTxCEATA(void) { SDIO->CMD_B.ATACMD = SET; } /*! * @brief Disables Sends CE-ATA command * * @param None * * @retval None */ void SDIO_DisableTxCEATA(void) { SDIO->CMD_B.ATACMD = RESET; } /*! * @brief Enables the specified SDIO interrupt * * @param interrupt: Select the SDIO interrupt source * The parameter can be any combination of following values: * @arg SDIO_INT_COMRESP : Command response received (CRC check failed) interrupt * @arg SDIO_INT_DBDR : Data block sent/received (CRC check failed) interrupt * @arg SDIO_INT_CMDRESTO : Command response timeout interrupt * @arg SDIO_INT_DATATO : Data timeout interrupt * @arg SDIO_INT_TXUDRER : Transmit FIFO underrun error interrupt * @arg SDIO_INT_RXOVRER : Received FIFO overrun error interrupt * @arg SDIO_INT_CMDRES : Command response received (CRC check passed) interrupt * @arg SDIO_INT_CMDSENT : Command sent (no response required) interrupt * @arg SDIO_INT_DATAEND : Data end (data counter, SDIDCOUNT, is zero) interrupt * @arg SDIO_INT_SBE : Start bit not detected on all data signals in wide bus mode interrupt * @arg SDIO_INT_DBCP : Data block sent/received (CRC check passed) interrupt * @arg SDIO_INT_CMDACT : Command transfer in progress interrupt * @arg SDIO_INT_TXACT : Data transmit in progress interrupt * @arg SDIO_INT_RXACT : Data receive in progress interrupt * @arg SDIO_INT_TXFHF : Transmit FIFO Half Empty interrupt * @arg SDIO_INT_RXFHF : Receive FIFO Half Full interrupt * @arg SDIO_INT_TXFF : Transmit FIFO full interrupt * @arg SDIO_INT_RXFF : Receive FIFO full interrupt * @arg SDIO_INT_TXFE : Transmit FIFO empty interrupt * @arg SDIO_INT_RXFE : Receive FIFO empty interrupt * @arg SDIO_INT_TXDA : Data available in transmit FIFO interrupt * @arg SDIO_INT_RXDA : Data available in receive FIFO interrupt * @arg SDIO_INT_SDIOINT : SD I/O interrupt received interrupt * @arg SDIO_INT_ATAEND : CE-ATA command completion signal received for CMD61 interrupt * * @retval None */ void SDIO_EnableInterrupt(uint32_t interrupt) { SDIO->MASK |= interrupt; } /*! * @brief Disables the specified SDIO interrupt * * @param interrupt: Select the SDIO interrupt source * The parameter can be any combination of following values: * @arg SDIO_INT_COMRESP : Command response received (CRC check failed) interrupt * @arg SDIO_INT_DBDR : Data block sent/received (CRC check failed) interrupt * @arg SDIO_INT_CMDRESTO : Command response timeout interrupt * @arg SDIO_INT_DATATO : Data timeout interrupt * @arg SDIO_INT_TXUDRER : Transmit FIFO underrun error interrupt * @arg SDIO_INT_RXOVRER : Received FIFO overrun error interrupt * @arg SDIO_INT_CMDRES : Command response received (CRC check passed) interrupt * @arg SDIO_INT_CMDSENT : Command sent (no response required) interrupt * @arg SDIO_INT_DATAEND : Data end (data counter, SDIDCOUNT, is zero) interrupt * @arg SDIO_INT_SBE : Start bit not detected on all data signals in wide bus mode interrupt * @arg SDIO_INT_DBCP : Data block sent/received (CRC check passed) interrupt * @arg SDIO_INT_CMDACT : Command transfer in progress interrupt * @arg SDIO_INT_TXACT : Data transmit in progress interrupt * @arg SDIO_INT_RXACT : Data receive in progress interrupt * @arg SDIO_INT_TXFHF : Transmit FIFO Half Empty interrupt * @arg SDIO_INT_RXFHF : Receive FIFO Half Full interrupt * @arg SDIO_INT_TXFF : Transmit FIFO full interrupt * @arg SDIO_INT_RXFF : Receive FIFO full interrupt * @arg SDIO_INT_TXFE : Transmit FIFO empty interrupt * @arg SDIO_INT_RXFE : Receive FIFO empty interrupt * @arg SDIO_INT_TXDA : Data available in transmit FIFO interrupt * @arg SDIO_INT_RXDA : Data available in receive FIFO interrupt * @arg SDIO_INT_SDIOINT : SD I/O interrupt received interrupt * @arg SDIO_INT_ATAEND : CE-ATA command completion signal received for CMD61 interrupt * * @retval None */ void SDIO_DisableInterrupt(uint32_t interrupt) { SDIO->MASK &= ~interrupt; } /*! * @brief Reads the specified SDIO flag * * @param flag: Select the flag to read * The parameter can be one of following values: * @arg SDIO_FLAG_COMRESP : Command response received (CRC check failed) flag * @arg SDIO_FLAG_DBDR : Data block sent/received (CRC check failed) flag * @arg SDIO_FLAG_CMDRESTO : Command response timeout flag * @arg SDIO_FLAG_DATATO : Data timeout flag * @arg SDIO_FLAG_TXUDRER : Transmit FIFO underrun error flag * @arg SDIO_FLAG_RXOVRER : Received FIFO overrun error flag * @arg SDIO_FLAG_CMDRES : Command response received (CRC check passed) flag * @arg SDIO_FLAG_CMDSENT : Command sent (no response required) flag * @arg SDIO_FLAG_DATAEND : Data end (data counter is zero) flag * @arg SDIO_FLAG_SBE : Start bit not detected on all data signals in wide bus mode flag * @arg SDIO_FLAG_DBCP : Data block sent/received (CRC check passed) flag * @arg SDIO_FLAG_CMDACT : Command transfer in progress flag * @arg SDIO_FLAG_TXACT : Data transmit in progress flag * @arg SDIO_FLAG_RXACT : Data receive in progress flag * @arg SDIO_FLAG_TXFHF : Transmit FIFO Half Empty flag * @arg SDIO_FLAG_RXFHF : Receive FIFO Half Full flag * @arg SDIO_FLAG_TXFF : Transmit FIFO full flag * @arg SDIO_FLAG_RXFF : Receive FIFO full flag * @arg SDIO_FLAG_TXFE : Transmit FIFO empty flag * @arg SDIO_FLAG_RXFE : Receive FIFO empty flag * @arg SDIO_FLAG_TXDA : Data available in transmit FIFO flag * @arg SDIO_FLAG_RXDA : Data available in receive FIFO flag * @arg SDIO_FLAG_SDIOINT : SD I/O interrupt received flag * @arg SDIO_FLAG_ATAEND : CE-ATA command completion signal received for CMD61 flag * * @retval SET or RESET */ uint8_t SDIO_ReadStatusFlag(SDIO_FLAG_T flag) { return (SDIO->STS & flag) ? SET : RESET; } /*! * @brief Clears the specified SDIO flag * * @param flag: Select the flag to clear * The parameter can be any combination of following values: * @arg SDIO_FLAG_COMRESP : Command response received (CRC check failed) flag * @arg SDIO_FLAG_DBDR : Data block sent/received (CRC check failed) flag * @arg SDIO_FLAG_CMDRESTO : Command response timeout flag * @arg SDIO_FLAG_DATATO : Data timeout flag * @arg SDIO_FLAG_TXUDRER : Transmit FIFO underrun error flag * @arg SDIO_FLAG_RXOVRER : Received FIFO overrun error flag * @arg SDIO_FLAG_CMDRES : Command response received (CRC check passed) flag * @arg SDIO_FLAG_CMDSENT : Command sent (no response required) flag * @arg SDIO_FLAG_DATAEND : Data end (data counter is zero) flag * @arg SDIO_FLAG_SBE : Start bit not detected on all data signals in wide bus mode flag * @arg SDIO_FLAG_DBCP : Data block sent/received (CRC check passed) flag * @arg SDIO_FLAG_SDIOINT : SD I/O interrupt received flag * @arg SDIO_FLAG_ATAEND : CE-ATA command completion signal received for CMD61 flag * * @retval None */ void SDIO_ClearStatusFlag(uint32_t flag) { SDIO->ICF = flag; } /*! * @brief Reads the specified SDIO Interrupt flag * * @param flag: Select the SDIO interrupt source * The parameter can be one of following values: * @arg SDIO_INT_COMRESP : Command response received (CRC check failed) interrupt * @arg SDIO_INT_DBDR : Data block sent/received (CRC check failed) interrupt * @arg SDIO_INT_CMDRESTO : Command response timeout interrupt * @arg SDIO_INT_DATATO : Data timeout interrupt * @arg SDIO_INT_TXUDRER : Transmit FIFO underrun error interrupt * @arg SDIO_INT_RXOVRER : Received FIFO overrun error interrupt * @arg SDIO_INT_CMDRES : Command response received (CRC check passed) interrupt * @arg SDIO_INT_CMDSENT : Command sent (no response required) interrupt * @arg SDIO_INT_DATAEND : Data end (data counter is zero) interrupt * @arg SDIO_INT_SBE : Start bit not detected on all data signals in wide bus mode interrupt * @arg SDIO_INT_DBCP : Data block sent/received (CRC check passed) interrupt * @arg SDIO_INT_CMDACT : Command transfer in progress interrupt * @arg SDIO_INT_TXACT : Data transmit in progress interrupt * @arg SDIO_INT_RXACT : Data receive in progress interrupt * @arg SDIO_INT_TXFHF : Transmit FIFO Half Empty interrupt * @arg SDIO_INT_RXFHF : Receive FIFO Half Full interrupt * @arg SDIO_INT_TXFF : Transmit FIFO full interrupt * @arg SDIO_INT_RXFF : Receive FIFO full interrupt * @arg SDIO_INT_TXFE : Transmit FIFO empty interrupt * @arg SDIO_INT_RXFE : Receive FIFO empty interrupt * @arg SDIO_INT_TXDA : Data available in transmit FIFO interrupt * @arg SDIO_INT_RXDA : Data available in receive FIFO interrupt * @arg SDIO_INT_SDIOINT : SD I/O interrupt received interrupt * @arg SDIO_INT_ATAEND : CE-ATA command completion signal received for CMD61 interrupt * * @retval SET or RESET */ uint8_t SDIO_ReadIntFlag(SDIO_INT_T flag) { uint32_t intEnable; uint32_t intStatus; intEnable = (uint32_t)(SDIO->MASK & flag); intStatus = (uint32_t)(SDIO->STS & flag); if (intEnable && intStatus) { return SET; } return RESET; } /*! * @brief Clears the specified SDIO Interrupt pending bits * * @param flag: Select the SDIO interrupt source * The parameter can be any combination of following values: * @arg SDIO_INT_COMRESP : Command response received (CRC check failed) interrupt * @arg SDIO_INT_DBDR : Data block sent/received (CRC check failed) interrupt * @arg SDIO_INT_CMDRESTO : Command response timeout interrupt * @arg SDIO_INT_DATATO : Data timeout interrupt * @arg SDIO_INT_TXUDRER : Transmit FIFO underrun error interrupt * @arg SDIO_INT_RXOVRER : Received FIFO overrun error interrupt * @arg SDIO_INT_CMDRES : Command response received (CRC check passed) interrupt * @arg SDIO_INT_CMDSENT : Command sent (no response required) interrupt * @arg SDIO_INT_DATAEND : Data end (data counter is zero) interrupt * @arg SDIO_INT_SBE : Start bit not detected on all data signals in wide bus mode interrupt * @arg SDIO_INT_DBCP : Data block sent/received (CRC check passed) interrupt * @arg SDIO_INT_SDIOINT : SD I/O interrupt received interrupt * @arg SDIO_INT_ATAEND : CE-ATA command completion signal received for CMD61 interrupt * * @retval None */ void SDIO_ClearIntFlag(uint32_t flag) { SDIO->ICF = flag; } /**@} end of group SDIO_Functions */ /**@} end of group SDIO_Driver */ /**@} end of group APM32F4xx_StdPeriphDriver */