/**
* @file xmc_sdmmc.h
* @date 2019-05-07
*
* @cond
*********************************************************************************************************************
* XMClib v2.1.24 - XMC Peripheral Driver Library
*
* Copyright (c) 2015-2019, Infineon Technologies AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
* following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following
* disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
* Infineon Technologies AG dave@infineon.com).
*********************************************************************************************************************
*
* Change History
* --------------
*
* 2015-02-20:
* - Initial version
* - Documentation updates
*
* 2015-06-20:
* - Removed version macros and declaration of GetDriverVersion API
*
* 2016-01-16:
* - Added the following APIs to the XMC_SDMMC low level driver
* 1) XMC_SDMMC_EnableDelayCmdDatLines
* 2) XMC_SDMMC_DisableDelayCmdDatLines
* 3) XMC_SDMMC_SetDelay
* 4) XMC_SDMMC_EnableHighSpeed
* 5) XMC_SDMMC_DisableHighSpeed
*
* 2016-04-07:
* - Added XMC_SDMMC_COMMAND_RESPONSE_t
*
* 2016-07-11:
* - Adjust masks for the following functions:
* 1) XMC_SDMMC_SetBusVoltage
* 2) XMC_SDMMC_SetDataLineTimeout
* 3) XMC_SDMMC_SDClockFreqSelect
*
* 2017-02-14:
* - Added:
* 1) XMC_SDMMC_SetCardDetectionStatus()
* 2) XMC_SDMMC_SetCardDetectionSource()
*
* 2018-08-29:
* - XMC_SDMMC_SetCardDetectionStatus() and XMC_SDMMC_SetCardDetectionSource()
* Changed for XMC43/XMC47/XMC48 to use SDMMC Write Protection and Card Detection Control register instead of the test register of SDMMC host controller
* - Added for XMC43/XMC47/XMC48:
* 1) XMC_SDMMC_SetWriteProtectionSource()
* 2) XMC_SDMMC_SetWriteProtectionStatus()
*
* 2019-05-07:
* - Fix compilation issues on XMC45
* - Fix compilation warnings
*
* @endcond
*/
#ifndef XMC_SDMMC_H
#define XMC_SDMMC_H
/*******************************************************************************
* HEADER FILES
*******************************************************************************/
#include "xmc_common.h"
#if defined (SDMMC)
#if (UC_SERIES != XMC45)
#define SDMMC_CON_WPSEL_Pos 0
#define SDMMC_CON_WPSEL_Msk 0x00000001UL
#define SDMMC_CON_WPSVAL_Pos 4
#define SDMMC_CON_WPSVAL_Msk 0x00000010UL
#define SDMMC_CON_CDSEL_Pos 16
#define SDMMC_CON_CDSEL_Msk 0x00010000UL
#define SDMMC_CON_CDSVAL_Pos 20
#define SDMMC_CON_CDSVAL_Msk 0x00100000UL
#endif
/**
* @addtogroup XMClib XMC Peripheral Library
* @{
*/
/**
* @addtogroup SDMMC
* @brief Secure Digital/Multi Media Card (SDMMC) driver for the XMC4500 microcontroller
*
* The SDMMC peripheral provides an interface between SD/SDIO/MMC cards and the AHB. It handles
* the SD/SDIO protocol at transmission level. It automatically packs data and checks for CRC,
* start/end bits and format correctness. For SD cards, a maximum transfer rate of 24MB/sec is
* supported and for MMC cards, 48MB/sec.
*
* The peripheral can be used for applications that require large storage memory; e.g. Data logging,
* firmware updates or an embedded database.
*
* The SDMMC low level driver provides functions to configure and initialize the SDMMC hardware
* peripheral.
* @{
*/
/*******************************************************************************
* MACROS
*******************************************************************************/
/**
* A convenient symbol for the SDMMC peripheral base address
*/
#if defined (SDMMC)
# define XMC_SDMMC ((XMC_SDMMC_t *)SDMMC_BASE)
#else
# error 'SDMMC' base peripheral pointer not defined
#endif
/*
* Check for valid ACMD errors
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_MODULE_PTR(p) ((p) == XMC_SDMMC)
/*
* Check for valid ACMD errors
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_ACMD_ERR(v)\
((v == XMC_SDMMC_ACMD12_NOT_EXEC_ERR) ||\
(v == XMC_SDMMC_ACMD_TIMEOUT_ERR) ||\
(v == XMC_SDMMC_ACMD_CRC_ERR) ||\
(v == XMC_SDMMC_ACMD_END_BIT_ERR) ||\
(v == XMC_SDMMC_ACMD_IND_ERR) ||\
(v == XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR))
/*
* Check for valid SDCLK divider frequency
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_SDCLK_FREQ(f)\
((f == XMC_SDMMC_CLK_DIV_1) ||\
(f == XMC_SDMMC_CLK_DIV_2) ||\
(f == XMC_SDMMC_CLK_DIV_4) ||\
(f == XMC_SDMMC_CLK_DIV_8) ||\
(f == XMC_SDMMC_CLK_DIV_16) ||\
(f == XMC_SDMMC_CLK_DIV_32) ||\
(f == XMC_SDMMC_CLK_DIV_64) ||\
(f == XMC_SDMMC_CLK_DIV_128) ||\
(f == XMC_SDMMC_CLK_DIV_256))
/*
* Check for valid bus voltage levels
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_BUS_VOLTAGE(v)\
(v == XMC_SDMMC_BUS_VOLTAGE_3_3_VOLTS)
/*
* Check for valid data timeout counter values
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_DAT_TIMEOUT_COUNTER(c)\
((c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_13) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_14) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_15) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_16) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_17) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_18) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_19) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_20) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_21) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_22) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_23) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_24) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_25) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_26) ||\
(c == XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_27))
/*
* Valid number of data lines
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_DATA_LINES(l)\
((l == XMC_SDMMC_DATA_LINES_1) ||\
(l == XMC_SDMMC_DATA_LINES_4) ||\
(l == XMC_SDMMC_DATA_LINES_8))
/*
* Check data transfer dir: Host to card and vice-versa
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_CHECK_DATA_TRANSFER_DIR(d)\
((d == XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD) ||\
(d == XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST))
/*
* Min and max number of delay elements
*
* This macro is used in the LLD for assertion checks (XMC_ASSERT).
*/
#define XMC_SDMMC_MIN_DELAY_ELEMENTS (0U)
#define XMC_SDMMC_MAX_DELAY_ELEMENTS (15U)
/*******************************************************************************
* ENUMS
*******************************************************************************/
/**
* Number of data lines for SDMMC data transfer
*/
typedef enum XMC_SDMMC_DATA_LINES
{
XMC_SDMMC_DATA_LINES_1 = 0x00U, /**< Single data line mode */
XMC_SDMMC_DATA_LINES_4 = 0x02U, /**< 4-bit mode */
XMC_SDMMC_DATA_LINES_8 = 0x20U /**< SD 8-bit mode */
} XMC_SDMMC_DATA_LINES_t;
/**
* Valid SD clock frequency divider selection
*/
typedef enum XMC_SDMMC_SDCLK_FREQ_SEL
{
XMC_SDMMC_CLK_DIV_1 = 0x00U, /**< Base clock (10 Mhz -> 63 Mhz) */
XMC_SDMMC_CLK_DIV_2 = 0x01U, /**< Base clock divided by 2 */
XMC_SDMMC_CLK_DIV_4 = 0x02U, /**< Base clock divided by 4 */
XMC_SDMMC_CLK_DIV_8 = 0x04U, /**< Base clock divided by 8 */
XMC_SDMMC_CLK_DIV_16 = 0x08U, /**< Base clock divided by 16 */
XMC_SDMMC_CLK_DIV_32 = 0x10U, /**< Base clock divided by 32 */
XMC_SDMMC_CLK_DIV_64 = 0x20U, /**< Base clock divided by 64 */
XMC_SDMMC_CLK_DIV_128 = 0x40U, /**< Base clock divided by 128 */
XMC_SDMMC_CLK_DIV_256 = 0x80U /**< Base clock divided by 256 */
} XMC_SDMMC_SDCLK_FREQ_SEL_t;
/**
* Status return values for the SDMMC low level driver
*/
typedef enum XMC_SDMMC_STATUS
{
XMC_SDMMC_STATUS_SUCCESS = 0U, /**< Operation successful */
XMC_SDMMC_STATUS_CMD_LINE_BUSY, /**< Command line busy */
XMC_SDMMC_STATUS_DAT_LINE_BUSY /**< Data line busy */
} XMC_SDMMC_STATUS_t;
/**
* SDMMC events (Normal and error events)
*/
typedef enum XMC_SDMMC_EVENT
{
XMC_SDMMC_CMD_COMPLETE = 0x01U, /**< Command complete event */
XMC_SDMMC_TX_COMPLETE = 0x02U, /**< Transmit complete event */
XMC_SDMMC_BLOCK_GAP_EVENT = 0x04U, /**< Block gap event */
XMC_SDMMC_BUFFER_WRITE_READY = 0x10U, /**< Buffer write ready event */
XMC_SDMMC_BUFFER_READ_READY = 0x20U, /**< Buffer read ready event */
XMC_SDMMC_CARD_INS = 0x40U, /**< Card insert event */
XMC_SDMMC_CARD_REMOVAL = 0x80U, /**< Card removal event */
XMC_SDMMC_CARD_INT = 0x100U, /**< Card INT event */
XMC_SDMMC_CARD_ERR = 0x8000U, /**< Card error interrupt */
XMC_SDMMC_CMD_TIMEOUT_ERR = ((uint32_t)0x01 << 16U), /**< Command time-out error */
XMC_SDMMC_CMD_CRC_ERR = ((uint32_t)0x02U << 16U), /**< Command CRC error */
XMC_SDMMC_CMD_END_BIT_ERR = ((uint32_t)0x04U << 16U), /**< Command end bit error */
XMC_SDMMC_CMD_IND_ERR = ((uint32_t)0x08U << 16U), /**< Command index error */
XMC_SDMMC_DATA_TIMEOUT_ERR = ((uint32_t)0x10U << 16U), /**< Data time-out error */
XMC_SDMMC_DATA_CRC_ERR = ((uint32_t)0x20U << 16U), /**< Data CRC error */
XMC_SDMMC_DATA_END_BIT_ERR = ((uint32_t)0x40U << 16U), /**< Data end bit error */
XMC_SDMMC_CURRENT_LIMIT_ERR = ((uint32_t)0x80U << 16U), /**< Current limit error */
XMC_SDMMC_ACMD_ERR = ((uint32_t)0x100U << 16U), /**< ACMD error */
XMC_SDMMC_TARGET_RESP_ERR = ((uint32_t)0x1000U << 16U) /**< Target response error */
} XMC_SDMMC_EVENT_t;
/**
* SDMMC wakeup events
*/
typedef enum XMC_SDMMC_WAKEUP_EVENT
{
XMC_SDMMC_WAKEUP_EN_CARD_INT = SDMMC_WAKEUP_CTRL_WAKEUP_EVENT_EN_INT_Msk, /**< Wakeup on card interrupt */
XMC_SDMMC_WAKEUP_EN_CARD_INS = SDMMC_WAKEUP_CTRL_WAKEUP_EVENT_EN_INS_Msk, /**< Wakeup on SD card insertion */
XMC_SDMMC_WAKEUP_EN_CARD_REM = SDMMC_WAKEUP_CTRL_WAKEUP_EVENT_EN_REM_Msk /**< Wakeup SD card removal */
} XMC_SDMMC_WAKEUP_EVENT_t;
/**
* SDMMC software reset modes
*/
typedef enum XMC_SDMMC_SW_RESET
{
XMC_SDMMC_SW_RESET_ALL = SDMMC_SW_RESET_SW_RST_ALL_Msk, /**< Software reset all */
XMC_SDMMC_SW_RST_CMD_LINE = SDMMC_SW_RESET_SW_RST_CMD_LINE_Msk, /**< Software reset command line */
XMC_SDMMC_SW_RST_DAT_LINE = SDMMC_SW_RESET_SW_RST_DAT_LINE_Msk /**< Software reset data line */
} XMC_SDMMC_SW_RESET_t;
/**
* CMD12 response errors of Auto CMD12
*/
typedef enum XMC_SDMMC_ACMD_ERR
{
XMC_SDMMC_ACMD12_NOT_EXEC_ERR = SDMMC_ACMD_ERR_STATUS_ACMD12_NOT_EXEC_ERR_Msk, /**< ACMD12 not executed error */
XMC_SDMMC_ACMD_TIMEOUT_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_TIMEOUT_ERR_Msk, /**< ACMD timeout error */
XMC_SDMMC_ACMD_CRC_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_CRC_ERR_Msk, /**< ACMD CRC error */
XMC_SDMMC_ACMD_END_BIT_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_END_BIT_ERR_Msk, /**< ACMD end bit error */
XMC_SDMMC_ACMD_IND_ERR = SDMMC_ACMD_ERR_STATUS_ACMD_IND_ERR_Msk, /**< ACMD IND error */
XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR = SDMMC_ACMD_ERR_STATUS_CMD_NOT_ISSUED_BY_ACMD12_ERR_Msk /**< CMD not issued by ACMD12 */
} XMC_SDMMC_ACMD_ERR_t;
/**
* SDMMC response types
*/
typedef enum XMC_SDMMC_RESPONSE_TYPE
{
XMC_SDMMC_RESPONSE_TYPE_NO_RESPONSE = 0U, /**< No response */
XMC_SDMMC_RESPONSE_TYPE_R1, /**< Response type: R1 */
XMC_SDMMC_RESPONSE_TYPE_R1b, /**< Response type: R1b */
XMC_SDMMC_RESPONSE_TYPE_R2, /**< Response type: R2 */
XMC_SDMMC_RESPONSE_TYPE_R3, /**< Response type: R3 */
XMC_SDMMC_RESPONSE_TYPE_R6, /**< Response type: R6 */
XMC_SDMMC_RESPONSE_TYPE_R7 /**< Response type: R7 */
} XMC_SDMMC_RESPONSE_TYPE_t;
/**
* Command response selection
*/
typedef enum XMC_SDMMC_COMMAND_RESPONSE
{
XMC_SDMMC_COMMAND_RESPONSE_NONE = 0, /**< No Response */
XMC_SDMMC_COMMAND_RESPONSE_LONG = 1, /**< Response length 136 */
XMC_SDMMC_COMMAND_RESPONSE_SHORT = 2, /**< Response length 48 */
XMC_SDMMC_COMMAND_RESPONSE_SHORT_BUSY = 3, /**< Response length 48 check Busy after response */
} XMC_SDMMC_COMMAND_RESPONSE_t;
/**
* Types of SDMMC commands
*/
typedef enum XMC_SDMMC_COMMAND_TYPE
{
XMC_SDMMC_COMMAND_TYPE_NORMAL = 0U, /**< Command normal */
XMC_SDMMC_COMMAND_TYPE_SUSPEND, /**< Command suspend */
XMC_SDMMC_COMMAND_TYPE_RESUME, /**< Command resume */
XMC_SDMMC_COMMAND_TYPE_ABORT /**< Command abort */
} XMC_SDMMC_COMMAND_TYPE_t;
/**
* SDMMC transfer modes
*/
typedef enum XMC_SDMMC_TRANSFER_MODE_TYPE
{
XMC_SDMMC_TRANSFER_MODE_TYPE_SINGLE = 0x00U, /**< Transfer mode type: single */
XMC_SDMMC_TRANSFER_MODE_TYPE_INFINITE = 0x20U, /**< Transfer mode type: infinite */
XMC_SDMMC_TRANSFER_MODE_TYPE_MULTIPLE = 0x22U, /**< Transfer mode type: multiple */
XMC_SDMMC_TRANSFER_MODE_TYPE_STOP_MULTIPLE = 0x22U /**< Transfer mode type: multiple stop */
} XMC_SDMMC_TRANSFER_MODE_TYPE_t;
/**
* Auto command transfer modes
*/
typedef enum XMC_SDMMC_TRANSFER_MODE_AUTO_CMD
{
XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_DISABLED = 0x00U, /**< ACMD mode disabled */
XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_12 /**< ACMD12 mode */
} XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_t;
/**
* SDMMC bus voltage level
*/
typedef enum XMC_SDMMC_BUS_VOLTAGE
{
XMC_SDMMC_BUS_VOLTAGE_3_3_VOLTS = 0x07U /**< 3.3V */
} XMC_SDMMC_BUS_VOLTAGE_t;
/**
* Data line timeout counter values
*/
typedef enum XMC_SDMMC_DAT_TIMEOUT_COUNTER
{
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_13 = 0U, /**< SDCLK * (2 ^ 13) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_14 = 1U, /**< SDCLK * (2 ^ 14) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_15 = 2U, /**< SDCLK * (2 ^ 15) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_16 = 3U, /**< SDCLK * (2 ^ 16) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_17 = 4U, /**< SDCLK * (2 ^ 17) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_18 = 5U, /**< SDCLK * (2 ^ 18) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_19 = 6U, /**< SDCLK * (2 ^ 19) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_20 = 7U, /**< SDCLK * (2 ^ 20) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_21 = 8U, /**< SDCLK * (2 ^ 21) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_22 = 9U, /**< SDCLK * (2 ^ 22) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_23 = 10U, /**< SDCLK * (2 ^ 23) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_24 = 11U, /**< SDCLK * (2 ^ 24) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_25 = 12U, /**< SDCLK * (2 ^ 25) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_26 = 13U, /**< SDCLK * (2 ^ 26) */
XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_27 = 14U, /**< SDCLK * (2 ^ 27) */
} XMC_SDMMC_DAT_TIMEOUT_COUNTER_t;
/**
* SDMMC data transfer direction
*/
typedef enum XMC_SDMMC_DATA_TRANSFER_DIR
{
XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD = 0U, /**< Host to card */
XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST /**< Card to host */
} XMC_SDMMC_DATA_TRANSFER_DIR_t;
/**
* SDMMC card detection signal source
*/
typedef enum XMC_SDMMC_CD_SOURCE
{
#if UC_SERIES == XMC45 || defined(DOXYGEN)
XMC_SDMMC_CD_SOURCE_PIN = 0 << SDMMC_HOST_CTRL_CARD_DET_SIGNAL_DETECT_Pos, /**< P1.10 input pin selected */
XMC_SDMMC_CD_SOURCE_SW = 1 << SDMMC_HOST_CTRL_CARD_DET_SIGNAL_DETECT_Pos /**< Software is selected */
#else
XMC_SDMMC_CD_SOURCE_PIN = 0 << SDMMC_CON_CDSEL_Pos, /**< P1.10 input pin selected */
XMC_SDMMC_CD_SOURCE_SW = 1 << SDMMC_CON_CDSEL_Pos /**< Software is selected */
#endif
} XMC_SDMMC_CD_SOURCE_t;
/**
* Used to set the SDMMC card detection status when the card detection status source input is set to software
*/
typedef enum XMC_SDMMC_CD_STATUS
{
#if UC_SERIES == XMC45 || defined(DOXYGEN)
XMC_SDMMC_CD_STATUS_NO_CARD = 0 << SDMMC_HOST_CTRL_CARD_DETECT_TEST_LEVEL_Pos, /**< No card detected */
XMC_SDMMC_CD_STATUS_INSERTED = 1 << SDMMC_HOST_CTRL_CARD_DETECT_TEST_LEVEL_Pos /**< Card detected */
#else
XMC_SDMMC_CD_STATUS_NO_CARD = 0 << SDMMC_CON_CDSVAL_Pos, /**< No card detected */
XMC_SDMMC_CD_STATUS_INSERTED = 1 << SDMMC_CON_CDSVAL_Pos /**< Card detected */
#endif
} XMC_SDMMC_CD_STATUS_t;
#if UC_SERIES != XMC45 || defined(DOXYGEN)
/**
* SDMMC card write protection signal source
* @note Only available for XMC4300, XMC4800 and XMC4700 series
*/
typedef enum XMC_SDMMC_WP_SOURCE
{
XMC_SDMMC_WP_SOURCE_PIN = 0 << SDMMC_CON_WPSEL_Pos, /**< P1.1 input pin selected */
XMC_SDMMC_WP_SOURCE_SW = 1 << SDMMC_CON_WPSEL_Pos /**< Software is selected */
} XMC_SDMMC_WP_SOURCE_t;
/**
* Used to set the SDMMC card protection status when the card protection status source input is set to software
* @note Only available for XMC4300, XMC4800 and XMC4700 series
*/
typedef enum XMC_SDMMC_WP_STATUS
{
XMC_SDMMC_WP_STATUS_NO_WRITE_PROTECTION = 0 << SDMMC_CON_WPSVAL_Pos, /**< No write protection */
XMC_SDMMC_WP_STATUS_WRITE_PROTECTION = 1 << SDMMC_CON_WPSVAL_Pos /**< Write protection active */
} XMC_SDMMC_WP_STATUS_t;
#endif
/*******************************************************************************
* DATA STRUCTURES
*******************************************************************************/
/**
* SDMMC device structure
*
* The structure represents a collection of all hardware registers used
* to configure the SDMMC peripheral on the XMC4500 microcontroller. The
* registers can be accessed with ::XMC_SDMMC.
*/
typedef struct
{
__I uint32_t RESERVED0;
__IO uint16_t BLOCK_SIZE;
__IO uint16_t BLOCK_COUNT;
__IO uint32_t ARGUMENT1;
__IO uint16_t TRANSFER_MODE;
__IO uint16_t COMMAND;
__I uint32_t RESPONSE[4];
__IO uint32_t DATA_BUFFER;
__I uint32_t PRESENT_STATE;
__IO uint8_t HOST_CTRL;
__IO uint8_t POWER_CTRL;
__IO uint8_t BLOCK_GAP_CTRL;
__IO uint8_t WAKEUP_CTRL;
__IO uint16_t CLOCK_CTRL;
__IO uint8_t TIMEOUT_CTRL;
__IO uint8_t SW_RESET;
__IO uint16_t INT_STATUS_NORM;
__IO uint16_t INT_STATUS_ERR;
__IO uint16_t EN_INT_STATUS_NORM;
__IO uint16_t EN_INT_STATUS_ERR;
__IO uint16_t EN_INT_SIGNAL_NORM;
__IO uint16_t EN_INT_SIGNAL_ERR;
__I uint16_t ACMD_ERR_STATUS;
__I uint16_t RESERVED1[9];
__O uint16_t FORCE_EVENT_ACMD_ERR_STATUS;
__O uint16_t FORCE_EVENT_ERR_STATUS;
__I uint32_t RESERVED2[8];
__O uint32_t DEBUG_SEL;
__I uint32_t RESERVED3[30];
__IO uint32_t SPI;
__I uint32_t RESERVED4[2];
__I uint16_t SLOT_INT_STATUS;
} XMC_SDMMC_t;
/* Anonymous structure/union guard start */
#if defined (__CC_ARM)
#pragma push
#pragma anon_unions
#elif defined (__TASKING__)
#pragma warning 586
#endif
/**
* Present state of the SDMMC host controller
*
* The structure presents a convenient way to obtain the SDMMC peripheral's
* present state information (for example, the write protect pin level). The
* XMC_SDMMC_GetPresentState() API can be used to populate the structure
* with the state of the SD host controller.
*/
typedef union XMC_SDMMC_PRESENT_STATE
{
struct
{
uint32_t command_inihibit_cmd : 1; /**< Command: Inhibit command */
uint32_t command_inihibit_dat : 1; /**< Command: Inhibit data */
uint32_t dat_line_active : 1; /**< Data line active */
uint32_t : 5;
uint32_t write_transfer_active : 1; /**< Write transfer active */
uint32_t read_transfer_active : 1; /**< Read transfer active */
uint32_t buffer_write_enable : 1; /**< Buffer write enable */
uint32_t buffer_read_enable : 1; /**< Buffer read enable */
uint32_t : 4;
uint32_t card_inserted : 1; /**< Card inserted */
uint32_t card_state_stable : 1; /**< Card state stable */
uint32_t card_detect_pin_level : 1; /**< Card detect pin level */
uint32_t write_protect_pin_level : 1; /**< Write protect pin level */
uint32_t dat_3_0_pin_level : 4; /**< Data 3_0 pin level */
uint32_t cmd_line_level : 1; /**< Command line level */
uint32_t dat7_4_pin_level : 4; /**< Data 7_4 pin level */
uint32_t : 3;
};
uint32_t b32;
} XMC_SDMMC_PRESENT_STATE_t;
/**
* SDMMC transfer mode configuration
*/
typedef struct XMC_SDMMC_TRANSFER_MODE
{
uint32_t block_size;
uint32_t num_blocks;
XMC_SDMMC_TRANSFER_MODE_TYPE_t type;
XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_t auto_cmd;
XMC_SDMMC_DATA_TRANSFER_DIR_t direction;
} XMC_SDMMC_TRANSFER_MODE_t;
/**
* Represent an SDMMC command
*
* The structure holds the configuration for an SDMMC command. The SDMMC
* COMMAND register is a 16-bit register which is responsible for enabling
* configuration parameters like command type, response type, index check
* enable (and a few more). Once SDMMC.COMMAND is configured, the
* XMC_SDMMC_SendCommand() function can be used to send the command.
*/
typedef union XMC_SDMMC_COMMAND
{
struct
{
uint16_t response_type_sel : 2; /**< Response type select ::XMC_SDMMC_COMMAND_RESPONSE_t */
uint16_t : 1;
uint16_t crc_check_en : 1; /**< Command CRC check enable */
uint16_t index_check_en : 1; /**< Command index check enable */
uint16_t dat_present_sel : 1; /**< Data present select */
uint16_t cmd_type : 2; /**< Command type ::XMC_SDMMC_COMMAND_TYPE_t */
uint16_t cmd_index : 6; /**< Command index */
uint16_t : 2;
};
uint16_t cmd;
} XMC_SDMMC_COMMAND_t;
/* Anonymous structure/union guard end */
#if defined (__CC_ARM)
#pragma pop
#elif defined (__TASKING__)
#pragma warning restore
#endif
/**
* Card response structure
*/
typedef struct XMC_SDMMC_RESPONSE
{
uint32_t response_0;
uint32_t response_2;
uint32_t response_4;
uint32_t response_6;
} XMC_SDMMC_RESPONSE_t;
/**
* SDMMC configuration data structure
*
* The structure is used to configure the bus width and the clock divider.
*/
typedef struct XMC_SDMMC_CONFIG
{
uint8_t bus_width; /**< SDMMC bus width */
XMC_SDMMC_SDCLK_FREQ_SEL_t clock_divider; /**< SDMMC clock divider */
} XMC_SDMMC_CONFIG_t;
/*******************************************************************************
* API PROTOTYPES
*******************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool
*
* \parDescription:
* Get power status of the SDMMC peripheral
*
* \par
* The function checks the SD_BUS_POWER bit-field of the POWER_CTRL register and returns
* a boolean value - "on" or "off".
*/
bool XMC_SDMMC_GetPowerStatus(XMC_SDMMC_t *const sdmmc);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Enable SDMMC peripheral
*
* \par
* The function de-asserts the peripheral reset. The peripheral needs to be initialized.
*/
void XMC_SDMMC_Enable(XMC_SDMMC_t *const sdmmc);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Disable SDMMC peripheral
*
* \par
* The function asserts the peripheral reset.
*/
void XMC_SDMMC_Disable(XMC_SDMMC_t *const sdmmc);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param config A pointer to a constant XMC_SDMMC_CONFIG_t structure containing the
* bus width and clock divider configuration
* @return ::XMC_SDMMC_STATUS_SUCCESS
*
* \parDescription:
* Initialize the SDMMC peripheral
*
* \par
* The function enables the SDMMC peripheral, sets the internal clock divider register
* and sets the bus width.
*/
XMC_SDMMC_STATUS_t XMC_SDMMC_Init(XMC_SDMMC_t *const sdmmc, const XMC_SDMMC_CONFIG_t *config);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
* logically OR'd events
* @return None
*
* \parDescription:
* Enable SDMMC normal and error event(s)
*
* \par
* The function first sets the bit-fields of EN_INT_STATUS_NORM and EN_INT_STATUS_ERR
* registers to enable interrupt status for requested normal/error SDMMC events. It then
* sets the bit-fields of EN_INT_SIGNAL_NORM and EN_INT_SIGNAL_ERR to enable the
* interrupt generation for the requested events.
*/
void XMC_SDMMC_EnableEvent(XMC_SDMMC_t *const sdmmc, uint32_t event);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
* logically OR'd events
* @return None
*
* \parDescription:
* Disable normal and error SDMMC event(s)
*
* \par
* The function disables the interrupt generation for the requested events by clearing
* the bit-fields of EN_INT_SIGNAL_NORM and EN_INT_SIGNAL_ERR registers.
*
* \parNote:
* The XMC_SDMMC_DisableEvent() function doesn't reset the the interrupt status. One
* may still use XMC_SDMMC_GetEvent() to check the status of requested events even if
* the interrupt generation is already disabled.
*/
void XMC_SDMMC_DisableEvent(XMC_SDMMC_t *const sdmmc, uint32_t event);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
* logically OR'd events
* @return None
*
* \parDescription:
* Clear SDMMC event(s)
*
* \par
* The function clears requested normal/error events by settings the bit-fields of
* the INT_STATUS register. Please check SDMMC_INT_STATUS_NORM in the XMC45000
* manual for more details.
*/
void XMC_SDMMC_ClearEvent(XMC_SDMMC_t *const sdmmc, uint32_t event);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (XMC_SDMMC_EVENT_t)
* @return bool
*
* \parDescription:
* Get SDMMC event status
*
* \par
* The function returns the status of a single requested (normal/error) event by
* reading the appropriate bit-fields of the INT_STATUS register.
*/
bool XMC_SDMMC_GetEvent(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_EVENT_t event);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
* logically OR'd events
* @return None
*
* \parDescription:
* Enable event status
*
* \par
* The function sets the bit-fields of EN_INT_STATUS_NORM and EN_INT_STATUS_ERR
* registers to enable interrupt status for requested normal/error SDMMC events.
*/
void XMC_SDMMC_EnableEventStatus(XMC_SDMMC_t *const sdmmc, uint32_t event);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (XMC_SDMMC_EVENT_t) or a valid combination of
* logically OR'd events
* @return None
*
* \parDescription:
* Disable event status
*
* \par
* The function resets the bit-fields of EN_INT_STATUS_NORM and EN_INT_STATUS_ERR
* registers to disable interrupt status for requested normal/error SDMMC events.
*/
void XMC_SDMMC_DisableEventStatus(XMC_SDMMC_t *const sdmmc, uint32_t event);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC event (::XMC_SDMMC_EVENT_t) or a valid combination of
* logically OR'd events
* @return None
*
* \parDescription:
* Trigger SDMMC error events
*
* \par
* The SDMMC peripheral supports triggering of following error events:
*
* ::XMC_SDMMC_CMD_TIMEOUT_ERR, ::XMC_SDMMC_CMD_CRC_ERR, ::XMC_SDMMC_CMD_END_BIT_ERR,
* ::XMC_SDMMC_CMD_IND_ERR, ::XMC_SDMMC_DATA_TIMEOUT_ERR, ::XMC_SDMMC_DATA_CRC_ERR,
* ::XMC_SDMMC_DATA_END_BIT_ERR, ::XMC_SDMMC_CURRENT_LIMIT_ERR, ::XMC_SDMMC_ACMD_ERR,
* ::XMC_SDMMC_TARGET_RESP_ERR
*
* For triggering Auto CMD12 error, see XMC_SDMMC_TriggerACMDErr()
*/
__STATIC_INLINE void XMC_SDMMC_TriggerEvent(XMC_SDMMC_t *const sdmmc, uint32_t event)
{
XMC_ASSERT("XMC_SDMMC_TriggerEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->FORCE_EVENT_ERR_STATUS |= (uint16_t)(event >> 16U);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param source A valid SDMMC card detection signal source (::XMC_SDMMC_CD_SOURCE_t)
* @return None
*
* \parDescription:
* Selects source for card detection
*/
__STATIC_INLINE void XMC_SDMMC_SetCardDetectionSource(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_CD_SOURCE_t source)
{
XMC_ASSERT("XMC_SDMMC_SetCardDetectionSource: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
#if UC_SERIES == XMC45
sdmmc->HOST_CTRL |= (sdmmc->HOST_CTRL & (uint32_t)~SDMMC_HOST_CTRL_CARD_DET_SIGNAL_DETECT_Msk) | source;
#else
XMC_UNUSED_ARG(sdmmc);
*(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_CDSEL_Msk) | source;
#endif
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param status A valid SDMMC card detection status (::XMC_SDMMC_CD_STATUS_t)
* @return None
*
* \parDescription:
* Sets the card detection status indicating whether card is inserted or not.
* Generates (card ins or card removal) interrupt when the normal interrupt is enabled.
* @note Only valid if SDMMC card detection signal source is set to XMC_SDMMC_CD_SOURCE_SW
*
*/
__STATIC_INLINE void XMC_SDMMC_SetCardDetectionStatus(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_CD_STATUS_t status)
{
XMC_ASSERT("XMC_SDMMC_SetCardDetectionStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
#if UC_SERIES == XMC45
sdmmc->HOST_CTRL |= (sdmmc->HOST_CTRL & (uint32_t)~SDMMC_HOST_CTRL_CARD_DETECT_TEST_LEVEL_Msk) | status;
#else
XMC_UNUSED_ARG(sdmmc);
*(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_CDSVAL_Msk) | status;
#endif
}
#if (UC_SERIES != XMC45) || defined(DOXYGEN)
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param source A valid SDMMC card detection signal source (::XMC_SDMMC_WP_SOURCE_t)
* @return None
*
* \parDescription:
* Selects input for card write protection status
*/
__STATIC_INLINE void XMC_SDMMC_SetWriteProtectionSource(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_WP_SOURCE_t source)
{
XMC_ASSERT("XMC_SDMMC_SetWriteProtectionSource: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_UNUSED_ARG(sdmmc);
#if UC_SERIES != XMC45
*(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_WPSEL_Msk) | source;
#endif
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param status A valid SDMMC card detection status (::XMC_SDMMC_WP_STATUS_t)
* @return None
*
* \parDescription:
* Sets the card write protection status indicating whether card is write protected or not.
* @note Only valid if SDMMC card detection signal source is set to XMC_SDMMC_WP_SOURCE_SW
*
*/
__STATIC_INLINE void XMC_SDMMC_SetWriteProtectionStatus(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_WP_STATUS_t status)
{
XMC_ASSERT("XMC_SDMMC_SetWriteProtectionStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_UNUSED_ARG(sdmmc);
#if UC_SERIES != XMC45
*(uint32_t *)SDMMC_CON = (*(uint32_t *)SDMMC_CON & (uint32_t)~SDMMC_CON_WPSVAL_Msk) | status;
#endif
}
#endif
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool
*
* \parDescription:
* Check if any error event has occured
*
* \par
* The function can typically be used for writing an error interrupt recovery routine.
* Should any error be indicated (If XMC_SDMMC_IsAnyErrorEvent() returns true), the
* routine may then clear the event after indicating the error event and reset the
* SDMMC command and data lines.
*/
__STATIC_INLINE bool XMC_SDMMC_IsAnyErrorEvent(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_IsAnyErrorEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (bool)(sdmmc->INT_STATUS_ERR);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC wakeup event (::XMC_SDMMC_WAKEUP_EVENT_t) or a valid combination
* of logically OR'd wakeup events
* @return None
*
* \parDescription:
* Enable wakeup event(s)
*
* \par
* The function enables SDMMC wakeup events by setting appropriate bit-fields of the WAKEUP_CTRL
* register.
*
* List of supported wakeup events -> Wakeup on:
* 1) Card interrupt
* 2) SD card insertion
* 3) SD card removal
*/
__STATIC_INLINE void XMC_SDMMC_EnableWakeupEvent(XMC_SDMMC_t *const sdmmc, uint32_t event)
{
XMC_ASSERT("XMC_SDMMC_EnableWakeupEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->WAKEUP_CTRL |= (uint8_t)event;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param event A valid SDMMC wakeup event (::XMC_SDMMC_WAKEUP_EVENT_t) or a valid combination
* of logically OR'd wakeup events
* @return None
*
* \parDescription:
* Disable wakeup event(s)
*
* \par
* The function disables SDMMC wakeup events by clearing appropriate bit-fields of the WAKEUP_CTRL
* register.
*
* List of supported wakeup events -> Wakeup on:
* 1) Card interrupt
* 2) SD card insertion
* 3) SD card removal
*/
__STATIC_INLINE void XMC_SDMMC_DisableWakeupEvent(XMC_SDMMC_t *const sdmmc, uint32_t event)
{
XMC_ASSERT("XMC_SDMMC_DisableWakeupEvent: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->WAKEUP_CTRL &= (uint8_t)~event;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param error A valid SDMMC ACMD error (::XMC_SDMMC_ACMD_ERR_t)
* @return bool
*
* \parDescription:
* Get status of Auto CMD12 errors
*
* \par
* The function detects the presence of an Auto CMD12 error. A boolean is returned to
* indicate if an error is detected.
*/
__STATIC_INLINE bool XMC_SDMMC_GetACMDErrStatus(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_ACMD_ERR_t error)
{
XMC_ASSERT("XMC_SDMMC_GetACMDErrStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_GetACMDErrStatus: Invalid ACMD response error", XMC_SDMMC_CHECK_ACMD_ERR(error));
return (bool)(sdmmc->ACMD_ERR_STATUS & (uint16_t)error);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param error A valid SDMMC ACMD error (::XMC_SDMMC_ACMD_ERR_t) or a valid combination
* of logically OR'd ACMD error events
* @return None
*
* \parDescription:
* Triggers Auto CMD12 error(s)
*
* \par
* This function triggers Auto CMD12 error(s) by setting appropriate bit-fields of the
* FORCE_EVENT_ACMD_ERR_STATUS register.
*
* \parRelated APIs:
* XMC_SDMMC_TriggerEvent()
*/
__STATIC_INLINE void XMC_SDMMC_TriggerACMDErr(XMC_SDMMC_t *const sdmmc, uint32_t error)
{
XMC_ASSERT("XMC_SDMMC_TriggerACMDErr: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->FORCE_EVENT_ACMD_ERR_STATUS |= (uint16_t)error;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return uint32_t The value held in the SDMMC FIFO
*
* \parDescription:
* Use this function to read a single word (32 bits) from the SDMMC FIFO.
*/
__STATIC_INLINE uint32_t XMC_SDMMC_ReadFIFO(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_ReadFIFO: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (sdmmc->DATA_BUFFER);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param data Pointer to a data word (32 bits) that needs to be written to the FIFO
* @return None
*
* \parDescription:
* Use this function to write a single word (32 bits) to the SDMMC FIFO.
*/
__STATIC_INLINE void XMC_SDMMC_WriteFIFO(XMC_SDMMC_t *const sdmmc, uint32_t *data)
{
XMC_ASSERT("XMC_SDMMC_WriteFIFO: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->DATA_BUFFER = *data;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Enable SDMMC bus power
*
* \par
* The function sets the SD_BUS_POWER bit-field in the POWER_CTRL register, enabling the
* bus power. It may be invoked after enabling the SD clock (XMC_SDMMC_SDClockEnable()).
*/
__STATIC_INLINE void XMC_SDMMC_BusPowerOn(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_BusPowerOn: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->POWER_CTRL |= (uint8_t)(SDMMC_POWER_CTRL_SD_BUS_POWER_Msk);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Disable SDMMC bus power
*
* \par
* The function resets the SD_BUS_POWER bit-field in the POWER_CTRL register, disabling the
* bus power.
*/
__STATIC_INLINE void XMC_SDMMC_BusPowerOff(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_BusPowerOff: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->POWER_CTRL &= (uint8_t)~SDMMC_POWER_CTRL_SD_BUS_POWER_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Enable the internal SDMMC clock
*
* \par
* The function enables the internal clock of the SDMMC peripheral. To check if the
* clock is stable, use XMC_SDMMC_GetClockStability().
*
* \parNote:
* Invoke XMC_SDMMC_Init() before using this function.
*/
__STATIC_INLINE void XMC_SDMMC_Start(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_Start: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
/* Enable internal clock */
sdmmc->CLOCK_CTRL |= (uint16_t)SDMMC_CLOCK_CTRL_INTERNAL_CLOCK_EN_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool
*
* \parDescription:
* Check internal clock stability
*
* \par
* Use this function to check the internal SDMMC clock stability. The function returns a
* boolean value indicating internal clock stability (true = stable)
*/
__STATIC_INLINE bool XMC_SDMMC_GetClockStability(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_GetClockStability: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
/* Return clock stability */
return (bool)(sdmmc->CLOCK_CTRL & SDMMC_CLOCK_CTRL_INTERNAL_CLOCK_STABLE_Msk);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Disable internal SDMMC clock
*
* \par
* The function disables the internal clock of the SDMMC peripheral. The SDMMC registers
* can still be read and written even if the internal clock is disabled.
*/
__STATIC_INLINE void XMC_SDMMC_Stop(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_Stop: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->CLOCK_CTRL &= (uint16_t)~SDMMC_CLOCK_CTRL_INTERNAL_CLOCK_EN_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Enable the SD clock
*
* \par
* The function sets the SDCLOCK_EN bit-field of the CLOCK_CTRL register, enabling the
* SD clock. It can be invoked after the internal clock has achieved stability. SD card
* initialization process may then follow.
*/
__STATIC_INLINE void XMC_SDMMC_SDClockEnable(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_SDClockEnable: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->CLOCK_CTRL |= (uint16_t)SDMMC_CLOCK_CTRL_SDCLOCK_EN_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return None
*
* \parDescription:
* Disable the SD clock
*
* \par
* The function resets the SDCLOCK_EN bit-field of the CLOCK_CTRL register, disabling the
* SD clock. It can be used alongside a SD card information reset routine (if required).
*/
__STATIC_INLINE void XMC_SDMMC_SDClockDisable(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_SDClockDisable: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->CLOCK_CTRL &= (uint16_t)~SDMMC_CLOCK_CTRL_SDCLOCK_EN_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param reset_mode Reset mode or a bitwise combination of modes
* @return None
*
* \parDescription:
* Set SDMMC software reset request
*
* \par
* The function sets in the SDMMC SW_RESET register:
* 1) bit 0 to reset all
* 2) bit 1 to reset CMD line
* 3) bit 2 reset DAT line
*
* It is typically used to reset the SD HOST controller's registers.
*/
__STATIC_INLINE void XMC_SDMMC_SetSWReset(XMC_SDMMC_t *const sdmmc, uint32_t reset_mode)
{
XMC_ASSERT("XMC_SDMMC_SetSWReset: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->SW_RESET |= (uint8_t)reset_mode;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return Software reset status
*
* \parDescription:
* Get SDMMC software reset status
*
* \par
* The SD host takes some time to reset its registers after invoking XMC_SDMMC_SetSWReset().
* Since XMC_SDMMC_SetSWReset() is a non-blocking function, XMC_SDMMC_GetSWResetStatus() has
* been provided to check the software reset status. The return value needs to be masked
* with the reset mode (XMC_SDMMC_SW_RESET_t) to get a specific software reset status value.
*/
__STATIC_INLINE uint32_t XMC_SDMMC_GetSWResetStatus(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_GetSWResetStatus: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (uint32_t)(sdmmc->SW_RESET);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return XMC_SDMMC_PRESENT_STATE_t A structure storing the present state of the host controller
*
* \parDescription:
* Get the present state of the SDMMC host controller
*
* \par
* Get the values of each bit-field in SDMMC_PRESENT_STATE register
* The function call populates an instance of the XMC_SDMMC_PRESENT_STATE_t structure with
* the state of the SD host controller and returns it to the caller.
*/
__STATIC_INLINE XMC_SDMMC_PRESENT_STATE_t XMC_SDMMC_GetPresentState(const XMC_SDMMC_t *const sdmmc)
{
XMC_SDMMC_PRESENT_STATE_t result;
XMC_ASSERT("XMC_SDMMC_GetPresentState: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
result.b32 = (uint32_t)sdmmc->PRESENT_STATE;
return result;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool SDMMC command line status
*
* \parDescription:
* Check if the command line is busy
*
* \par
* The function reads the SDMMC PRESENT_STATE register and returns "true" if the command
* line is busy ("false" otherwise). The command line must be free before sending an SDMMC
* command with XMC_SDMMC_SendCommand().
*/
__STATIC_INLINE bool XMC_SDMMC_IsCommandLineBusy(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_IsCommandLineBusy: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (bool)(sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_COMMAND_INHIBIT_CMD_Msk);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool SDMMC data line status
*
* \parDescription:
* Check if the data line is busy
*
* \par
* The function reads the SDMMC PRESENT_STATE register and returns "true" if the data
* line is busy ("false" otherwise). The data line must be free before sending an SDMMC
* command with XMC_SDMMC_SendCommand().
*/
__STATIC_INLINE bool XMC_SDMMC_IsDataLineBusy(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_IsDataLineBusy: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (bool)(sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_COMMAND_INHIBIT_DAT_Msk);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool Status of all data lines
*
* \parDescription:
* Check if all data line are high
*
* \par
* The function reads the SDMMC PRESENT_STATE register and returns "true" if all data
* lines are high. It can be used to handle SDMMC error conditions. For example, if an
* error event (XMC_SDMMC_IsAnyErrorEvent()) is detected and all data lines are high,
* the user code can conclude that the error is of a "recoverable" type.
*/
__STATIC_INLINE bool XMC_SDMMC_IsAllDataLinesHigh(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_IsAllDataLinesHigh: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return ((((sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_DAT_3_0_PIN_LEVEL_Msk) >>
SDMMC_PRESENT_STATE_DAT_3_0_PIN_LEVEL_Pos) == 0x0FU) ? true : false);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param command A pointer to a constant of type XMC_SDMMC_COMMAND_t, pointing to the command configuration
* @param arg Command argument
* @return ::XMC_SDMMC_STATUS_SUCCESS
*
* \parDescription:
* Send normal SDMMC command
*
* \par
* Use this function to send a normal SDMMC command. This non-blocking function sets the
* ARGUMENT1 and COMMAND registers. It is the user's responsibility to check if the command
* and data lines are busy (XMC_SDMMC_IsDataLineBusy(), XMC_SDMMC_IsCommandLineBusy()).
*/
XMC_SDMMC_STATUS_t XMC_SDMMC_SendCommand(XMC_SDMMC_t *const sdmmc, const XMC_SDMMC_COMMAND_t *command, uint32_t arg);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return uint32_t SDMMC command response
*
* \parDescription:
* Get card response (no Auto command)
*
* \par
* This function returns [39:8] bits of the card response. The others are checked automatically
* by the peripheral. This function can be used with response type R1, R1b, R3, R4, R5, R5b, R6
* but it doesn't support the retrieving of R1 of Auto CMD 23 and R1b of Auto CMD 12. To get
* these responses, use XMC_SDMMC_GetAutoCommandResponse().
*/
__STATIC_INLINE uint32_t XMC_SDMMC_GetCommandResponse(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_GetCommandResponse: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (sdmmc->RESPONSE[0]);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return uint32_t Auto command response value
*
* \parDescription:
* Get card response of Auto commands
*
* \par
* This function returns card response [39:8] bits of auto commands: R1 of Auto CMD 23 and
* R1b of Auto CMD 12.
*/
__STATIC_INLINE uint32_t XMC_SDMMC_GetAutoCommandResponse(const XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_GetAutoCommandResponse: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (sdmmc->RESPONSE[3]);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param response Pointer to structure type XMC_SDMMC_RESPONSE_t to store the full response
* @return None
*
* \parDescription:
* Get card R2 response
*
* \par
* The R2 response is 120 bits wide. The function reads all peripheral registers and store in
* the response data structure.
*/
void XMC_SDMMC_GetR2Response(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_RESPONSE_t *const response);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param transfer_mode Transfer mode configuration
* @return None
*
* \parDescription:
* Configure data transfer mode
*
* \par
* The function configures block size, block count, type of data transfer, response type
* and sets the auto command configuration. Use this function to configure a multi-block
* SDMMC transfer.
*/
void XMC_SDMMC_SetDataTransferMode(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_TRANSFER_MODE_t *const transfer_mode);
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return uint32_t Number of blocks that need to be transferred
*
* \parDescription:
* Get the number of blocks that need to be transferred
*
* \par
* This function is valid only for multiple block transfers. The host controller
* decrements the block count after each block transfer and stops when the count reaches
* zero. It can only be accessed when no transaction is happening (i.e after a transaction
* has stopped). This function returns an invalid value during the transfer.
*
* When saving transfer context as a result of the suspend command, the number of blocks
* yet to be transferred can be determined by using this function.
*/
__STATIC_INLINE uint32_t XMC_SDMMC_GetTransferBlocksNum(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_GetTransferBlocksNum: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (uint32_t)(sdmmc->BLOCK_COUNT);
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param enabled "true" to enable read wait control, "false" to disable read wait control.
* @return None
*
* \parDescription:
* Configure read wait control
*
* \par
* The read wait function is optional for SDIO cards. If the card supports read wait and
* XMC_SDMMC_GetTransferBlocksNum() is executed, the SDMMC peripheral will stop read data
* using DAT[2] line. If this feature is not enabled the peripheral has to stop the SD
* clock to hold read data, restricting commands generation.
*
* When the host driver detects an SD card insertion, it sets this bit according to the
* CCCR of the SDIO card. If the card does not support read wait, this feature shall
* never be enabled otherwise a DAT line conflict may occur. If this feature is disabled,
* Suspend/Resume cannot be supported.
*/
__STATIC_INLINE void XMC_SDMMC_SetReadWaitControl(XMC_SDMMC_t *const sdmmc, bool enabled)
{
XMC_ASSERT("XMC_SDMMC_SetReadWaitControl: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->BLOCK_GAP_CTRL = (uint8_t)((sdmmc->BLOCK_GAP_CTRL & (uint8_t)~SDMMC_BLOCK_GAP_CTRL_READ_WAIT_CTRL_Msk) |
(uint8_t)((uint8_t)enabled << SDMMC_BLOCK_GAP_CTRL_READ_WAIT_CTRL_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param enabled "true" to set stop at block gap, "false" for transfer
* @return None
*
* \parDescription:
* Stop at block gap request
*
* \par
* The function is used to terminate a transaction execution at the next block gap for
* non-DMA transfers.
*/
__STATIC_INLINE void XMC_SDMMC_SetStopAtBlockGap(XMC_SDMMC_t *const sdmmc, bool enabled)
{
XMC_ASSERT("XMC_SDMMC_SetStopAtBlockGap: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->BLOCK_GAP_CTRL = (uint8_t)((sdmmc->BLOCK_GAP_CTRL & (uint8_t)~SDMMC_BLOCK_GAP_CTRL_STOP_AT_BLOCK_GAP_Msk) |
(uint8_t)((uint8_t)enabled << SDMMC_BLOCK_GAP_CTRL_STOP_AT_BLOCK_GAP_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param enabled "true" to restart transaction, "false" is ignored
* @return None
*
* \parDescription:
* Issue a continue request
*
* \par
* The function is used to restart a transaction which was stopped using the "Stop at
* block gap" request. (XMC_SDMMC_SetStopAtBlockGap())
*/
__STATIC_INLINE void XMC_SDMMC_SetContinueRequest(XMC_SDMMC_t *const sdmmc, bool enabled)
{
XMC_ASSERT("XMC_SDMMC_SetContinueRequest: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->BLOCK_GAP_CTRL = ((sdmmc->BLOCK_GAP_CTRL & (uint8_t)~SDMMC_BLOCK_GAP_CTRL_CONTINUE_REQ_Msk) |
(uint8_t)((uint8_t)enabled << SDMMC_BLOCK_GAP_CTRL_CONTINUE_REQ_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @return bool
*
* \parDescription:
* Get continue request
*
* \par
* The function returns the status of the BLOCK_GAP_CTRL.CONTINUE_REQ bit-field. It
* returns "true" if the transaction is restarted after a "stop at block gap" request.
*/
__STATIC_INLINE bool XMC_SDMMC_GetContinueRequest(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_GetContinueRequest: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
return (bool)(sdmmc->BLOCK_GAP_CTRL & (uint8_t)(1U << SDMMC_BLOCK_GAP_CTRL_CONTINUE_REQ_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param config A pointer to the SDMMC configuration structure (::XMC_SDMMC_CONFIG_t)
* @return None
*
* \parDescription:
* Enable interrupt at block gap
*
* \par
* The function sets the BLOCK_GAP_CTRL.INT_AT_BLOCK_GAP bit-field to enable interrupt
* at block gap for a multi-block transfer. This bit is only valid in a 4-bit mode of
* the SDIO card.
*/
__STATIC_INLINE void XMC_SDMMC_EnableInterruptAtBlockGap(XMC_SDMMC_t *const sdmmc, const XMC_SDMMC_CONFIG_t *config)
{
XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: This operation is only valid in 4-bit mode",
(config->bus_width == XMC_SDMMC_DATA_LINES_1));
XMC_UNUSED_ARG(config);
sdmmc->BLOCK_GAP_CTRL |= (uint8_t)SDMMC_BLOCK_GAP_CTRL_INT_AT_BLOCK_GAP_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param config A pointer to the SDMMC configuration structure (::XMC_SDMMC_CONFIG_t)
* @return None
*
* \parDescription:
* Disable interrupt at block gap
*
* \par
* The function resets the BLOCK_GAP_CTRL.INT_AT_BLOCK_GAP bit-field to disable interrupt
* at block gap. This bit is only valid in a 4-bit mode of the SDIO card.
*/
__STATIC_INLINE void XMC_SDMMC_DisableInterruptAtBlockGap(XMC_SDMMC_t *const sdmmc,
const XMC_SDMMC_CONFIG_t *config)
{
XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_EnableInterruptAtBlockGap: This operation is only valid in 4-bit mode",
(config->bus_width == XMC_SDMMC_DATA_LINES_1));
XMC_UNUSED_ARG(config);
sdmmc->BLOCK_GAP_CTRL &= (uint8_t)~SDMMC_BLOCK_GAP_CTRL_INT_AT_BLOCK_GAP_Msk;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param clk Desired clock frequency (::XMC_SDMMC_SDCLK_FREQ_SEL_t)
* @return None
*
* \parDescription:
* Set SD clock frequency
*
* \par
* The function sets the CLOCK_CTRL register to configure the frequency of the SD clock
* pin. The register is programmed with the divisor of the base clock frequency (clk).
*
* The following settings are permitted (8-bit divided clock mode):
* 00H: base clock (10MHz->63MHz)
* 01H: base clock divided by 2
* 10H: base clock divided by 32
* 02H: base clock divided by 4
* 04H: base clock divided by 8
* 08H: base clock divided by 16
* 20H: base clock divided by 64
* 40H: base clock divided by 128
* 80H: base clock divided by 256
*
* \parNote:
* The internal clock should be disabled before updating frequency clock select. Please
* see section 2.2.14 -> "Clock Control Register" in the SD HOST specification for more
* information.
*/
__STATIC_INLINE void XMC_SDMMC_SDClockFreqSelect(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_SDCLK_FREQ_SEL_t clk)
{
XMC_ASSERT("XMC_SDMMC_SDClockFreqSelect: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_SDClockFreqSelect: Invalid clock frequency selection", XMC_SDMMC_CHECK_SDCLK_FREQ(clk));
sdmmc->CLOCK_CTRL = (uint16_t)((sdmmc->CLOCK_CTRL & (uint32_t)~SDMMC_CLOCK_CTRL_SDCLK_FREQ_SEL_Msk) |
(uint32_t)(clk << SDMMC_CLOCK_CTRL_SDCLK_FREQ_SEL_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param bus_voltage Desired bus voltage (::XMC_SDMMC_BUS_VOLTAGE_t)
* @return None
*
* \parDescription:
* Set SDMMC bus voltage
*
* \par
* The function sets the CLOCK_CTRL register to configure the bus voltage. Currently,
* 3.3 volts is the supported voltage level. This function is relevant within the host
* controller initialization routine.
*/
__STATIC_INLINE void XMC_SDMMC_SetBusVoltage(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_BUS_VOLTAGE_t bus_voltage)
{
XMC_ASSERT("XMC_SDMMC_SetBusVoltage: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_SetBusVoltage: Invalid bus voltage", XMC_SDMMC_CHECK_BUS_VOLTAGE(bus_voltage));
sdmmc->POWER_CTRL = (uint8_t)((sdmmc->POWER_CTRL & (uint32_t)~SDMMC_POWER_CTRL_SD_BUS_VOLTAGE_SEL_Msk) |
(uint32_t)(bus_voltage << SDMMC_POWER_CTRL_SD_BUS_VOLTAGE_SEL_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param timeout Data line timeout value
* @return None
*
* \parDescription:
* Set data line timeout
*
* \par
* Use the function to set the interval by which the data line timeouts are detected. The
* timeout clock frequency is generated by dividing the SD clock (TMCLK) by the timeout argument.
* This function must be called before setting the bus voltage (XMC_SDMMC_SetBusVoltage()).
*/
__STATIC_INLINE void XMC_SDMMC_SetDataLineTimeout(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_DAT_TIMEOUT_COUNTER_t timeout)
{
XMC_ASSERT("XMC_SDMMC_SetDataLineTimeout: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_SetDataLineTimeout: Invalid timeout", XMC_SDMMC_CHECK_DAT_TIMEOUT_COUNTER(timeout));
sdmmc->TIMEOUT_CTRL = (uint8_t)((sdmmc->TIMEOUT_CTRL & (uint32_t)~SDMMC_TIMEOUT_CTRL_DAT_TIMEOUT_CNT_VAL_Msk) |
(uint32_t)(timeout << SDMMC_TIMEOUT_CTRL_DAT_TIMEOUT_CNT_VAL_Pos));
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param lines Number of data lines to use (::XMC_SDMMC_DATA_LINES_t)
* @return None
*
* \parDescription:
* Set data transfer width
*
* \par
* Use the function to set the data transfer width. Before using this function, an ACMD6
* command (with R1 response type) must be sent to switch the bus width.
*/
__STATIC_INLINE void XMC_SDMMC_SetDataTransferWidth(XMC_SDMMC_t *const sdmmc, XMC_SDMMC_DATA_LINES_t lines)
{
XMC_ASSERT("XMC_SDMMC_SetDataTransferWidth: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_SetDataTransferWidth: Invalid no. of data lines", XMC_SDMMC_CHECK_DATA_LINES(lines));
sdmmc->HOST_CTRL &= (uint8_t)~(XMC_SDMMC_DATA_LINES_1 | XMC_SDMMC_DATA_LINES_4 | XMC_SDMMC_DATA_LINES_8);
sdmmc->HOST_CTRL |= (uint8_t)lines;
}
/**
* @param sdmmc A constant pointer to XMC_SDMMC_t, pointing to the SDMMC base address
* @param dir Transfer direction (::XMC_SDMMC_DATA_TRANSFER_DIR_t)
* @return None
*
* \parDescription:
* Set data transfer direction
*
* \par
* Use the function to set the data transfer direction: host to card OR card to host. It
* is typically used to configure block operations (read/write) on the SD card. For
* example, XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD must be used for a write block operation.
*/
__STATIC_INLINE void XMC_SDMMC_SetDataTransferDirection(XMC_SDMMC_t *const sdmmc,
XMC_SDMMC_DATA_TRANSFER_DIR_t dir)
{
XMC_ASSERT("XMC_SDMMC_SetDataTransferDirection: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
XMC_ASSERT("XMC_SDMMC_SetDataTransferDirection: Invalid direction", XMC_SDMMC_CHECK_DATA_TRANSFER_DIR(dir));
sdmmc->TRANSFER_MODE = (uint16_t)((sdmmc->TRANSFER_MODE & (uint16_t)~SDMMC_TRANSFER_MODE_TX_DIR_SELECT_Msk) |
(uint16_t)((uint16_t)dir << SDMMC_TRANSFER_MODE_TX_DIR_SELECT_Pos));
}
/**
* @param None
* @return None
*
* \parDescription:
* Enable delay on the command/data out lines
*
* \par
* Use the function to enable delay on the command/data out lines. Invoke this function
* before selecting the number of delay elements.
*/
__STATIC_INLINE void XMC_SDMMC_EnableDelayCmdDatLines(void)
{
SCU_GENERAL->SDMMCDEL |= (uint32_t)SCU_GENERAL_SDMMCDEL_TAPEN_Msk;
}
/**
* @param None
* @return None
*
* \parDescription:
* Disable delay on the command/data out lines
*
* \par
* Use the function to disable delay on the command/data out lines.
*/
__STATIC_INLINE void XMC_SDMMC_DisableDelayCmdDatLines(void)
{
SCU_GENERAL->SDMMCDEL &= (uint32_t)~SCU_GENERAL_SDMMCDEL_TAPEN_Msk;
}
/**
* @param tapdel Number of delay elements to select
* @return None
*
* \parDescription:
* Set number of delay elements on the command/data out lines
*
* \par
* Use the function to set the number of delay elements on the command/data out lines.
* The function writes the delay value to the SDMMC delay control register (SDMMCDEL)
* within the realm of the SCU peripheral. A delay of tapdel + 1 is considered as the
* final selected number of delay elements.
*/
__STATIC_INLINE void XMC_SDMMC_SetDelay(uint8_t tapdel)
{
SCU_GENERAL->SDMMCDEL = (uint32_t)((SCU_GENERAL->SDMMCDEL & (uint32_t)~SCU_GENERAL_SDMMCDEL_TAPDEL_Msk) |
(uint32_t)(tapdel << SCU_GENERAL_SDMMCDEL_TAPDEL_Pos));
}
/**
* @param None
* @return None
*
* \parDescription:
* High speed enable
*
* \par
* Use the function to enable high speed operation. The default is a normal speed operation.
* Once enabled, the host controller outputs command and data lines at the rising edge of the
* SD clock (up to 50 MHz for SD).
*/
__STATIC_INLINE void XMC_SDMMC_EnableHighSpeed(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_EnableHighSpeed: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->HOST_CTRL |= (uint8_t)SDMMC_HOST_CTRL_HIGH_SPEED_EN_Msk;
}
/**
* @param None
* @return None
*
* \parDescription:
* High speed disable
*
* \par
* Use the function to disable high speed operation. The host controller will switch back
* to a normal speed mode. In this mode, the host controller outputs command and data lines
* at 25 MHz for SD.
*/
__STATIC_INLINE void XMC_SDMMC_DisableHighSpeed(XMC_SDMMC_t *const sdmmc)
{
XMC_ASSERT("XMC_SDMMC_DisableHighSpeed: Invalid module pointer", XMC_SDMMC_CHECK_MODULE_PTR(sdmmc));
sdmmc->HOST_CTRL &= (uint8_t)~SDMMC_HOST_CTRL_HIGH_SPEED_EN_Msk;
}
#ifdef __cplusplus
}
#endif
/**
* @}
*/
/**
* @}
*/
#endif /* #if defined (SDMMC) */
#endif