+ * int main(void)
+ * {
+ * DAVE_STATUS_t status;
+ * DAVE_APP_VERSION_t app_version;
+ * SDMMC_BLOCK_CARD_STATE_t card_status;
+ *
+ * status = DAVE_Init(); // SDMMC_BLOCK_Init() is called from DAVE_Init()
+ *
+ * sdmmc_status = SDMMC_BLOCK_Initialize(&SDMMC_BLOCK_0);
+ *
+ * if (sdmmc_status == SDMMC_BLOCK_STATUS_SUCCESS)
+ * {
+ * do
+ * {
+ * send_data[count] = count;
+ * } while (count++ < 1024);
+ *
+ * sdmmc_status = SDMMC_BLOCK_WriteBlock(&SDMMC_BLOCK_0, send_data, 1004U, 2U);
+ *
+ * if (sdmmc_status == SDMMC_BLOCK_STATUS_SUCCESS)
+ * {
+ * sdmmc_status = SDMMC_BLOCK_ReadBlock(&SDMMC_BLOCK_0, read_data, 1004U, 2U);
+ *
+ * for (count = 0; count < 1024; count++)
+ * {
+ * if(read_data[count] != send_data[count])
+ * status = DAVE_STATUS_FAILURE;
+ * }
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_CTRL_TRIM, &erase_address);
+ *
+ * sdmmc_status = SDMMC_BLOCK_ReadBlock(&SDMMC_BLOCK_0, read_data, 1004U, 2U);
+ *
+ * for (count = 0; count < 1024; count++)
+ * {
+ * if(read_data[count] != 0U)
+ * status = DAVE_STATUS_FAILURE;
+ * }
+ * }
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_CTRL_EJECT, &buffer);
+ * }
+ *
+ * if(status == DAVE_STATUS_FAILURE)
+ * {
+ * // Placeholder for error handler code. The while loop below can be replaced with an user error handler.
+ * XMC_DEBUG("DAVE APPs initialization failed\n");
+ *
+ * while(1U)
+ * {
+ *
+ * }
+ * }
+ *
+ * // Placeholder for user application code. The while loop below can be replaced with user application code.
+ * while(1U)
+ * {
+ *
+ * }
+ * }
+ * @endcode
+ */
+SDMMC_BLOCK_STATUS_t SDMMC_BLOCK_WriteBlock(SDMMC_BLOCK_t *const obj,
+ uint8_t *write_buf,
+ const uint32_t sector_number,
+ const uint8_t sector_count);
+
+/**
+ * @brief Control the specified SDMMC device features and the miscellaneous device independent functions
+ * other than disk read/write.
+ * @param obj A pointer to SDMMC_BLOCK_t, pointing to the SDMMC_BLOCK handle configuration
+ * @param command Specifies the command code.
+ * @param buffer Pointer to the parameter buffer depends on the command code.\n
+ * When it is not used, specify a NULL pointer.
+ * @return SDMMC_BLOCK_STATUS_t: Status of SDMMC_BLOCK APP operation.\n
+ * SDMMC_BLOCK_STATUS_SUCCESS: on successful operation.\n
+ * SDMMC_BLOCK_STATUS_FAILURE: If the specified operation fails.\n
+ * SDMMC_BLOCK_STATUS_NOTRDY : Card is not available or not initialized\n
+ * SDMMC_BLOCK_STATUS_LOCKED : Card is locked with password\n
+ * SDMMC_BLOCK_STATUS_PARERR : If invalid parameter is passed as argument.\n
+ * SDMMC_BLOCK_STATUS_WRPRT : Card is write protected.\n
+ *
+ * \parDescription:
+ * For Locking features, the user must provide the password information in the SDMMC_BLOCK_PASSWORD_t structure.
+ *
+ * The IOCTL commands used are: \n\n
+ * Generic IOCTL commands: \n\n
+ * SDMMC_BLOCK_CTRL_SYNC: Flush disk cache (for write functions). \n ('buffer' can be NULL). \n\n
+ * SDMMC_BLOCK_GET_SECTOR_COUNT: Get media size. \n ('buffer' must refer to a uint32_t) \n\n
+ * SDMMC_BLOCK_GET_SECTOR_SIZE: Get sector size. \n ('buffer' must refer to a uint32_t) \n\n
+ * SDMMC_BLOCK_GET_BLOCK_SIZE: Get erase block size. \n ('buffer' must refer to a uint32_t) \n\n
+ * SDMMC_BLOCK_CTRL_TRIM: Inform device that the data on the block of sectors is no longer used. \n
+ * ('buffer must refer to a value of type SDMMC_BLOCK_ERASE_ADDRESS_t). \n\n
+ * SDMMC_BLOCK_CTRL_EJECT: Eject media. \n ('buffer' can be NULL). \n\n
+ * MMC/SD card specific IOCTL commands: \n\n
+ * SDMMC_BLOCK_MMC_GET_TYPE: Get card type i.e. Standard Capacity v2/v1x or High Capacity card. \n
+ * ('buffer' must refer to a value of type SDMMC_BLOCK_CARD_TYPE_t). \n\n
+ * SDMMC_BLOCK_MMC_GET_CSD: Get Card's Specific Data register. \n ('buffer' must refer to a value of type SDMMC_BLOCK_SDV2_CSD_t). \n\n
+ * SDMMC_BLOCK_MMC_GET_CID: Get Card's Identification Number. \n ('buffer' must refer to a value of type SDMMC_BLOCK_CID_t). \n\n
+ * SDMMC_BLOCK_MMC_GET_OCR: Get Card's Operating Condition Register \n ('buffer' must refer to a uint32_t). \n\n
+ * SDMMC_BLOCK_MMC_GET_SDSTAT: Get SD bus status information. \n ('buffer' must refer to a uin8_t array of size 64 bytes) \n\n
+ * SDMMC_BLOCK_MMC_LOCK_CARD: Locks the card. \n ('buffer' must refer to a value of type SDMMC_BLOCK_PASSWORD_t). \n\n
+ * SDMMC_BLOCK_MMC_UNLOCK_CARD: Unlocks the card. \n ('buffer' must refer to a value of type SDMMC_BLOCK_PASSWORD_t). \n\n
+ * SDMMC_BLOCK_MMC_SET_PASSWD: Set/replace the password. \n ('buffer' must refer to a value of type SDMMC_BLOCK_PASSWORD_t). \n\n
+ * SDMMC_BLOCK_MMC_CLEAR_PASSWD: Clear the password. \n ('buffer' must refer to a value of type SDMMC_BLOCK_PASSWORD_t). \n\n
+ * SDMMC_BLOCK_MMC_SET_LOCK: Sets the password and locks the card in the same power cycle. \n ('buffer' must refer to a value of type SDMMC_BLOCK_PASSWORD_t). \n\n
+ * SDMMC_BLOCK_MMC_READ_LOCK_STATUS: Reads the current lock status of the card. \n ('buffer' must refer to a value of type SDMMC_BLOCK_CARD_LOCK_STATUS_t). \n\n
+ * SDMMC_BLOCK_MMC_FORCE_ERASE: Force erase the password. It is useful when user forgets the password. \n ('buffer' is NULL). \n\n
+ *
+ *
+ * Example Usage1:
+ * The example initializes the card. If initialization is successful the control then checks for the lock_status.
+ * For a card without any password, the program should indicate that the card is not locked. Then a password of length
+ * 6 is set and the card is locked with the configured password. The lock status is then checked to ensure that it is
+ * locked. Post this operation, the card is unlocked. If the unlock operation is successful, the card should
+ * indicate so. The password is then cleared.
+ * @code
+ * #include //Declarations from DAVE Code Generation (includes SFR declaration)
+ *
+ * SDMMC_BLOCK_PASSWORD_t password =
+ * {
+ * .old_pwd_len = 6U,
+ * .old_pwd = {'p', 'a', 's', 's', 'w', 'd'},
+ * };
+ *
+ * int main(void)
+ * {
+ * DAVE_STATUS_t status;
+ * SDMMC_BLOCK_STATUS_t sdmmc_status;
+ * SDMMC_BLOCK_CARD_LOCK_STATUS_t lock_status;
+ *
+ * status = DAVE_Init(); // Initialization of DAVE APPs
+ *
+ * sdmmc_status = SDMMC_BLOCK_Initialize(&SDMMC_BLOCK_0);
+ *
+ * if (sdmmc_status == SDMMC_BLOCK_STATUS_SUCCESS)
+ * {
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_READ_LOCK_STATUS, &lock_status);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_SET_PASSWD, &password);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_LOCK_CARD, &password);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_READ_LOCK_STATUS, &lock_status);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_UNLOCK_CARD, &password);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_READ_LOCK_STATUS, &lock_status);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_CLEAR_PASSWD, &password);
+ * }
+ *
+ * if(status == DAVE_STATUS_FAILURE)
+ * {
+ * // Placeholder for error handler code. The while loop below can be replaced with an user error handler.
+ * XMC_DEBUG("DAVE APPs initialization failed\n");
+ *
+ * while(1U)
+ * {
+ *
+ * }
+ * }
+ *
+ * // Placeholder for user application code. The while loop below can be replaced with user application code.
+ * while(1U)
+ * {
+ *
+ * }
+ * }
+ * @endcode
+ *
+ * Example Usage2:
+ * This example demonstrates the procedure to change the existing password of the card and then performs a force erase
+ * of the card.
+ * @code
+ * #include //Declarations from DAVE Code Generation (includes SFR declaration)
+ * #include
+ * SDMMC_BLOCK_PASSWORD_t password =
+ * {
+ * .old_pwd_len = 6U,
+ * .old_pwd = {'p', 'a', 's', 's', 'w', 'd'},
+ * .new_pwd_len = 6U,
+ * .new_pwd = {'s', 'e', 'c', 'r', 'e', 't'},
+ * };
+ *
+ * int main(void)
+ * {
+ * DAVE_STATUS_t status;
+ * SDMMC_BLOCK_STATUS_t sdmmc_status;
+ * SDMMC_BLOCK_CARD_LOCK_STATUS_t lock_status;
+ * uint8_t buffer;
+ *
+ * status = DAVE_Init(); /. Initialization of DAVE APPs
+ *
+ * sdmmc_status = SDMMC_BLOCK_Initialize(&SDMMC_BLOCK_0);
+ *
+ * if (sdmmc_status == SDMMC_BLOCK_STATUS_SUCCESS)
+ * {
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_READ_LOCK_STATUS, &lock_status);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_SET_PASSWD, &password);
+ *
+ * // Set the old password value with the new one. SO that card can be locked with the password configured.
+ * memcpy(password.old_pwd, password.new_pwd, password.new_pwd_len);
+ * password.old_pwd_len = password.new_pwd_len;
+ * password.new_pwd_len = 0U;
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_LOCK_CARD, &password);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_READ_LOCK_STATUS, &lock_status);
+ *
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_FORCE_ERASE, &buffer);
+ * }
+ *
+ * if(status == DAVE_STATUS_FAILURE)
+ * {
+ * // Placeholder for error handler code. The while loop below can be replaced with an user error handler.
+ * XMC_DEBUG("DAVE APPs initialization failed\n");
+ *
+ * while(1U)
+ * {
+ *
+ * }
+ * }
+ *
+ * // Placeholder for user application code. The while loop below can be replaced with user application code.
+ * while(1U)
+ * {
+ *
+ * }
+ * }
+ * @endcode
+ */
+SDMMC_BLOCK_STATUS_t SDMMC_BLOCK_Ioctl(SDMMC_BLOCK_t *const obj,
+ const uint8_t command,
+ void *buffer);
+
+#if SDMMC_BLOCK_SD_CARD_DETECTION_SUPPORT
+
+#ifdef SDMMC_BLOCK_SD
+
+ /**
+ * @brief Register a callback function
+ * @param obj A pointer to SDMMC_BLOCK_t, pointing to the SDMMC_BLOCK handle configuration
+ * @param cb A pointer to a function accepting ::SDMMC_BLOCK_SD_INTERRUPT_t and returning void
+ * @return SDMMC_BLOCK_STATUS_t: Status of callback function registration.\n
+ * SDMMC_BLOCK_STATUS_SUCCESS - On successful registration.\n
+ * SDMMC_BLOCK_STATUS_PARERR - If registration fails (invalid callback parameter).\n
+ *
+ * \parDescription:
+ * The function can be used to register a callback function to signal a card detection
+ * event. The microcontroller will generate interrupts for a card insertion and a card
+ * removal event. The callback can be used to signal these events.
+ *
+ * Example Usage:
+ * The following example registers a callback function for the card-detect events:
+ * card insertion and removal.
+ * @code
+ * #include
+ *
+ * volatile bool led_status = false;
+ *
+ * void card_detect_callback(SDMMC_BLOCK_SD_INTERRUPT_t card_ins)
+ * {
+ * if (card_ins == SDMMC_BLOCK_SD_INTERRUPT_CARD_INSERTION)
+ * {
+ * // Turn an LED on perhaps? Be sure to configure the LED first.
+ * led_status = true;
+ * }
+ * else
+ * {
+ * // Turn the LED off perhaps?
+ * led_status = false;
+ * }
+ * }
+ *
+ * int main(void)
+ * {
+ * DAVE_STATUS_t status;
+ * SDMMC_BLOCK_STATUS_t sdmmc_status;
+ * SDMMC_BLOCK_CARD_LOCK_STATUS_t lock_status;
+ *
+ * // Register the callback now
+ * sdmmc_status = SDMMC_BLOCK_RegisterCallback(&SDMMC_BLOCK_0, card_detect_callback);
+ *
+ * status = DAVE_Init(); // SDMMC_BLOCK_Init() is called from DAVE_Init()
+ *
+ * sdmmc_status = SDMMC_BLOCK_Initialize(&SDMMC_BLOCK_0);
+ * if (sdmmc_status == SDMMC_BLOCK_STATUS_SUCCESS)
+ * {
+ * sdmmc_status = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, SDMMC_BLOCK_MMC_READ_LOCK_STATUS, &lock_status);
+ * }
+ *
+ * // Placeholder for user application code.
+ * while(1U)
+ * {
+ * }
+ * }
+ * @endcode
+ */
+SDMMC_BLOCK_STATUS_t SDMMC_BLOCK_RegisterCallback(SDMMC_BLOCK_t *const obj,
+ void (*cb)(SDMMC_BLOCK_SD_INTERRUPT_t));
+
+#endif /* #ifdef SDMMC_BLOCK_SD */
+
+#endif /* #if SDMMC_BLOCK_SD_CARD_DETECTION_SUPPORT */
+
+/**
+ * @}
+ */
+
+/* Support for C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#include "sdmmc_block_extern.h"
+
+#endif /* SDMMC_BLOCK_H */
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_conf.c b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_conf.c
new file mode 100644
index 00000000..4ecfedee
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_conf.c
@@ -0,0 +1,326 @@
+/*********************************************************************************************************************
+* DAVE APP Name : SDMMC_BLOCK APP Version: 4.0.22
+*
+* NOTE:
+* This file is generated by DAVE. Any manual modification done to this file will be lost when the code is regenerated.
+*********************************************************************************************************************/
+
+/**
+ * @cond
+ ***********************************************************************************************************************
+ * Copyright (c) 2016, 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
+ * --------------
+ *
+ * 2016-01-20:
+ * - Initial version
+ *
+ * 2016-02-05:
+ * - RTOS support added
+ *
+ * 2016-04-05:
+ * - MISRA fixes.
+ * - Bug fixes done for PR.
+ *
+ * 2016-04-05:
+ * - Code genration fix for XMC4300 device.
+ *
+ * @endcond
+ */
+
+/***********************************************************************************************************************
+ * HEADER FILES
+ **********************************************************************************************************************/
+
+#include "sdmmc_block.h"
+
+/**********************************************************************************************************************
+ * LOCAL ROUTINES
+ **********************************************************************************************************************/
+
+/* SDMMC_BLOCK configuration initialization */
+static void SDMMC_BLOCK_0_Config_Init(void);
+
+
+/**********************************************************************************************************************
+ * EXTERNAL REFERENCES
+ **********************************************************************************************************************/
+
+extern SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_ErrorInterruptHandler(SDMMC_BLOCK_t *const obj,
+ uint16_t int_status);
+
+extern SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_NormalInterruptHandler(SDMMC_BLOCK_t *const obj,
+ uint16_t int_status);
+
+
+/**********************************************************************************************************************
+ * GLOBAL VARIABLES
+ **********************************************************************************************************************/
+
+volatile uint16_t normal_int_status; /* Normal interrupt status */
+volatile uint16_t err_int_status; /* Error interrupt status */
+
+
+/**********************************************************************************************************************
+ * DATA STRUCTURES
+ **********************************************************************************************************************/
+
+
+/* SDMMC_BLOCK Data 0 pin config */
+const SDMMC_BLOCK_GPIO_CONFIG_t SDMMC_BLOCK_0_DATA_0_PIN_CONFIG =
+{
+ .config =
+ {
+ .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
+ .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_MEDIUM_EDGE,
+ .output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
+ },
+ .hw_control = XMC_GPIO_HWCTRL_PERIPHERAL1,
+};
+
+/* SDMMC_BLOCK Data 0 pin */
+const SDMMC_BLOCK_PIN_CONFIG_t SDMMC_BLOCK_0_DATA_0 =
+{
+ .port = (XMC_GPIO_PORT_t *)PORT4_BASE,
+ .pin = (uint8_t)0,
+ .config = &SDMMC_BLOCK_0_DATA_0_PIN_CONFIG
+};
+
+
+/* SDMMC_BLOCK Data 1 pin config */
+const SDMMC_BLOCK_GPIO_CONFIG_t SDMMC_BLOCK_0_DATA_1_PIN_CONFIG =
+{
+ .config =
+ {
+ .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
+ .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_MEDIUM_EDGE,
+ .output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
+ },
+ .hw_control = XMC_GPIO_HWCTRL_PERIPHERAL1,
+};
+
+/* SDMMC_BLOCK Data 1 pin */
+const SDMMC_BLOCK_PIN_CONFIG_t SDMMC_BLOCK_0_DATA_1 =
+{
+ .port = (XMC_GPIO_PORT_t *)PORT1_BASE,
+ .pin = (uint8_t)6,
+ .config = &SDMMC_BLOCK_0_DATA_1_PIN_CONFIG
+};
+
+
+/* SDMMC_BLOCK Data 2 pin config */
+const SDMMC_BLOCK_GPIO_CONFIG_t SDMMC_BLOCK_0_DATA_2_PIN_CONFIG =
+{
+ .config =
+ {
+ .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
+ .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_MEDIUM_EDGE,
+ .output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
+ },
+ .hw_control = XMC_GPIO_HWCTRL_PERIPHERAL1,
+};
+
+/* SDMMC_BLOCK Data 2 pin */
+const SDMMC_BLOCK_PIN_CONFIG_t SDMMC_BLOCK_0_DATA_2 =
+{
+ .port = (XMC_GPIO_PORT_t *)PORT1_BASE,
+ .pin = (uint8_t)7,
+ .config = &SDMMC_BLOCK_0_DATA_2_PIN_CONFIG
+};
+
+
+/* SDMMC_BLOCK Data 3 pin config */
+const SDMMC_BLOCK_GPIO_CONFIG_t SDMMC_BLOCK_0_DATA_3_PIN_CONFIG =
+{
+ .config =
+ {
+ .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
+ .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_MEDIUM_EDGE,
+ .output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
+ },
+ .hw_control = XMC_GPIO_HWCTRL_PERIPHERAL1,
+};
+
+/* SDMMC_BLOCK Data 3 pin */
+const SDMMC_BLOCK_PIN_CONFIG_t SDMMC_BLOCK_0_DATA_3 =
+{
+ .port = (XMC_GPIO_PORT_t *)PORT4_BASE,
+ .pin = (uint8_t)1,
+ .config = &SDMMC_BLOCK_0_DATA_3_PIN_CONFIG
+};
+
+
+/* SDMMC_BLOCK Command pin config */
+const SDMMC_BLOCK_GPIO_CONFIG_t SDMMC_BLOCK_0_COMMAND_PIN_CONFIG =
+{
+ .config =
+ {
+ .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
+ .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_MEDIUM_EDGE,
+ .output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
+ },
+ .hw_control = XMC_GPIO_HWCTRL_PERIPHERAL1,
+};
+
+/* SDMMC_BLOCK Command pin */
+const SDMMC_BLOCK_PIN_CONFIG_t SDMMC_BLOCK_0_COMMAND =
+{
+ .port = (XMC_GPIO_PORT_t *)PORT3_BASE,
+ .pin = (uint8_t)5,
+ .config = &SDMMC_BLOCK_0_COMMAND_PIN_CONFIG
+};
+
+
+/* SDMMC_BLOCK Clock pin config */
+const SDMMC_BLOCK_GPIO_CONFIG_t SDMMC_BLOCK_0_CLK_PIN_CONFIG =
+{
+ .config =
+ {
+ .mode = XMC_GPIO_MODE_OUTPUT_PUSH_PULL,
+ .output_strength = XMC_GPIO_OUTPUT_STRENGTH_STRONG_MEDIUM_EDGE,
+ .output_level = XMC_GPIO_OUTPUT_LEVEL_LOW,
+ },
+ .hw_control = XMC_GPIO_HWCTRL_PERIPHERAL1,
+};
+
+/* SDMMC_BLOCK Clock pin */
+const SDMMC_BLOCK_PIN_CONFIG_t SDMMC_BLOCK_0_CLK =
+{
+ .port = (XMC_GPIO_PORT_t *)PORT3_BASE,
+ .pin = (uint8_t)6,
+ .config = &SDMMC_BLOCK_0_CLK_PIN_CONFIG
+};
+
+
+/* SDMMC SD mode instance */
+SDMMC_BLOCK_SD_t SDMMC_BLOCK_0_SD =
+{
+ .sdmmc = XMC_SDMMC, /* SDMMC instance */
+ .int_priority = 63U, /* Node interrupt priority */
+ .int_sub_priority = 0U, /* Node interrupt sub-priority */
+ .mode_init_flag = false, /* Mode initialization false by default */
+};
+
+/* SDMMC_BLOCK APP instance */
+SDMMC_BLOCK_t SDMMC_BLOCK_0 =
+{
+ .interface_mode = SDMMC_BLOCK_CARD_INTERFACE_SD, /* SD interface */
+ .sdmmc_sd = &SDMMC_BLOCK_0_SD, /* SDMMC_SD instance */
+ .rtos_mode = SDMMC_BLOCK_RTOS_MODE_DISABLED, /* RTOS mose is not used */
+
+ #if SDMMC_BLOCK_RTOS_MODE_SELECT
+ .cmsis_rtos = NULL, /* RTOS mose is not used */
+ #endif /* SDMMC_BLOCK_RTOS_MODE_SELECT */
+
+ .init_pins = SDMMC_BLOCK_0_Config_Init, /* true: Initialized; false: Uninitialized */
+ .init_flag = false, /* true: Initialized; false: Uninitialized */
+ .card_state = ((uint8_t)SDMMC_BLOCK_CARD_STATE_NOT_INITIALIZED |
+ (uint8_t)SDMMC_BLOCK_CARD_STATE_NO_CARD) /* Card state */
+};
+
+/**********************************************************************************************************************
+ * FUNCTION DEFINITIONS
+ **********************************************************************************************************************/
+
+/* SDMMC SD interrupt handler */
+void SDMMC0_0_IRQHandler(void)
+{
+ normal_int_status = SDMMC_BLOCK_0.sdmmc_sd->sdmmc->INT_STATUS_NORM;
+ err_int_status = SDMMC_BLOCK_0.sdmmc_sd->sdmmc->INT_STATUS_ERR;
+
+ if (normal_int_status & SDMMC_INT_STATUS_NORM_ERR_INT_Msk)
+ {
+ SDMMC_BLOCK_SD_ErrorInterruptHandler(&SDMMC_BLOCK_0, err_int_status);
+ }
+
+ if (normal_int_status & SDMMC_BLOCK_NORMAL_INT_STATUS_BITS)
+ {
+ SDMMC_BLOCK_SD_NormalInterruptHandler(&SDMMC_BLOCK_0, normal_int_status);
+ }
+}
+
+/*
+ * Configuration initialization:
+ * For pins and other mode specific settings
+ */
+static void SDMMC_BLOCK_0_Config_Init(void)
+{
+ /* Enable delay on command and data lines */
+ XMC_SDMMC_EnableDelayCmdDatLines();
+
+ /* Set the delay value chosen in the APP user interface */
+ XMC_SDMMC_SetDelay(SDMMC_BLOCK_SD_NUM_DELAY_ELEMENTS);
+
+ XMC_GPIO_Init(SDMMC_BLOCK_0_COMMAND.port,
+ SDMMC_BLOCK_0_COMMAND.pin,
+ &SDMMC_BLOCK_0_COMMAND.config->config);
+ XMC_GPIO_SetHardwareControl(SDMMC_BLOCK_0_COMMAND.port,
+ SDMMC_BLOCK_0_COMMAND.pin,
+ SDMMC_BLOCK_0_COMMAND.config->hw_control);
+
+ XMC_GPIO_Init(SDMMC_BLOCK_0_CLK.port,
+ SDMMC_BLOCK_0_CLK.pin,
+ &SDMMC_BLOCK_0_CLK.config->config);
+ XMC_GPIO_SetHardwareControl(SDMMC_BLOCK_0_CLK.port,
+ SDMMC_BLOCK_0_CLK.pin,
+ SDMMC_BLOCK_0_CLK.config->hw_control);
+
+ XMC_GPIO_Init(SDMMC_BLOCK_0_DATA_0.port,
+ SDMMC_BLOCK_0_DATA_0.pin,
+ &SDMMC_BLOCK_0_DATA_0.config->config);
+ XMC_GPIO_SetHardwareControl(SDMMC_BLOCK_0_DATA_0.port,
+ SDMMC_BLOCK_0_DATA_0.pin,
+ SDMMC_BLOCK_0_DATA_0.config->hw_control);
+
+ XMC_GPIO_Init(SDMMC_BLOCK_0_DATA_1.port,
+ SDMMC_BLOCK_0_DATA_1.pin,
+ &SDMMC_BLOCK_0_DATA_1.config->config);
+ XMC_GPIO_SetHardwareControl(SDMMC_BLOCK_0_DATA_1.port,
+ SDMMC_BLOCK_0_DATA_1.pin,
+ SDMMC_BLOCK_0_DATA_1.config->hw_control);
+
+ XMC_GPIO_Init(SDMMC_BLOCK_0_DATA_2.port,
+ SDMMC_BLOCK_0_DATA_2.pin,
+ &SDMMC_BLOCK_0_DATA_2.config->config);
+ XMC_GPIO_SetHardwareControl(SDMMC_BLOCK_0_DATA_2.port,
+ SDMMC_BLOCK_0_DATA_2.pin,
+ SDMMC_BLOCK_0_DATA_2.config->hw_control);
+
+ XMC_GPIO_Init(SDMMC_BLOCK_0_DATA_3.port,
+ SDMMC_BLOCK_0_DATA_3.pin,
+ &SDMMC_BLOCK_0_DATA_3.config->config);
+ XMC_GPIO_SetHardwareControl(SDMMC_BLOCK_0_DATA_3.port,
+ SDMMC_BLOCK_0_DATA_3.pin,
+ SDMMC_BLOCK_0_DATA_3.config->hw_control);
+
+ XMC_SDMMC_SetCardDetectionSource(XMC_SDMMC, XMC_SDMMC_CD_SOURCE_SW);
+ XMC_SDMMC_SetCardDetectionStatus(XMC_SDMMC, XMC_SDMMC_CD_STATUS_INSERTED);
+}
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_conf.h b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_conf.h
new file mode 100644
index 00000000..9380ae74
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_conf.h
@@ -0,0 +1,82 @@
+/*********************************************************************************************************************
+* DAVE APP Name : SDMMC_BLOCK APP Version: 4.0.22
+*
+* NOTE:
+* This file is generated by DAVE. Any manual modification done to this file will be lost when the code is regenerated.
+*********************************************************************************************************************/
+
+/**
+ * @cond
+ ***********************************************************************************************************************
+ * Copyright (c) 2016, 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
+ * --------------
+ *
+ * 2016-01-20:
+ * - Initial version
+ *
+ * 2016-02-05:
+ * - RTOS support added
+ *
+ * 2016-04-05:
+ * - Bug fixes done for PR.
+ *
+ * @endcond
+ */
+
+#ifndef SDMMC_BLOCK_CONF_H
+#define SDMMC_BLOCK_CONF_H
+
+
+
+/***********************************************************************************************************************
+ * HEADER FILES
+ **********************************************************************************************************************/
+
+#include "xmc_scu.h"
+#include "xmc_sdmmc.h"
+
+
+/**********************************************************************************************************************
+ * MACROS
+ **********************************************************************************************************************/
+
+#define SDMMC_BLOCK_MAJOR_VERSION (4U) /**< Major version */
+#define SDMMC_BLOCK_MINOR_VERSION (0U) /**< Minor version */
+#define SDMMC_BLOCK_PATCH_VERSION (22U) /**< Patch version */
+
+#define SDMMC_BLOCK_SD
+#define SDMMC_BLOCK_SD_NUM_DELAY_ELEMENTS (8U)
+#define SDMMC_BLOCK_SD_SUPPORT_4_BUS_WIDTH (1U)
+#define SDMMC_BLOCK_RTOS_MODE_SELECT (0U)
+
+/* Added configurable to support polling mode operation instead of interrupt driven. */
+#define SDMMC_BLOCK_POLLING_MODE (1U)
+
+#endif /* ifndef SDMMC_BLOCK_CONF_H */
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_extern.h b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_extern.h
new file mode 100644
index 00000000..5fb8d1c6
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_extern.h
@@ -0,0 +1,79 @@
+/*********************************************************************************************************************
+* DAVE APP Name : SDMMC_BLOCK APP Version: 4.0.22
+*
+* NOTE:
+* This file is generated by DAVE. Any manual modification done to this file will be lost when the code is regenerated.
+*********************************************************************************************************************/
+
+/**
+ * @cond
+ ***********************************************************************************************************************
+ * Copyright (c) 2016, 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
+ * --------------
+ *
+ * 2016-01-20:
+ * - Initial version
+ *
+ * 2016-02-05:
+ * - RTOS support added
+ *
+ * 2016-04-05:
+ * - Test hooks is added to emulates the hardware failures.
+ * - Bug fixes done for PR.
+ *
+ * 2016-06-07:
+ * - Fixed code generation error for project folder paths with spaces in between.
+ * @endcond
+ */
+
+#ifndef SDMMC_BLOCK_EXTERN_H
+#define SDMMC_BLOCK_EXTERN_H
+
+/***********************************************************************************************************************
+ * HEADER FILES
+ **********************************************************************************************************************/
+
+/**********************************************************************************************************************
+ * MACROS
+ **********************************************************************************************************************/
+
+/***********************************************************************************************************************
+ * EXTERN DECLARATIONS
+ ***********************************************************************************************************************/
+
+extern SDMMC_BLOCK_t SDMMC_BLOCK_0;
+
+#ifdef SDMMC_BLOCK_TEST_HOOK_ENABLE
+extern uint32_t sdmmc_block_test_hook_expected_command;
+#endif
+
+
+
+#endif /* ifndef SDMMC_BLOCK_EXTERN_H */
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_private_sd.c b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_private_sd.c
new file mode 100644
index 00000000..af860567
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_private_sd.c
@@ -0,0 +1,2911 @@
+/**
+ * @file sdmmc_block_private_sd.c
+ * @date 2017-06-08
+ *
+ * NOTE:
+ * This file is generated by DAVE. Any manual modification done to this file will be lost when the code is regenerated.
+ *
+ * @cond
+ ***********************************************************************************************************************
+ * SDMMC_BLOCK v4.0.22 - Configures the SD host to interface with the SDMMC card.
+ *
+ * Copyright (c) 2016-2017, 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
+ * --------------
+ *
+ * 2016-01-20:
+ * - Initial version.
+ *
+ * 2016-02-08:
+ * - Help Doc updated.
+ * - Bug fixes done.
+ *
+ * 2016-04-05
+ * - Bug fixes for public release, April, 2016
+ * - MISRA fixes
+ * - Add timeout for erase()
+ * - Check write protection in write/erase conditions
+ * - Remove mode_init_flag check for functions invoked in IOCTL
+ *
+ * 2016-07-20:
+ * - lReadResponse(): Fixes in handling XMC_SDMMC_RESPONSE_TYPE_R2
+ *
+ * 2016-08-24:
+ * - Introduce timeout mechanism in SDMMC_BLOCK_SD_lCheckDataCommandLines()
+ *
+ * 2017-06-08
+ * - Fix SDMMC_BLOCK_SD_GetSectorCount() for Standard Capacity cards
+ *
+ * @endcond
+ *
+ */
+
+#include "sdmmc_block_private_sd.h"
+#include "boot.h"
+
+
+#ifdef SDMMC_BLOCK_SD
+
+
+/***********************************************************************************************************************
+ * EXTERNAL ROUTINES
+ **********************************************************************************************************************/
+extern void SDMMC0_0_IRQHandler(void);
+
+
+/***********************************************************************************************************************
+ * LOCAL ROUTINES
+ **********************************************************************************************************************/
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lReset(SDMMC_BLOCK_t *const obj, uint32_t reset);
+
+static void
+SDMMC_BLOCK_SD_lCardCleanUp(SDMMC_BLOCK_t *const obj);
+
+static uint32_t
+SDMMC_BLOCK_SD_lCheckDataCommandLines(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd);
+
+static void
+SDMMC_BLOCK_SD_lCheckArgumentError(const uint32_t *card_status, uint8_t *err);
+
+static void
+SDMMC_BLOCK_SD_lCheckEraseError(const uint32_t *card_status, uint8_t *err);
+
+static void
+SDMMC_BLOCK_SD_lCheckCardError(const uint32_t *card_status, uint8_t *err);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCheckErrorInResponse(const uint32_t *card_status);
+
+static void
+SDMMC_BLOCK_SD_lGetCardLockState(SDMMC_BLOCK_t *const obj, uint32_t card_status, uint16_t cmd_index);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lTransferDelay(SDMMC_BLOCK_t *const obj, uint32_t delay);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lReadResponse(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ XMC_SDMMC_RESPONSE_TYPE_t resp_type,
+ void *resp);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lSendCommand(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t arg,
+ XMC_SDMMC_RESPONSE_TYPE_t resp_type,
+ void *resp);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lSetVoltageWindow(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lQueryOperatingCondition(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lQueryVoltage(SDMMC_BLOCK_t *const obj, uint32_t arg);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lAfterCardInitialize(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lInitializeCard(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lGetWriteProtect(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lConfigureSingleBlockTransfer(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t arg,
+ uint16_t block_size);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lMultiBlockTransfer(SDMMC_BLOCK_t *const obj,
+ uint32_t *addr,
+ uint32_t num_blocks,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t *buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_t transfer_mode);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCheckLockStatus(SDMMC_BLOCK_t *const obj, SDMMC_BLOCK_CARD_LOCK_STATUS_t mode);
+
+#if SDMMC_BLOCK_SD_SUPPORT_4_BUS_WIDTH
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lSwitchBusWidth(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lSwitchSpeed(SDMMC_BLOCK_t *const obj);
+#endif
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCommandDelay(SDMMC_BLOCK_t *const obj, uint32_t delay);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lSwitchToTransferState(SDMMC_BLOCK_t *const obj);
+
+static void
+SDMMC_BLOCK_SD_lAcmdErrorRecovery(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCheckSectorBound(SDMMC_BLOCK_t *const obj,
+ uint32_t sector_num,
+ uint32_t sector_count);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lLocalErase(SDMMC_BLOCK_t *const obj,
+ uint32_t start_addr,
+ uint32_t end_addr,
+ uint32_t timeout);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lHostControllerInit(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lHostControllerDeInit(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCardReadMultipleBlocks(SDMMC_BLOCK_t *const obj,
+ uint32_t *read_buf,
+ uint32_t read_addr,
+ uint32_t num_blocks);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCardReadSingleBlock(SDMMC_BLOCK_t *const obj,
+ uint32_t *read_buf,
+ uint32_t read_addr);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCardWriteMultipleBlocks(SDMMC_BLOCK_t *const obj,
+ const uint32_t *write_buf,
+ uint32_t write_addr,
+ uint32_t num_blocks);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lCardWriteSingleBlock(SDMMC_BLOCK_t *const obj,
+ const uint32_t *write_buf,
+ uint32_t write_addr);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lDelay(SDMMC_BLOCK_t *const obj, uint32_t delay);
+
+static void
+SDMMC_BLOCK_SD_lWriteCardType(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lReadRca(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lReadCardRegisters(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lDataTransfer(SDMMC_BLOCK_t *const obj,
+ uint32_t *buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_t transfer_mode,
+ uint32_t quad_bytes);
+
+
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lErrorInterruptRecovery(SDMMC_BLOCK_t *const obj);
+
+static SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_lSingleBlockTransfer(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t arg,
+ uint16_t block_size,
+ uint32_t *buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_t transfer_mode);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_Start(SDMMC_BLOCK_t *const obj);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_NormalInterruptHandler(SDMMC_BLOCK_t *const obj, uint16_t int_status);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_ErrorInterruptHandler(SDMMC_BLOCK_t *const obj, uint16_t int_status);
+
+/***********************************************************************************************************************
+ * MACROS
+ **********************************************************************************************************************/
+
+/***********************************************************************************************************************
+ * DATA STRUCTURES
+ **********************************************************************************************************************/
+
+/* Command Structure defining SD, MMC and Application specific commands */
+const XMC_SDMMC_COMMAND_t sdmmc_block_command[40] =
+{
+ /* Start: SD card commands */
+ {{0U, 0U, 0U, 0U, 0U, SDMMC_BLOCK_GO_IDLE_STATE}}, /* 0 */
+ {{1U, 1U, 0U, 0U, 0U, SDMMC_BLOCK_ALL_SEND_CID}}, /* 1 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SEND_RELATIVE_ADDR}}, /* 2 */
+ {{0U, 0U, 0U, 0U, 0U, SDMMC_BLOCK_SET_DSR}}, /* 3 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_SWITCH_FUNC}}, /* 4 */
+ {{3U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SELECT_DESELECT_CARD}}, /* 5 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SD_SEND_IF_COND}}, /* 6 */
+ {{1U, 1U, 0U, 0U, 0U, SDMMC_BLOCK_SEND_CSD}}, /* 7 */
+ {{1U, 1U, 0U, 0U, 0U, SDMMC_BLOCK_SEND_CID}}, /* 8 */
+ {{3U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_STOP_TRANSMISSION}}, /* 9 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SEND_STATUS}}, /* 10 */
+ {{0U, 0U, 0U, 0U, 0U, SDMMC_BLOCK_GO_INACTIVE_STATE}}, /* 11 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SET_BLOCKLEN}}, /* 12 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_READ_SINGLE_BLOCK}}, /* 13 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_READ_MULTIPLE_BLOCK}}, /* 14 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_WRITE_BLOCK}}, /* 15 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_WRITE_MULTIPLE_BLOCK}}, /* 16 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_PROGRAM_CSD}}, /* 17 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SET_WRITE_PROT}}, /* 18 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_CLR_WRITE_PROT}}, /* 19 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_SEND_WRITE_PROT}}, /* 20 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_ERASE_WR_BLK_START}}, /* 21 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_ERASE_WR_BLK_END}}, /* 22 */
+ {{3U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_ERASE}}, /* 23 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_LOCK_UNLOCK}}, /* 24 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_APP_CMD}}, /* 25 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_GEN_CMD}}, /* 26 */
+ /* Start: application specific commands */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SET_BUS_WIDTH}}, /* 27 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_SD_STATUS}}, /* 28 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_SEND_NUM_WR_BLOCKS}}, /* 29 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SET_WR_BLK_ERASE_COUNT}}, /* 30 */
+ {{2U, 0U, 0U, 0U, 0U, SDMMC_BLOCK_SD_SEND_OP_COND}}, /* 31 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SET_CLR_CARD_DETECT}}, /* 32 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_SEND_SCR}}, /* 33 */
+ /* Start of SDMMC_MMC Card specific commands */
+ {{2U, 0U, 1U, 0U, 0U, SDMMC_BLOCK_MMC_SEND_OP_COND}}, /* 34 */
+ {{3U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_MMC_SLEEP_AWAKE}}, /* 35 */
+ {{3U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_SWITCH_FUNC}}, /* 36 */
+ {{2U, 1U, 1U, 1U, 0U, SDMMC_BLOCK_MMC_SEND_EXT_CSD}}, /* 37 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_ERASE_GROUP_START}}, /* 38 */
+ {{2U, 1U, 1U, 0U, 0U, SDMMC_BLOCK_ERASE_GROUP_END}} /* 39 */
+};
+
+/*
+ * SD card command index hash table
+ * It contains the index of the command structure
+ *
+ * Array index 0-57 is for general SD commands and array
+ * index 58-64 is for application specific commands.
+ */
+const uint8_t sdmmc_block_sd_hash_table[65] =
+{
+ (uint8_t)0x00, (uint8_t)0xFF, (uint8_t)0x01, (uint8_t)0x02,
+ (uint8_t)0x03, (uint8_t)0xFF, (uint8_t)0x04, (uint8_t)0x05,
+ (uint8_t)0x06, (uint8_t)0x07, (uint8_t)0x08, (uint8_t)0xFF,
+ (uint8_t)0x09, (uint8_t)0x0A, (uint8_t)0xFF, (uint8_t)0x0B,
+ (uint8_t)0x0C, (uint8_t)0x0D, (uint8_t)0x0E, (uint8_t)0xFF,
+ (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF,
+ (uint8_t)0x0F, (uint8_t)0x10, (uint8_t)0xFF, (uint8_t)0x11,
+ (uint8_t)0x12, (uint8_t)0x13, (uint8_t)0x14, (uint8_t)0xFF,
+ (uint8_t)0x15, (uint8_t)0x16, (uint8_t)0xFF, (uint8_t)0xFF,
+ (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0x17, (uint8_t)0xFF,
+ (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0x18, (uint8_t)0xFF,
+ (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF,
+ (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF,
+ (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0xFF, (uint8_t)0x19,
+ (uint8_t)0x1A, (uint8_t)0xFF, (uint8_t)0x1B, (uint8_t)0x1C,
+ (uint8_t)0x1D, (uint8_t)0x1E, (uint8_t)0x1F, (uint8_t)0x20,
+ (uint8_t)0x21
+};
+
+/***********************************************************************************************************************
+ * EXTERNAL REFERENCES
+ **********************************************************************************************************************/
+
+/***********************************************************************************************************************
+ * API DEFINITIONS
+ **********************************************************************************************************************/
+
+/* Resets the Host Controller's register */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lReset(SDMMC_BLOCK_t *const obj, uint32_t reset)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ uint32_t timeoutTime;
+
+ XMC_SDMMC_SetSWReset(obj->sdmmc_sd->sdmmc, reset);
+
+ /* Set timeout time. */
+ timeoutTime = TimerGet() + (SDMMC_BLOCK_RESET_DELAY / 1000u) + 1u;
+
+ do
+ {
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ }
+ while (((uint32_t)XMC_SDMMC_GetSWResetStatus(obj->sdmmc_sd->sdmmc)) & (reset));
+
+ return status;
+}
+
+/* Clears card specific structures and stops the SD clock */
+static void SDMMC_BLOCK_SD_lCardCleanUp(SDMMC_BLOCK_t *const obj)
+{
+ memset((void *)&obj->sdmmc_sd->card_info, 0, sizeof(SDMMC_BLOCK_SD_CARD_INFORMATION_t));
+ obj->card_type = (uint8_t)0;
+ obj->sdmmc_sd->f8 = (uint8_t)0;
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->err_recovery_stat = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->transfer_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->card_state = (uint8_t)0U;
+
+ /* SD clock disable */
+ XMC_SDMMC_SDClockDisable(obj->sdmmc_sd->sdmmc);
+}
+
+/* Check if CMD and DAT lines are free before issuing a command */
+static uint32_t SDMMC_BLOCK_SD_lCheckDataCommandLines(SDMMC_BLOCK_t *const obj, const XMC_SDMMC_COMMAND_t *cmd)
+{
+ uint32_t status = (uint32_t)SDMMC_BLOCK_MODE_STATUS_CMD_LINE_BUSY;
+ uint32_t timeoutTime;
+
+ timeoutTime = TimerGet() + (SDMMC_BLOCK_DELAY_IN_COMMAND / 1000u) + 1u;
+
+ do
+ {
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while ((XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc) ||
+ (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc))));
+
+ /* Check if command line is not busy; then proceed */
+ if (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc) == false)
+ {
+ status = (uint32_t)SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ if (((uint32_t)cmd->dat_present_sel == (uint32_t)1U) ||
+ ((uint32_t)cmd->cmd_index == (uint32_t)SDMMC_BLOCK_SEND_STATUS) ||
+ ((uint32_t)cmd->response_type_sel == (uint32_t)3U))
+ {
+ if (XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc) != false)
+ {
+ status = (uint32_t)SDMMC_BLOCK_MODE_STATUS_DATA_LINE_BUSY;
+ }
+ else
+ {
+ if (((uint32_t)cmd->dat_present_sel == (uint32_t)1U) || ((uint32_t)cmd->response_type_sel == (uint32_t)3U))
+ {
+ /* Update data line state to active */
+ obj->card_state |= (uint8_t)SDMMC_BLOCK_CARD_STATE_DATA_ACTIVE;
+ }
+ }
+ }
+
+ if (status == (uint32_t)SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Update command line state to active */
+ obj->card_state |= (uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ }
+ }
+
+ return status;
+}
+
+/* Check response error types in command's arguments category */
+static void SDMMC_BLOCK_SD_lCheckArgumentError(const uint32_t *card_status, uint8_t *err)
+{
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_OUT_OF_RANGE_BITMASK) != (uint32_t)0U)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckArgumentError: Out of range error");
+ }
+
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_ADDRESS_ERROR_BITMASK) != (uint32_t)0U)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckArgumentError: Address error");
+ }
+
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_BLOCK_LEN_ERROR_BITMASK) != (uint32_t)0U)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckArgumentError: Block length error");
+ }
+
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_WP_VIOLATION_BITMASK) != (uint32_t)0U)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckArgumentError: Write protection violation error");
+ }
+}
+
+/* Checks response error types in erase category */
+static void SDMMC_BLOCK_SD_lCheckEraseError(const uint32_t *card_status, uint8_t *err)
+{
+ /* An error in the sequence of erase commands occurred.*/
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_ERASE_SEQ_ERROR_BITMASK) != (uint32_t)0)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckEraseError: Sequential erase error");
+ }
+
+ /* An invalid selection of write-blocks for erase occurred */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_ERASE_PARAM_BITMASK) != (uint32_t)0)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckEraseError: Parameter erase error");
+ }
+
+ /*
+ * Set when only partial address space was erased due to existing
+ * write protected blocks OR the temporary/permanent write protected card
+ * was erased
+ */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_WP_ERASE_SKIP_BITMASK) != (uint32_t)0)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckEraseError: Write protection erase skip error");
+ }
+}
+
+/* Check response error types in card's internal error category */
+static void SDMMC_BLOCK_SD_lCheckCardError(const uint32_t *card_status, uint8_t *err)
+{
+ /* Card internal ECC was applied but failed to correct the data */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_CARD_ECC_FAILED_BITMASK) != (uint32_t)0U)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckCardError: Card ECC error");
+ }
+
+ /* Internal card controller error */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_CC_ERROR_BITMASK) != (uint32_t)0)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckCardError: Internal card controller error");
+ }
+
+ /* A general or an unknown error occurred during the operation */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_ERROR_BITMASK) != (uint32_t)0)
+ {
+ *err = (uint8_t)1U;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckCardError: Unknown error");
+ }
+}
+
+/* Check for any error in the command's (received) response */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCheckErrorInResponse(const uint32_t *card_status)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ uint8_t err = (uint8_t)0; /* No error */
+
+ /* Check errors in arguments */
+ SDMMC_BLOCK_SD_lCheckArgumentError(card_status, &err);
+
+ /* Check errors specific to erase operation */
+ SDMMC_BLOCK_SD_lCheckEraseError(card_status, &err);
+
+ /* Check errors specific to the card */
+ SDMMC_BLOCK_SD_lCheckCardError(card_status, &err);
+
+ /*
+ * Set when a sequence or password error has been detected in
+ * lock/unlock card command
+ */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_LOCK_UNLOCK_FAILED_BITMASK) != (uint32_t)0)
+ {
+ err = (uint8_t)1;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckErrorInResponse: Lock/unlock error");
+ }
+
+ /*
+ * Can be one of the following errors:
+ * 1) The read only section of the CSD does not match the card content
+ * 2) An attempt to reverse the copy or permanent WP bits was made
+ */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_CSD_OVERWRITE_BITMASK) != (uint32_t)0)
+ {
+ err = (uint8_t)1;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckErrorInResponse: CSD overwrite error");
+ }
+
+ /* Error in the sequence of the authentication process */
+ if ((*card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_ASK_SEQ_ERROR_BITMASK) != (uint32_t)0)
+ {
+ err = (uint8_t)1;
+ XMC_DEBUG("SDMMC_BLOCK_SD_CheckErrorInResponse: Authentication sequence error");
+ }
+
+ /* Some SD cards treat CMD55 as an illegal command */
+ if (err == 1U)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ }
+
+ return status;
+}
+
+/* Check for lock status of SD card */
+static void SDMMC_BLOCK_SD_lGetCardLockState(SDMMC_BLOCK_t *const obj, uint32_t card_status, uint16_t cmd_index)
+{
+ if (((card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_CARD_IS_LOCKED_BITMASK) != (uint32_t)0) &&
+ (cmd_index != (uint32_t)SDMMC_BLOCK_SEND_RELATIVE_ADDR))
+ {
+ obj->card_state |= (uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED;
+ }
+ else
+ {
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED;
+ }
+}
+
+/* Provide transfer delay */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lTransferDelay(SDMMC_BLOCK_t *const obj, uint32_t delay)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ uint32_t timeoutTime;
+ obj->sdmmc_sd->tmr_expire = (bool)1;
+
+ timeoutTime = TimerGet() + (delay / 1000u) + 1u;
+
+ do
+ {
+#if (SDMMC_BLOCK_POLLING_MODE > 0U)
+ /* Poll for interrupt events. */
+ SDMMC0_0_IRQHandler();
+#endif
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while (obj->sdmmc_sd->isr_context.transfer_flag == (uint8_t)0U);
+
+ obj->sdmmc_sd->isr_context.transfer_flag = (uint8_t)0U;
+
+ if (obj->sdmmc_sd->transfer_int_err != SDMMC_BLOCK_MODE_STATUS_TRANSFER_COMPLETE)
+ {
+ status = (SDMMC_BLOCK_MODE_STATUS_t)obj->sdmmc_sd->data_int_err;
+ }
+
+ return status;
+}
+
+/* Read response received for the command issued */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lReadResponse(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ XMC_SDMMC_RESPONSE_TYPE_t resp_type,
+ void *resp)
+{
+ uint32_t *ptr;
+ uint32_t card_status = 0U;
+ uint32_t err_status = 0U;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ /* To mask high byte from response register */
+ uint32_t resp_high_mask = 0;
+
+ /* Check for no-response type commands */
+ if (((uint16_t)cmd->cmd_index == (uint16_t)SDMMC_BLOCK_GO_IDLE_STATE) ||
+ ((uint16_t)cmd->cmd_index == (uint16_t)SDMMC_BLOCK_GO_INACTIVE_STATE))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ else
+ {
+ ptr = (uint32_t *)resp;
+ card_status = (uint32_t)obj->sdmmc_sd->sdmmc->RESPONSE[0];
+
+ /* Check Lock Status */
+ SDMMC_BLOCK_SD_lGetCardLockState(obj, card_status, (uint16_t)cmd->cmd_index);
+
+ /* Check response type */
+ switch (resp_type)
+ {
+ /* Response R1 */
+ case XMC_SDMMC_RESPONSE_TYPE_R1:
+ /* check the error bits in the response */
+ *ptr = card_status;
+ status = SDMMC_BLOCK_SD_lCheckErrorInResponse(&card_status);
+ break;
+
+ /* Response R1b */
+ case XMC_SDMMC_RESPONSE_TYPE_R1b:
+ *ptr = card_status;
+
+ status = SDMMC_BLOCK_SD_lCheckErrorInResponse(&card_status);
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Wait for transfer complete interrupt */
+ status = SDMMC_BLOCK_SD_lTransferDelay(obj, (uint32_t)SDMMC_BLOCK_DELAY_IN_TRANSFER);
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ XMC_DEBUG("SDMMC_BLOCK_ReadResponse: For R1b, SDMMC_BLOCK_TransferDelay failed");
+ }
+ }
+
+ break;
+
+ /* Response R2: response register R0-R7 */
+ case XMC_SDMMC_RESPONSE_TYPE_R2:
+ *ptr = (uint32_t)((uint32_t)XMC_SDMMC->RESPONSE[0] << 8U); ptr++;
+ resp_high_mask = (uint32_t)(((uint32_t)XMC_SDMMC->RESPONSE[0] & 0xFF000000) >> 24U);
+
+ *ptr = (uint32_t)(((uint32_t)XMC_SDMMC->RESPONSE[1] << 8U) | resp_high_mask); ptr++;
+ resp_high_mask = (uint32_t)(((uint32_t)XMC_SDMMC->RESPONSE[1] & 0xFF000000) >> 24U);
+
+ *ptr = (uint32_t)(((uint32_t)XMC_SDMMC->RESPONSE[2] << 8U) | resp_high_mask);
+ resp_high_mask = (uint32_t)(((uint32_t)XMC_SDMMC->RESPONSE[2] & 0xFF000000) >> 24U);
+
+ *ptr = (uint32_t)(((uint32_t)XMC_SDMMC->RESPONSE[3] << 8U) | resp_high_mask);
+ break;
+
+ /* Responses R3 and R7 */
+ case XMC_SDMMC_RESPONSE_TYPE_R3:
+ *ptr = card_status;
+ break;
+
+ case XMC_SDMMC_RESPONSE_TYPE_R7:
+ *ptr = card_status;
+ break;
+
+ /* Response R6 */
+ case XMC_SDMMC_RESPONSE_TYPE_R6:
+ err_status = card_status & (uint32_t)SDMMC_RESPONSE0_RESPONSE0_Msk;
+ status = SDMMC_BLOCK_SD_lCheckErrorInResponse(&err_status);
+
+ /* Read 16-bit RCA received in response R1 register */
+ *ptr = ((uint32_t)(card_status & (uint32_t)SDMMC_RESPONSE0_RESPONSE1_Msk) >> SDMMC_BLOCK_HC_RESPONSE1_BITPOS);
+ break;
+
+ /* No response */
+ case XMC_SDMMC_RESPONSE_TYPE_NO_RESPONSE:
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ break;
+
+ default:
+ status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ break;
+ }
+ }
+
+ return status;
+}
+
+/* Send command */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lSendCommand(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t arg,
+ XMC_SDMMC_RESPONSE_TYPE_t resp_type,
+ void *resp)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t timeoutTime;
+
+ obj->sdmmc_sd->issue_abort = (uint8_t)0U;
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Data or command line free? */
+ status = (SDMMC_BLOCK_MODE_STATUS_t)SDMMC_BLOCK_SD_lCheckDataCommandLines(obj, cmd);
+ if (!((status == SDMMC_BLOCK_MODE_STATUS_DATA_LINE_BUSY) ||
+ (status == SDMMC_BLOCK_MODE_STATUS_CMD_LINE_BUSY)))
+ {
+ /* Send command */
+ (void)XMC_SDMMC_SendCommand(obj->sdmmc_sd->sdmmc, cmd, arg);
+
+ /* Block until any of the bit in the interrupt status register gets set */
+ timeoutTime = TimerGet() + (SDMMC_BLOCK_DELAY_IN_COMMAND / 1000u) + 1u;
+
+ do
+ {
+#if (SDMMC_BLOCK_POLLING_MODE > 0U)
+ /* Poll for interrupt events. */
+ SDMMC0_0_IRQHandler();
+#endif
+
+ if (TimerGet() > timeoutTime)
+ {
+ XMC_DEBUG("SDMMC_BLOCK_SendCommand: Timeout occured");
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while ((uint8_t)obj->sdmmc_sd->isr_context.cmd_flag == (uint8_t)0U);
+
+ obj->sdmmc_sd->isr_context.cmd_flag = (uint8_t)0;
+
+ /* Check for possible errors */
+ if ((SDMMC_BLOCK_MODE_STATUS_t)obj->sdmmc_sd->cmd_int_err == SDMMC_BLOCK_MODE_STATUS_COMMAND_COMPLETE)
+ {
+ /* Read response received */
+ status = SDMMC_BLOCK_SD_lReadResponse(obj, cmd, resp_type, resp);
+ }
+ /* For cmd8, check for cmd timeout interrupt */
+ else if (((SDMMC_BLOCK_MODE_STATUS_t)obj->sdmmc_sd->cmd_int_err == SDMMC_BLOCK_MODE_STATUS_COMMAND_TIMEOUT_ERROR) &&
+ ((uint16_t)cmd->cmd_index == (uint16_t)SDMMC_BLOCK_SD_SEND_IF_COND))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_COMMAND_TIMEOUT_ERROR;
+ }
+ else
+ {
+ if ((uint16_t)cmd->dat_present_sel == (uint16_t)1)
+ {
+ obj->sdmmc_sd->issue_abort = (uint8_t)1;
+ }
+
+ /* Error Recovery for the failed command */
+ status = SDMMC_BLOCK_SD_lErrorInterruptRecovery(obj);
+ }
+ }
+
+ return status;
+}
+
+/* Set voltage window in the OCR register */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lSetVoltageWindow(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t card_status = 0U;
+ uint32_t loop_count = 0U;
+ uint32_t arg = 0U;
+
+ if (obj->sdmmc_sd->f8 == (uint8_t)0U)
+ {
+ arg = SDMMC_BLOCK_SD_ACMD41_F80_ARG; /* Set HCS=0 for standard cards */
+ }
+ else
+ {
+ arg = SDMMC_BLOCK_SD_ACMD41_F81_ARG; /* Set HCS=1 for high capacity cards */
+ }
+
+ do
+ {
+ /* Send CMD55 for application specific commands (default RCA: 0) */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(55)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Send ACMD41 to set card's voltage window */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(62)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R3,
+ &(obj->sdmmc_sd->card_info.ocr));
+
+ if ((status != SDMMC_BLOCK_MODE_STATUS_SUCCESS) &&
+ (status != SDMMC_BLOCK_MODE_STATUS_ILLEGAL_COMMAND_ERROR))
+ {
+ break;
+ }
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+
+ /* Card takes some time to set power status bit. Card must respond in a second */
+ (void)SDMMC_BLOCK_SD_lDelay(obj, (uint32_t)SDMMC_BLOCK_CARD_POWER_DELAY);
+ }
+ else
+ {
+ loop_count = 100U;
+ }
+ } while (((loop_count++) < (uint32_t)50U) &&
+ (!(((uint32_t)obj->sdmmc_sd->card_info.ocr &
+ (uint32_t)SDMMC_BLOCK_OCR_POWER_STATUS_BITMASK)!= (uint32_t)0UL)));
+
+ return status;
+}
+
+/* Query voltage operating condition of the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lQueryOperatingCondition(SDMMC_BLOCK_t *const obj)
+{
+ uint32_t resp_data = 0U;
+ SDMMC_BLOCK_MODE_STATUS_t status;
+
+ /* Query voltage operating condition (cmd8) */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(8)),
+ SDMMC_BLOCK_SD_CMD8_ARG,
+ XMC_SDMMC_RESPONSE_TYPE_R7,
+ &resp_data);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check if pattern matches in both the argument and response */
+ if (((resp_data >> SDMMC_BLOCK_SD_CMD8_CHECK_PATTERN_BITPOS) & SDMMC_BLOCK_SD_CMD8_CHECK_PATTERN_BITMASK) !=
+ (SDMMC_BLOCK_SD_CMD8_CHECK_PATTERN_VALUE))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_BAD_RESPONSE;
+ }
+ /* Check if input voltage accepted by the card in the response */
+ else if (((uint8_t)(resp_data >> SDMMC_BLOCK_SD_CMD8_VHS_BITPOS) & SDMMC_BLOCK_SD_CMD8_VHS_BITMASK) !=
+ (SDMMC_BLOCK_SD_VHS_PATTERN_2_7_3_6_VALUE))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_BAD_RESPONSE;
+ }
+ else
+ {
+ /* Set Flag f8 */
+ obj->sdmmc_sd->f8 = (uint8_t)1U;
+ }
+ }
+ /* Response received; High capacity cards */
+ else
+ {
+ /* No response is received for Standard Capacity SD cards or MMC card. */
+ if (obj->sdmmc_sd->cmd_int_err == SDMMC_BLOCK_MODE_STATUS_COMMAND_TIMEOUT_ERROR)
+ {
+ obj->sdmmc_sd->f8 = (uint8_t)0U;
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ }
+
+ return status;
+}
+
+/* Query voltage supported from the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lQueryVoltage(SDMMC_BLOCK_t *const obj, uint32_t arg)
+{
+ uint32_t card_status = 0U;
+ SDMMC_BLOCK_MODE_STATUS_t status;
+
+ /* Send CMD55 for application specific commands with 0 as the default RCA */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(55)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (((obj->sdmmc_sd->f8 == (uint8_t)0U) && (status == SDMMC_BLOCK_MODE_STATUS_ILLEGAL_COMMAND_ERROR)) ||
+ (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS))
+ {
+ /* Send ACMD41 to query the card's voltage window */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(62)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R3,
+ &(obj->sdmmc_sd->card_info.ocr));
+
+ if ((status == SDMMC_BLOCK_MODE_STATUS_ILLEGAL_COMMAND_ERROR) ||
+ (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS))
+ {
+ /* Send ACMD41 with voltage window argument set */
+ status = SDMMC_BLOCK_SD_lSetVoltageWindow(obj);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* SD Card Type */
+ SDMMC_BLOCK_SD_lWriteCardType(obj);
+ }
+ }
+ }
+
+ return status;
+}
+
+/* Read card registers after the card initialization */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lAfterCardInitialize(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint8_t card_lock = (obj->card_state & (uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED);
+ uint32_t card_status;
+
+ /* Read CSD & SCR register & card write protection flags */
+ status = SDMMC_BLOCK_SD_lReadCardRegisters(obj);
+
+ /* Explicitly set block size as 512 */
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(16)),
+ 512U,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+ }
+
+ if ((status == SDMMC_BLOCK_MODE_STATUS_SUCCESS) && (card_lock == (uint8_t)0U))
+ {
+#if SDMMC_BLOCK_SD_SUPPORT_4_BUS_WIDTH
+ /* Switch to 4-bit bus width if supported */
+ status = SDMMC_BLOCK_SD_lSwitchBusWidth(obj);
+
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Switch to default (1-bit) bus width */
+ XMC_SDMMC_SetDataTransferWidth(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_LINES_1);
+ }
+
+ /* Switch to high speed mode */
+ status = SDMMC_BLOCK_SD_lSwitchSpeed(obj);
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Switch host controller to normal (default) speed mode */
+ XMC_SDMMC_DisableHighSpeed(obj->sdmmc_sd->sdmmc);
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+#endif
+ }
+
+ return status;
+}
+
+/* Initialize the SD card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lInitializeCard(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t lock_status;
+ uint8_t count = (uint8_t)0U;
+
+ /* Repeat the below steps 2 times if bad response is received */
+ do
+ {
+ /* Reset the card (CMD0) */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(0)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_NO_RESPONSE,
+ NULL);
+
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ break;
+ }
+
+ /* Query card's operation condition */
+ status = SDMMC_BLOCK_SD_lQueryOperatingCondition(obj);
+
+ count++;
+ } while ((count < (uint8_t)SDMMC_BLOCK_NUM_CARD_RESET_RETRIES) &&
+ (status == SDMMC_BLOCK_MODE_STATUS_BAD_RESPONSE));
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Query and set voltage window */
+ status = SDMMC_BLOCK_SD_lQueryVoltage(obj, (uint32_t)obj->sdmmc_sd->card_info.rca);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Read CID */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(2)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_R2,
+ (void *)obj->sdmmc_sd->card_info.cid);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Read RCA */
+ status = SDMMC_BLOCK_SD_lReadRca(obj);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check card lock/unlock status */
+ status = SDMMC_BLOCK_SD_GetLockStatus(obj, &lock_status);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ if (lock_status == SDMMC_BLOCK_CARD_LOCK_STATUS_LOCKED)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_INITIALIZED_BUT_LOCKED;
+ }
+
+ /* Update card initialization status */
+ obj->card_state &= (uint8_t)~((uint8_t)SDMMC_BLOCK_CARD_STATE_NOT_INITIALIZED |
+ (uint8_t)SDMMC_BLOCK_CARD_STATE_NO_CARD);
+ }
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+
+/* Get card type */
+static void SDMMC_BLOCK_SD_lWriteCardType(SDMMC_BLOCK_t *const obj)
+{
+ /* If F8=0; standard capacity v1 card */
+ if (obj->sdmmc_sd->f8 == (uint8_t)0U)
+ {
+ obj->card_type |= (uint8_t)SDMMC_BLOCK_CARD_TYPE_STANDARD_CAPACITY_V1X;
+ }
+ /* If F8=1; standard capacity v2 or high capacity card */
+ else
+ {
+ /* Check CCS bit in the OCR register; CCS=1 implies a high capacity card */
+ if (((uint32_t)obj->sdmmc_sd->card_info.ocr & (uint32_t)SDMMC_BLOCK_OCR_CCS_BITMASK) != (uint32_t)0U)
+ {
+ obj->card_type |= (uint8_t)((uint8_t)SDMMC_BLOCK_CARD_TYPE_HIGH_CAPACITY |
+ (uint8_t)SDMMC_BLOCK_CARD_TYPE_BLOCK_ADDRESSING);
+ }
+ else
+ {
+ /* CCS=0 implies standard capacity v2 */
+ obj->card_type |= (uint8_t)SDMMC_BLOCK_CARD_TYPE_STANDARD_CAPACITY_V2;
+ }
+ }
+}
+
+/* Check write protection status of card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lGetWriteProtect(SDMMC_BLOCK_t *const obj)
+{
+ uint32_t sd_status[16] = {0U};
+ uint32_t write_protect;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ status = SDMMC_BLOCK_SD_GetSdStatus(obj, (void *)&(sd_status[0]));
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Bits 480:495 in the SD status provides write protection information */
+ write_protect = ((sd_status[0] & 0xFF000000U) >> 24U) | (((sd_status[0] & 0x00FF0000U) >> 16U) << 8U);
+ if ((write_protect & SDMMC_BLOCK_SD_CARD_TYPE_BITMASK) != 0U)
+ {
+ obj->card_state |= (uint8_t)SDMMC_BLOCK_CARD_STATE_WRITE_PROTECTED;
+ }
+ }
+
+ return status;
+}
+
+/* Reads RCA (relative card address) of the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lReadRca(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(3)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_R6,
+ &(obj->sdmmc_sd->card_info.rca));
+ return status;
+}
+
+/* Read the CSD, SCR and Write protection status of the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lReadCardRegisters(SDMMC_BLOCK_t *const obj)
+{
+ uint32_t arg = 0U;
+ uint32_t card_status = 0U;
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ SDMMC_BLOCK_SCR_t scr_content = {0U};
+ uint8_t card_lock = (obj->card_state & (uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED);
+
+ /* Read CSD Register */
+ arg |= (uint32_t)((uint32_t)obj->sdmmc_sd->card_info.rca << (uint16_t)SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(9)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R2,
+ (void *)obj->sdmmc_sd->card_info.csd);
+
+ if ((status == SDMMC_BLOCK_MODE_STATUS_SUCCESS) && (card_lock == (uint8_t)0U))
+ {
+ /* Set write protection flags */
+ status = SDMMC_BLOCK_SD_lGetWriteProtect(obj);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Read SCR register for SD card */
+ if (((uint8_t)obj->card_type & (uint8_t)SDMMC_BLOCK_CARD_TYPE_MMC) == 0U)
+ {
+ /* Switch to Transferring State. */
+ status = SDMMC_BLOCK_SD_lSwitchToTransferState(obj);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Send application specific command CMD55 */
+ arg |= (uint32_t)((uint32_t)obj->sdmmc_sd->card_info.rca << (uint32_t)SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(55)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Set direction select bit */
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST);
+
+ /* Read the transferred SCR data */
+ status = SDMMC_BLOCK_SD_lSingleBlockTransfer(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(64)),
+ (uint32_t)SDMMC_BLOCK_ARGUMENT0,
+ (uint16_t)8U,
+ (uint32_t *)&scr_content,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_READ_BUFFER);
+
+ obj->sdmmc_sd->card_info.scr = scr_content;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ status = SDMMC_BLOCK_SD_lSwitchToTransferState(obj);
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST);
+ }
+
+ return status;
+}
+
+/* Configure the registers for a single block transfer */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lConfigureSingleBlockTransfer(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t arg,
+ uint16_t block_size)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t card_status = 0U;
+ XMC_SDMMC_TRANSFER_MODE_t response;
+
+ response.block_size = block_size;
+ response.type = XMC_SDMMC_TRANSFER_MODE_TYPE_SINGLE;
+ response.auto_cmd = XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_DISABLED;
+
+ XMC_SDMMC_SetDataTransferMode(obj->sdmmc_sd->sdmmc, &response);
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj, cmd, arg, XMC_SDMMC_RESPONSE_TYPE_R1, &card_status);
+
+ return status;
+}
+
+/* Configure the registers for a multi-block transfer */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lConfigureMultiBlockTransfer(SDMMC_BLOCK_t *const obj,
+ uint32_t *arg,
+ uint32_t num_blocks,
+ const XMC_SDMMC_COMMAND_t *cmd)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ uint32_t card_status = 0U;
+ XMC_SDMMC_TRANSFER_MODE_t response;
+
+ /* Block addressing */
+ if (((uint8_t)obj->card_type & (uint8_t)SDMMC_BLOCK_CARD_TYPE_BLOCK_ADDRESSING) == (uint8_t)0U)
+ {
+ *arg *= (uint32_t)512U;
+ }
+
+ response.block_size = SDMMC_BLOCK_TX_BLOCK_SIZE_VALUE;
+ response.num_blocks = num_blocks;
+ response.type = XMC_SDMMC_TRANSFER_MODE_TYPE_MULTIPLE;
+ response.auto_cmd = XMC_SDMMC_TRANSFER_MODE_AUTO_CMD_12;
+
+ XMC_SDMMC_SetDataTransferMode(obj->sdmmc_sd->sdmmc, &response);
+
+ /* Enable ACMD 12 interrupt signal */
+ XMC_SDMMC_EnableEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_ACMD_ERR);
+
+ /* Send multiple block transfer command */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj, cmd, *arg, XMC_SDMMC_RESPONSE_TYPE_R1, &card_status);
+
+ return status;
+}
+
+/* Transfer multiple blocks of data */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lMultiBlockTransfer(SDMMC_BLOCK_t *const obj,
+ uint32_t *addr,
+ uint32_t num_blocks,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t *buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_t transfer_mode)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ obj->sdmmc_sd->transfer_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Configure registers for Multi block transfer*/
+ status = SDMMC_BLOCK_SD_lConfigureMultiBlockTransfer(obj, addr, (uint32_t)num_blocks, cmd);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Read/write block data */
+ while ((uint32_t)num_blocks > 0U)
+ {
+ /* Perform Transfer */
+ status = SDMMC_BLOCK_SD_lDataTransfer(obj, buf, transfer_mode, SDMMC_BLOCK_NUM_QUADLETS_IN_BLOCK);
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ break;
+ }
+ /* Decrement number of blocks */
+ num_blocks--;
+ /* Pointer pointing to the next block pointer */
+ buf += (uint32_t)SDMMC_BLOCK_NUM_QUADLETS_IN_BLOCK;
+ }
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Block on transfer complete interrupt */
+ /* Timeout: 5ms */
+ status = SDMMC_BLOCK_SD_lTransferDelay(obj, SDMMC_BLOCK_DELAY_IN_TRANSFER);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check if transfer happened successfully; Check ACMD status */
+ if ((SDMMC_BLOCK_MODE_STATUS_t)obj->sdmmc_sd->acmd_int_err == SDMMC_BLOCK_MODE_STATUS_ACMD12_ERROR)
+ {
+ /* Call ACMD12 error recovery */
+ SDMMC_BLOCK_SD_lAcmdErrorRecovery(obj);
+ }
+ }
+ }
+ }
+ return status;
+}
+
+/* Performs single block transfer */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lSingleBlockTransfer(SDMMC_BLOCK_t *const obj,
+ const XMC_SDMMC_COMMAND_t *cmd,
+ uint32_t arg,
+ uint16_t block_size,
+ uint32_t *buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_t transfer_mode)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ uint32_t timeoutTime;
+ uint32_t qbytes = (uint32_t)(((((uint32_t)block_size + 3UL) >> 2U) << 2U) >> 2U);
+
+ status = SDMMC_BLOCK_SD_lConfigureSingleBlockTransfer(obj, cmd, arg, block_size);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Perform data transfer */
+ status = SDMMC_BLOCK_SD_lDataTransfer(obj, buf, transfer_mode, qbytes);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Block on transfer complete interrupt */
+ timeoutTime = TimerGet() + (SDMMC_BLOCK_DELAY_IN_TRANSFER / 1000u) + 1u;
+
+ do
+ {
+#if (SDMMC_BLOCK_POLLING_MODE > 0U)
+ /* Poll for interrupt events. */
+ SDMMC0_0_IRQHandler();
+#endif
+
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while ((uint8_t)obj->sdmmc_sd->isr_context.transfer_flag == (uint8_t)0U);
+
+ obj->sdmmc_sd->isr_context.transfer_flag = (uint8_t)0U;
+
+ /* Check transfer complete status */
+ if ((SDMMC_BLOCK_MODE_STATUS_t)obj->sdmmc_sd->transfer_int_err == SDMMC_BLOCK_MODE_STATUS_TRANSFER_COMPLETE)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ else
+ {
+ obj->sdmmc_sd->issue_abort = (uint8_t)1U;
+ status = SDMMC_BLOCK_SD_lErrorInterruptRecovery(obj);
+ }
+ }
+ }
+
+ return status;
+}
+
+/* Check lock status */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCheckLockStatus(SDMMC_BLOCK_t *const obj,
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t mode)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t lock_status;
+
+ status = SDMMC_BLOCK_SD_GetLockStatus(obj, &lock_status);
+ /* For lock, card state must be "locked" */
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ if ((lock_status == SDMMC_BLOCK_CARD_LOCK_STATUS_LOCKED) && (mode == SDMMC_BLOCK_CARD_LOCK_STATUS_LOCKED))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ /* For unlock, card state must be "unlocked" */
+ else if ((lock_status == SDMMC_BLOCK_CARD_LOCK_STATUS_UNLOCKED) && (mode == SDMMC_BLOCK_CARD_LOCK_STATUS_UNLOCKED))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ else
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_LOCK_UNLOCK_ERROR;
+ }
+ }
+
+ return status;
+}
+
+#if SDMMC_BLOCK_SD_SUPPORT_4_BUS_WIDTH
+
+/* Switch bus width to 4-bit if supported */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lSwitchBusWidth(SDMMC_BLOCK_t *const obj)
+{
+ uint32_t arg = 0U;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t card_status = 0U;
+
+ /* Switch to transfer state (CMD7) */
+ status = SDMMC_BLOCK_SD_lSwitchToTransferState(obj);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Disable card insertion interrupt */
+ XMC_SDMMC_DisableEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CARD_INS);
+
+ /* Check data transfer width supported in SCR register */
+ if ((obj->sdmmc_sd->card_info.scr.sd_bus_width & SDMMC_BLOCK_SCR_BUS_WIDTH4_BITMASK))
+ {
+ /* Set the argument */
+ arg |= ((uint32_t)obj->sdmmc_sd->card_info.rca << (uint32_t)SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ /* Send application specific command */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(55)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Send ACMD6 to switch the bus width */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(58)),
+ SDMMC_BLOCK_SD_4BUS_WIDTH_ARG,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+ }
+ }
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Set data transfer width */
+ XMC_SDMMC_SetDataTransferWidth(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_LINES_4);
+ }
+ }
+
+ return status;
+}
+
+/* Switch the card speed mode to high speed if supported */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lSwitchSpeed(SDMMC_BLOCK_t *const obj)
+{
+ uint32_t switch_status[16] = {0U};
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Check CMD6 support in SCR register */
+ if (obj->sdmmc_sd->card_info.scr.sd_spec != 0UL)
+ {
+ /* Switch to transfer state (CMD7) */
+ status = SDMMC_BLOCK_SD_lSwitchToTransferState(obj);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /*
+ * Send the Switch function command and read the transferred block of
+ * data from the card
+ */
+ status = SDMMC_BLOCK_SD_lSingleBlockTransfer(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(6)),
+ SDMMC_BLOCK_SD_HIGH_SPEED_ARG,
+ 64U,
+ (uint32_t *)switch_status,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_READ_BUFFER);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ if (((switch_status[4] & (uint32_t)SDMMC_BLOCK_SWITCH_FUNC_GRP1_STATUS_BITMASK) >>
+ (uint32_t)SDMMC_BLOCK_SWITCH_FUNC_GRP1_STATUS_BITPOS) != (uint32_t)1U)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ }
+ }
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Change speed mode (high speed) in the host controller */
+ XMC_SDMMC_EnableHighSpeed(obj->sdmmc_sd->sdmmc);
+ }
+ }
+ }
+
+ return status;
+}
+
+#endif
+
+/* Provides delay in command execution */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCommandDelay(SDMMC_BLOCK_t *const obj, uint32_t delay)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ uint32_t timeoutTime;
+ obj->sdmmc_sd->tmr_expire = (bool)1U;
+
+ timeoutTime = TimerGet() + (delay / 1000u) + 1u;
+
+ do
+ {
+#if (SDMMC_BLOCK_POLLING_MODE > 0U)
+ /* Poll for interrupt events. */
+ SDMMC0_0_IRQHandler();
+#endif
+
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while ((!((obj->sdmmc_sd->isr_context.cmd_flag == 1U) ||
+ (obj->sdmmc_sd->isr_context.data_flag == 1U))) &&
+ ((XMC_SDMMC_GetEvent(obj->sdmmc_sd->sdmmc, XMC_SDMMC_CARD_ERR) != 0U)));
+
+ obj->sdmmc_sd->isr_context.cmd_flag = (uint8_t)0U;
+ obj->sdmmc_sd->isr_context.data_flag = (uint8_t)0U;
+
+ return status;
+}
+
+/* Recovery task for error interrupts */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lErrorInterruptRecovery(SDMMC_BLOCK_t *const obj)
+{
+ XMC_SDMMC_COMMAND_t *cmd = (XMC_SDMMC_COMMAND_t *)&(SDMMC_BLOCK_COMMON_COMMAND(12));
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_NONRECOVERABLE_ERROR;
+ uint32_t normal_events = 0U;
+ uint32_t error_events = 0U;
+
+ error_events = ((uint32_t)XMC_SDMMC_CMD_TIMEOUT_ERR) |
+ ((uint32_t)XMC_SDMMC_CMD_CRC_ERR) |
+ ((uint32_t)XMC_SDMMC_CMD_END_BIT_ERR) |
+ ((uint32_t)XMC_SDMMC_CMD_IND_ERR) |
+ ((uint32_t)XMC_SDMMC_DATA_TIMEOUT_ERR) |
+ ((uint32_t)XMC_SDMMC_DATA_CRC_ERR) |
+ ((uint32_t)XMC_SDMMC_DATA_END_BIT_ERR) |
+ ((uint32_t)XMC_SDMMC_CURRENT_LIMIT_ERR) |
+ ((uint32_t)XMC_SDMMC_TARGET_RESP_ERR);
+
+ /* Disable all error events */
+ XMC_SDMMC_DisableEvent(obj->sdmmc_sd->sdmmc, error_events);
+
+ /* Check error interrupt status bits D0-D3 for CMD line errors */
+ if ((((uint32_t)obj->sdmmc_sd->isr_context.int_status_shadow &
+ (uint32_t)SDMMC_BLOCK_ERROR_CMD_STATUS_BITMASK) != (uint32_t)0U) ||
+ (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc) == true))
+ {
+ /* Set software reset for CMD line */
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RST_CMD_LINE);
+ }
+
+ /* Check error interrupt status bits D4-D6 for data line errors */
+ if ((((uint32_t)obj->sdmmc_sd->isr_context.int_status_shadow &
+ (uint32_t)SDMMC_BLOCK_ERROR_DATA_STATUS_BITMASK) != (uint32_t)0U) ||
+ (XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc) == true))
+ {
+ /* Set software reset for data line */
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RST_DAT_LINE);
+ }
+
+ error_events = ((uint32_t)XMC_SDMMC_CMD_TIMEOUT_ERR) |
+ ((uint32_t)XMC_SDMMC_CMD_CRC_ERR) |
+ ((uint32_t)XMC_SDMMC_CMD_END_BIT_ERR) |
+ ((uint32_t)XMC_SDMMC_CMD_IND_ERR) |
+ ((uint32_t)XMC_SDMMC_DATA_TIMEOUT_ERR) |
+ ((uint32_t)XMC_SDMMC_DATA_CRC_ERR) |
+ ((uint32_t)XMC_SDMMC_DATA_END_BIT_ERR) |
+ ((uint32_t)XMC_SDMMC_CURRENT_LIMIT_ERR) |
+ ((uint32_t)XMC_SDMMC_CARD_ERR);
+
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, error_events);
+
+ if (obj->sdmmc_sd->issue_abort == (uint8_t)1U)
+ {
+ /* Issue abort command. Set argument register */
+ (void)XMC_SDMMC_SendCommand(obj->sdmmc_sd->sdmmc, cmd, SDMMC_BLOCK_ARGUMENT0);
+
+ /* Wait for any interrupt status bit to be set */
+
+ /* Timeout of 5ms */
+ status = SDMMC_BLOCK_SD_lCommandDelay(obj, (uint32_t)SDMMC_BLOCK_DELAY_IN_COMMAND);
+ if ((SDMMC_BLOCK_MODE_STATUS_t)status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* If error status bit is set in the status register */
+ if (XMC_SDMMC_IsAnyErrorEvent(obj->sdmmc_sd->sdmmc) == true)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_NONRECOVERABLE_ERROR;
+
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, normal_events);
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, error_events);
+
+ /* Set software reset for CMD line and data line */
+ (void)SDMMC_BLOCK_SD_lReset(obj, (uint32_t)((uint32_t)XMC_SDMMC_SW_RST_CMD_LINE |
+ (uint32_t)XMC_SDMMC_SW_RST_DAT_LINE));
+ }
+ }
+
+ /* Check Data lines status in present status register */
+ if (XMC_SDMMC_IsAnyErrorEvent(obj->sdmmc_sd->sdmmc) == false)
+ {
+ if (XMC_SDMMC_IsAllDataLinesHigh(obj->sdmmc_sd->sdmmc) == true)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_RECOVERABLE_ERROR;
+ }
+ else
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_NONRECOVERABLE_ERROR;
+ }
+ }
+ }
+ else
+ {
+ if (XMC_SDMMC_IsAnyErrorEvent(obj->sdmmc_sd->sdmmc) == false)
+ {
+ if (XMC_SDMMC_IsAllDataLinesHigh(obj->sdmmc_sd->sdmmc) == true)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_RECOVERABLE_ERROR;
+ }
+ else
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_NONRECOVERABLE_ERROR;
+ }
+ }
+ }
+
+ /* Enable the error interrupt signal */
+ error_events |= (uint32_t)XMC_SDMMC_TARGET_RESP_ERR;
+ XMC_SDMMC_EnableEvent(obj->sdmmc_sd->sdmmc, error_events);
+
+ /* Global error recovery variable */
+ obj->sdmmc_sd->err_recovery_stat = status;
+
+ return status;
+}
+
+/* Handles interrupts in normal interrupt status register */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_NormalInterruptHandler(SDMMC_BLOCK_t *const obj, uint16_t int_status)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+
+#if SDMMC_BLOCK_SD_CARD_DETECTION_SUPPORT
+ bool pstate;
+
+ /* Card removal interrupt */
+ if ((int_status & (uint32_t)XMC_SDMMC_CARD_REMOVAL) != 0U)
+ {
+ obj->sdmmc_sd->card_detect_state |= ((uint32_t)1U << SDMMC_BLOCK_SD_INTERRUPT_CARD_REMOVAL);
+ /* Clear the interrupt status bit */
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CARD_REMOVAL);
+ }
+
+ /* Card insertion interrupt */
+ if ((int_status & (uint32_t)XMC_SDMMC_CARD_INS) != 0U)
+ {
+ obj->sdmmc_sd->card_detect_state |= ((uint32_t)1U << SDMMC_BLOCK_SD_INTERRUPT_CARD_INSERTION);
+ /* Clear the interrupt status bit */
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CARD_INS);
+ }
+
+ /* Invoke a callback function if a user has registered one */
+ if ((obj->sdmmc_sd->callback != NULL) && (obj->sdmmc_sd->card_detect_state != 0U))
+ {
+ obj->sdmmc_sd->card_detect_state = 0U;
+ pstate = (bool)(SDMMC_BLOCK_0.sdmmc_sd->sdmmc->PRESENT_STATE & SDMMC_PRESENT_STATE_CARD_INSERTED_Msk);
+ obj->sdmmc_sd->callback((SDMMC_BLOCK_SD_INTERRUPT_t)pstate);
+ }
+ else
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_NULL_POINTER;
+ }
+#endif
+
+ /* Buffer read ready interrupt */
+ if (((uint32_t)int_status & (uint32_t)XMC_SDMMC_BUFFER_READ_READY) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_BUFFER_READY;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_BUFFER_READ_READY);
+ obj->sdmmc_sd->isr_context.data_flag = (uint8_t)1U;
+ }
+
+ /* Buffer write ready interrupt */
+ if (((uint32_t)int_status & (uint32_t)XMC_SDMMC_BUFFER_WRITE_READY) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_BUFFER_READY;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_BUFFER_WRITE_READY);
+ obj->sdmmc_sd->isr_context.data_flag = (uint8_t)1U;
+ }
+
+ /* Transfer complete interrupt */
+ if (((uint32_t)int_status & (uint32_t)XMC_SDMMC_TX_COMPLETE) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->transfer_int_err = SDMMC_BLOCK_MODE_STATUS_TRANSFER_COMPLETE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_TX_COMPLETE);
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_DATA_ACTIVE;
+ obj->sdmmc_sd->isr_context.transfer_flag = (uint8_t)1U;
+ }
+
+ /* Command complete interrupt */
+ if (((uint32_t)int_status & (uint32_t)XMC_SDMMC_CMD_COMPLETE) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_COMMAND_COMPLETE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CMD_COMPLETE);
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ obj->sdmmc_sd->isr_context.cmd_flag = (uint8_t)1;
+ }
+
+ return status;
+}
+
+/* Handles interrupt in error interrupt status register */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_ErrorInterruptHandler(SDMMC_BLOCK_t *const obj,
+ uint16_t int_status)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->isr_context.int_status_shadow = int_status;
+
+ /* Command timeout error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_CMD_TIMEOUT_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_COMMAND_TIMEOUT_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CMD_TIMEOUT_ERR);
+ obj->sdmmc_sd->isr_context.cmd_flag = 1U;
+ }
+
+ /* Command CRC error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_CMD_CRC_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_COMMAND_CRC_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CMD_CRC_ERR);
+ obj->sdmmc_sd->isr_context.cmd_flag = 1U;
+ }
+
+ /* Command end bit error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_CMD_END_BIT_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_COMMAND_ENDBIT_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CMD_END_BIT_ERR);
+ obj->sdmmc_sd->isr_context.cmd_flag = 1U;
+ }
+
+ /* Command index error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_CMD_IND_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_COMMAND_INDEX_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_CMD_IND_ERR);
+ obj->sdmmc_sd->isr_context.cmd_flag = 1U;
+ }
+
+ /* Data timeout error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_DATA_TIMEOUT_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_DATA_TIMEOUT_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_DATA_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_DATA_TIMEOUT_ERR);
+ obj->sdmmc_sd->isr_context.data_flag = 1U;
+ }
+
+ /* Data CRC error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_DATA_CRC_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_DATA_CRC_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_DATA_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_DATA_CRC_ERR);
+ obj->sdmmc_sd->isr_context.data_flag = 1U;
+ }
+
+ /* Data end bit error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_DATA_END_BIT_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_DATA_ENDBIT_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_DATA_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_DATA_END_BIT_ERR);
+ obj->sdmmc_sd->isr_context.data_flag = 1U;
+ }
+
+ /* ACMD12 error interrupt */
+ if (((uint32_t)int_status & ((uint32_t)XMC_SDMMC_ACMD_ERR >> 16U)) != (uint32_t)0)
+ {
+ obj->sdmmc_sd->acmd_int_err = SDMMC_BLOCK_MODE_STATUS_ACMD12_ERROR;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_CMD_ACTIVE;
+ obj->card_state &= (uint8_t)~(uint8_t)SDMMC_BLOCK_CARD_STATE_DATA_ACTIVE;
+ XMC_SDMMC_ClearEvent(obj->sdmmc_sd->sdmmc, (uint32_t)XMC_SDMMC_ACMD_ERR);
+ obj->sdmmc_sd->isr_context.cmd_flag = 1U;
+ }
+
+ return status;
+}
+
+/* Switch the card state to transferring state if it isn't */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lSwitchToTransferState(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t arg = 0UL;
+ uint32_t card_status = 0U;
+
+ /* Check the current state of the card */
+ arg |= (uint32_t)((uint32_t)obj->sdmmc_sd->card_info.rca << (uint32_t)SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ /* Send CMD13 to read card status */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(13)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check if it is in transferring state */
+ if (((card_status & SDMMC_BLOCK_SD_CSR_CURRENT_STATE_BITMASK) >> SDMMC_BLOCK_SD_CSR_CURRENT_STATE_BITPOS) ==
+ SDMMC_BLOCK_SD_CSR_CURRENT_STATE_TRANS_VALUE)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ else
+ {
+ /* Switch to transfer state (CMD7) */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(7)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1b,
+ &card_status);
+ }
+ }
+
+ return status;
+}
+
+/* Do data transfer to OR from card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lDataTransfer(SDMMC_BLOCK_t *const obj,
+ uint32_t *buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_t transfer_mode,
+ uint32_t quad_bytes)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t timeoutTime;
+ uint32_t count = 0U;
+
+ /* Block on buffer read/write ready interrupt */
+ timeoutTime = TimerGet() + (SDMMC_BLOCK_RESET_IN_DATA_TRANSFER / 1000u) + 1u;
+
+ do
+ {
+#if (SDMMC_BLOCK_POLLING_MODE > 0U)
+ /* Poll for interrupt events. */
+ SDMMC0_0_IRQHandler();
+#endif
+
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while (obj->sdmmc_sd->isr_context.data_flag == 0U);
+
+ obj->sdmmc_sd->isr_context.data_flag = (uint8_t)0U;
+
+ /* Check if buffer is ready */
+ if (obj->sdmmc_sd->data_int_err == SDMMC_BLOCK_MODE_STATUS_BUFFER_READY)
+ {
+ /* 4 bytes data transmission in each iteration */
+ for (count = 0U; count < quad_bytes; count++)
+ {
+ if (transfer_mode == SDMMC_BLOCK_SD_DATA_TRANSFER_READ_BUFFER)
+ {
+ *buf = (uint32_t)XMC_SDMMC_ReadFIFO(obj->sdmmc_sd->sdmmc);
+ }
+
+ if (transfer_mode == SDMMC_BLOCK_SD_DATA_TRANSFER_WRITE_BUFFER)
+ {
+ XMC_SDMMC_WriteFIFO(obj->sdmmc_sd->sdmmc, buf);
+ }
+
+ buf++;
+ }
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ }
+ else
+ {
+ obj->sdmmc_sd->issue_abort = (uint8_t)1U;
+ status = SDMMC_BLOCK_SD_lErrorInterruptRecovery(obj);
+ }
+
+ return status;
+}
+
+/* Performs the ACMD error recovery */
+static void SDMMC_BLOCK_SD_lAcmdErrorRecovery(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ uint32_t pcmd_flag = 0U;
+ uint32_t card_status = 0U;
+
+ /* Check ACMD12 "Not executed err" in Auto CMD12 error status register */
+ if (XMC_SDMMC_GetACMDErrStatus(obj->sdmmc_sd->sdmmc, XMC_SDMMC_ACMD12_NOT_EXEC_ERR) == true)
+ {
+ pcmd_flag = 1U;
+ /* Check Return Status of Recovery function of CMD_wo_DAT command */
+ if (obj->sdmmc_sd->err_recovery_stat == SDMMC_BLOCK_MODE_STATUS_RECOVERABLE_ERROR)
+ {
+ /* For recoverable error, issue CMD12 */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(12)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+ }
+ if ((status != SDMMC_BLOCK_MODE_STATUS_SUCCESS) && (status != SDMMC_BLOCK_MODE_STATUS_NONRECOVERABLE_ERROR))
+ {
+ /* Set software reset for data line */
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RST_DAT_LINE);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check for XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR */
+ if (XMC_SDMMC_GetACMDErrStatus(obj->sdmmc_sd->sdmmc, XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR) == true)
+ {
+ XMC_DEBUG("SDMMC_BLOCK_ACMDErrorRecovery: SDMMC_BLOCK_ACMD_CMD_wo_DAT_NOT_ISSUED");
+ }
+ else
+ {
+ /*
+ * Check pcmd_flag. If 1, an error occurred in CMD_wo_DAT,
+ * and also in the SD memory transfer
+ */
+ if (pcmd_flag == 1U)
+ {
+ XMC_DEBUG("SDMMC_BLOCK_CheckPCMDFlag: ACMD both error");
+ }
+ else
+ {
+ XMC_DEBUG("SDMMC_BLOCK_CheckPCMDFlag: ACMD SD transfer error");
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* Set software reset for CMD line */
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RST_CMD_LINE);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Issue CMD12 */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(12)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+ if (status != SDMMC_BLOCK_MODE_STATUS_NONRECOVERABLE_ERROR)
+ {
+ /*Set Software Reset for Data line*/
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RST_DAT_LINE);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR */
+ if (XMC_SDMMC_GetACMDErrStatus(obj->sdmmc_sd->sdmmc, XMC_SDMMC_CMD_NOT_ISSUED_BY_ACMD12_ERR) == true)
+ {
+ XMC_DEBUG("SDMMC_BLOCK_ACMDErrorRecovery: SDMMC_BLOCK_ACMD_CMD_wo_DAT_NOT_ISSUED");
+ }
+ else
+ {
+ /*
+ * Check PCMD flag. If 1, an error occurred in CMD_wo_DAT,
+ * and also in the SD memory transfer
+ */
+ if (pcmd_flag == 1U)
+ {
+ XMC_DEBUG("SDMMC_BLOCK_CheckPCMDFlag: ACMD both error");
+ }
+ else
+ {
+ XMC_DEBUG("SDMMC_BLOCK_CheckPCMDFlag: ACMD SD transfer error");
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+/* Delay function */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lDelay(SDMMC_BLOCK_t *const obj, uint32_t delay)
+{
+ uint32_t timeoutTime;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_CREATE_TIMER_FAILED;
+
+ /* Set timeout time. */
+ timeoutTime = TimerGet() + (delay / 1000u) + 1u;
+
+ /* Wait for the timer to expire. */
+ while (TimerGet() < timeoutTime)
+ {
+ /* Service the watchdog. */
+ CopService();
+ }
+
+ /* Update the status. */
+ status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+
+ /* Return the status. */
+ return status;
+}
+
+/*
+ * Perform host controller initialization and card initialization.
+ * Also, reading card registers
+ */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_CardIdentificationProcess(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t timeoutTime;
+
+ /* Wait until the internal clock is stable */
+ timeoutTime = TimerGet() + (SDMMC_BLOCK_CLOCK_STABLE_DELAY / 1000u) + 1u;
+
+ do
+ {
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while ((XMC_SDMMC_GetClockStability(obj->sdmmc_sd->sdmmc) == false));
+
+ if (status != SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED)
+ {
+ /* Enable the SD clock */
+ XMC_SDMMC_SDClockEnable(obj->sdmmc_sd->sdmmc);
+
+ /* Turn the bus power on */
+ XMC_SDMMC_BusPowerOn(obj->sdmmc_sd->sdmmc);
+
+ if (obj->sdmmc_sd->mode_init_flag == false)
+ {
+ status = SDMMC_BLOCK_SD_lInitializeCard(obj);
+ if ((status == SDMMC_BLOCK_MODE_STATUS_SUCCESS) ||
+ (status == SDMMC_BLOCK_MODE_STATUS_INITIALIZED_BUT_LOCKED))
+ {
+ status = SDMMC_BLOCK_SD_lAfterCardInitialize(obj);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ obj->sdmmc_sd->mode_init_flag = 1U;
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+/* Check if the sector address is out of bound */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCheckSectorBound(SDMMC_BLOCK_t *const obj,
+ uint32_t sector_num,
+ uint32_t sector_count)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ uint32_t local_sector_count = 0U;
+
+ /* Get sector count function */
+ status = SDMMC_BLOCK_SD_GetSectorCount(obj, (void *)&local_sector_count);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Check the sector count limit */
+ if ((sector_num + sector_count) > local_sector_count)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_SECTOR_OUT_OF_BOUND;
+ }
+ }
+
+ return status;
+}
+
+/* Perform erase operation */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lLocalErase(SDMMC_BLOCK_t *const obj,
+ uint32_t start_addr,
+ uint32_t end_addr,
+ uint32_t timeout)
+{
+ /* Stores the response received */
+ uint32_t card_status = 0U;
+ uint32_t timeoutTime;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ if (((uint32_t)obj->card_type & (uint32_t)SDMMC_BLOCK_CARD_TYPE_BLOCK_ADDRESSING) == (uint32_t)0U)
+ {
+ start_addr *= (uint32_t)512U;
+ end_addr *= (uint32_t)512U;
+ }
+
+ /* SD erase start command */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(32)),
+ start_addr,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* SD Erase End Command */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(33)),
+ end_addr,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+ }
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(38)),
+ SDMMC_BLOCK_ARGUMENT0,
+ XMC_SDMMC_RESPONSE_TYPE_R1b,
+ &card_status);
+
+ timeoutTime = TimerGet() + ((timeout * (uint32_t)1000U)) + 1u;
+
+ do
+ {
+ if (TimerGet() > timeoutTime)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_TIMEOUT_OCCURED;
+ break;
+ }
+ /* Service the watchdog. */
+ CopService();
+ } while ((XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc) ||
+ (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc))));
+
+ }
+
+ return status;
+}
+
+/*
+ * PUBLIC FUNCTIONS
+ */
+
+/* Initialize host controller */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lHostControllerInit(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_HOST_CONTROLLER_INITIALIZED;
+
+ /* Check if host controller is initialized */
+ if (((uint32_t)obj->card_state & (uint32_t)SDMMC_BLOCK_CARD_STATE_HC_INITIALIZED) == (uint32_t)0U)
+ {
+ /* Reset the registers to default values */
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RESET_ALL);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /*
+ * The internal clock should be disabled before
+ * updating frequency clock select (Please see
+ * section 2.2.14 -> Clock Control Register)
+ */
+ XMC_SDMMC_Stop(obj->sdmmc_sd->sdmmc);
+
+ /* Select SD clock frequency */
+ XMC_SDMMC_SDClockFreqSelect(obj->sdmmc_sd->sdmmc, XMC_SDMMC_CLK_DIV_2);
+
+ /* Internal clock enable */
+ XMC_SDMMC_Start(obj->sdmmc_sd->sdmmc);
+
+ /*
+ * Enable all normal interrupt status bits except block-gap
+ * event, card interrupt event, DMA int., ADMA and auto cmd
+ * errors. Enable the status and the events themselves.
+ */
+ obj->sdmmc_sd->sdmmc->EN_INT_STATUS_NORM = SDMMC_BLOCK_NORMAL_INT_STATUS_ENABLE;
+ obj->sdmmc_sd->sdmmc->EN_INT_STATUS_ERR = SDMMC_BLOCK_ERROR_INT_STATUS_ENABLE;
+ obj->sdmmc_sd->sdmmc->EN_INT_SIGNAL_NORM = SDMMC_BLOCK_NORMAL_INT_SIGNAL_ENABLE;
+ obj->sdmmc_sd->sdmmc->EN_INT_SIGNAL_ERR = SDMMC_BLOCK_ERROR_INT_SIGNAL_ENABLE;
+
+#if SDMMC_BLOCK_SD_CARD_DETECTION_SUPPORT
+ XMC_SDMMC_EnableEvent(obj->sdmmc_sd->sdmmc, ((uint32_t)XMC_SDMMC_CARD_REMOVAL) |
+ ((uint32_t)XMC_SDMMC_CARD_INS) |
+ ((uint32_t)XMC_SDMMC_CARD_INT));
+#endif
+
+ /* Set data-line timeout */
+ XMC_SDMMC_SetDataLineTimeout(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DAT_TIMEOUT_COUNTER_2_POW_27);
+
+ /* Set bus voltage in the power control register: flattop 3.3 volts */
+ XMC_SDMMC_SetBusVoltage(obj->sdmmc_sd->sdmmc, XMC_SDMMC_BUS_VOLTAGE_3_3_VOLTS);
+
+ /* Update the state status to card initialized */
+ obj->card_state |= (uint8_t)((uint8_t)SDMMC_BLOCK_CARD_STATE_HC_INITIALIZED |
+ (uint8_t)SDMMC_BLOCK_CARD_STATE_NO_CARD |
+ (uint8_t)SDMMC_BLOCK_CARD_STATE_NOT_INITIALIZED);
+
+ /* A stub of delay for initialization */
+ for (volatile uint32_t i = 0; (uint32_t)i < (uint32_t)100000U; i++)
+ {
+ }
+ }
+ }
+
+ return status;
+}
+
+/* De-initialize the host controller */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lHostControllerDeInit(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Check if the host controller is initialized */
+ if (((uint32_t)obj->card_state & (uint32_t)SDMMC_BLOCK_CARD_STATE_HC_INITIALIZED) != (uint32_t)0U)
+ {
+ /* Cleanup the card */
+ SDMMC_BLOCK_SD_lCardCleanUp(obj);
+
+ /* Reset host controller's registers */
+ status = SDMMC_BLOCK_SD_lReset(obj, (uint32_t)XMC_SDMMC_SW_RESET_ALL);
+ }
+
+ return status;
+}
+
+/* Read multiple blocks of data from the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCardReadMultipleBlocks(SDMMC_BLOCK_t *const obj,
+ uint32_t *read_buf,
+ uint32_t read_addr,
+ uint32_t num_blocks)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_INIT_FAIL;
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->transfer_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Check if initialization is successful */
+ if (obj->sdmmc_sd->mode_init_flag == true)
+ {
+ /* Ensure that sector number is not out of bound */
+ status = SDMMC_BLOCK_SD_lCheckSectorBound(obj, read_addr, num_blocks);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Set transfer direction select in the Transfer Mode Register */
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST);
+
+ /* Send Multiple Block Read Command i.e CMD18 */
+ status = SDMMC_BLOCK_SD_lMultiBlockTransfer(obj,
+ &read_addr,
+ num_blocks,
+ &(SDMMC_BLOCK_COMMON_COMMAND(18)),
+ read_buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_READ_BUFFER);
+ }
+ }
+
+ return status;
+}
+
+/* Read single block of data from the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCardReadSingleBlock(SDMMC_BLOCK_t *const obj,
+ uint32_t *read_buf,
+ uint32_t read_addr)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_INIT_FAIL;
+ uint32_t sector_count = 1U;
+
+ /* Check if initialization successful */
+ if (obj->sdmmc_sd->mode_init_flag == true)
+ {
+ /* Ensure that the sector number is not out of bound */
+ status = SDMMC_BLOCK_SD_lCheckSectorBound(obj, read_addr, sector_count);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Block addressing or byte addressing */
+ if (((uint32_t)obj->card_type & (uint32_t)SDMMC_BLOCK_CARD_TYPE_BLOCK_ADDRESSING) == (uint32_t)0UL)
+ {
+ read_addr = (uint32_t)(read_addr * 512UL);
+ }
+
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST);
+ /* SDMMC->TRANSFER_MODE |= (uint16_t)((uint32_t)1U << (uint32_t)SDMMC_TRANSFER_MODE_TX_DIR_SELECT_Pos); */
+
+ /* Perform the Single block transfer operation */
+ status = SDMMC_BLOCK_SD_lSingleBlockTransfer(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(17)),
+ read_addr,
+ (uint16_t)SDMMC_BLOCK_BLOCK_SIZE,
+ read_buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_READ_BUFFER);
+ }
+ }
+
+ return status;
+}
+
+/* Write multiple blocks of data on the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCardWriteMultipleBlocks(SDMMC_BLOCK_t *const obj,
+ const uint32_t *write_buf,
+ uint32_t write_addr,
+ uint32_t num_blocks)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_INIT_FAIL;
+
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->transfer_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Check if initialization is successful */
+ if (obj->sdmmc_sd->mode_init_flag == true)
+ {
+ /* Ensure sector number is not out of bound */
+ status = SDMMC_BLOCK_SD_lCheckSectorBound(obj, write_addr, num_blocks);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Clear transfer direction select in transfer mode register */
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD);
+
+ /* Send Multiple Block Write Command i.e CMD25 */
+ status = SDMMC_BLOCK_SD_lMultiBlockTransfer(obj,
+ &write_addr,
+ num_blocks,
+ &(SDMMC_BLOCK_COMMON_COMMAND(25)),
+ (uint32_t *)write_buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_WRITE_BUFFER);
+ }
+ }
+
+ return status;
+}
+
+/* Write single block of data on the card */
+static SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_lCardWriteSingleBlock(SDMMC_BLOCK_t *const obj,
+ const uint32_t *write_buf,
+ uint32_t write_addr)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_INIT_FAIL;
+ uint32_t sector_count = 1U;
+
+ /* Check if initialization is successful */
+ if (obj->sdmmc_sd->mode_init_flag == true)
+ {
+ /* Check if sector number is not out of bound */
+ status = SDMMC_BLOCK_SD_lCheckSectorBound(obj, write_addr, sector_count);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* If not block addressing, then multiply by 512 bytes */
+ if (((uint32_t)obj->card_type & (uint32_t)SDMMC_BLOCK_CARD_TYPE_BLOCK_ADDRESSING) == (uint32_t)0U)
+ {
+ write_addr = (uint32_t)(write_addr * 512U);
+ }
+
+ /* Clear transfer direction select bit */
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD);
+
+ /* Single block transfer function */
+ status = SDMMC_BLOCK_SD_lSingleBlockTransfer(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(24)),
+ write_addr,
+ (uint16_t)SDMMC_BLOCK_BLOCK_SIZE,
+ (uint32_t *)write_buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_WRITE_BUFFER);
+ }
+ }
+
+ return status;
+}
+
+/* Erase data from the card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_EraseBlock(SDMMC_BLOCK_t *const obj, uint32_t start_addr, uint32_t end_addr)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_INIT_FAIL;
+ uint32_t tmp_start_addr;
+ uint32_t num_sectors = 0U;
+ /* Allocation unit to no. of sectors in 1 AU table mapping */
+ uint32_t au_to_sectors[10] = {0U, 32U, 64U, 128U, 256U, 512U, 1024U, 2048U, 4096U, 8192U};
+ uint16_t erase_size = (uint16_t)0U;
+ uint8_t erase_offset = (uint8_t)0U;
+ uint8_t erase_timeout = (uint8_t)0U;
+ uint8_t au_size = (uint8_t)0U;
+ uint32_t sectors_in_au = 0U;
+ uint32_t sectors_in_erase_cluster = 0U;
+ /* Read SD status */
+ uint32_t sd_status[16] = {0U};
+ uint32_t erase_timeout_per_cluster = 0UL;
+
+ obj->sdmmc_sd->cmd_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->data_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ obj->sdmmc_sd->transfer_int_err = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* If the card is read only or write protected */
+ if ((obj->card_state & (uint8_t)SDMMC_BLOCK_CARD_STATE_WRITE_PROTECTED) != (uint8_t)0U)
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_WP_VIOLATION_ERROR;
+ }
+#ifdef SDMMC_BLOCK_CARD_WRITE_PROTECT_SIGNAL
+ else if ((obj->sdwc != NULL) && (XMC_GPIO_GetInput(obj->sdwc->port, obj->sdwc->pin)))
+ {
+ status = SDMMC_BLOCK_MODE_STATUS_WP_VIOLATION_ERROR;
+ }
+#endif /* SDMMC_BLOCK_CARD_WRITE_PROTECT_SIGNAL */
+ /* Assume initialization is successful: This is invoked from IOCTL */
+ else
+ {
+ tmp_start_addr = start_addr;
+ num_sectors = (end_addr - tmp_start_addr) + 1U;
+ /* Check sector number is not out of bound */
+ status = SDMMC_BLOCK_SD_lCheckSectorBound(obj, tmp_start_addr, num_sectors);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Erase timeout calculation */
+ /* Get SD status */
+ status = SDMMC_BLOCK_SD_GetSdStatus(obj, (void*)&(sd_status[0]));
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Bits 400-401 in SD status: Erase offset */
+ erase_offset = (uint8_t)(((sd_status[3] & 0x00000300UL)) >> 8U);
+
+ /* Bits 402-407: Erase timeout */
+ erase_timeout = (uint8_t)(((sd_status[3] & 0x0000FC00UL)) >> 10UL);
+
+ /* Bits 408-423: Erase size */
+ erase_size = (uint16_t)((((sd_status[2] & 0xFF000000U) >> 24U) << 8U) | (sd_status[3] & 0x000000FFU));
+
+ /* Bits 428-431: Allocation unit size */
+ au_size = (uint8_t)((sd_status[2] & 0x00F00000U) >> 20);
+
+ /* Erase timeout calculations */
+ erase_timeout_per_cluster = ((uint32_t)erase_timeout / (uint32_t)erase_size) + (uint32_t)erase_offset;
+
+ /* Number of sectors in 1 AU */
+ sectors_in_au = au_to_sectors[au_size];
+ sectors_in_erase_cluster = sectors_in_au * erase_size;
+
+ while (num_sectors >= sectors_in_erase_cluster)
+ {
+ status = SDMMC_BLOCK_SD_lLocalErase(obj,
+ tmp_start_addr,
+ (tmp_start_addr + sectors_in_erase_cluster),
+ erase_timeout_per_cluster);
+ if (status != SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ break;
+ }
+ tmp_start_addr = tmp_start_addr + sectors_in_erase_cluster;
+ num_sectors = num_sectors - sectors_in_erase_cluster;
+ }
+
+ if (num_sectors != 0U)
+ {
+ status = SDMMC_BLOCK_SD_lLocalErase(obj, tmp_start_addr, end_addr, erase_timeout_per_cluster);
+ }
+ }
+ }
+ }
+
+ /* Wait for until the command OR data lines aren't busy */
+ while ((XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc)) || (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc)))
+ {
+ }
+
+ return status;
+}
+
+/* Set, clear password, lock/unlock card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_LockUnlockCard(SDMMC_BLOCK_t *const obj,
+ SDMMC_BLOCK_LOCK_STRUCTURE_t *lock,
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t operation_mode)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t data_length = 0U;
+ uint32_t card_status;
+
+ /* Select the card before proceeding */
+ status = SDMMC_BLOCK_SD_lSwitchToTransferState(obj);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Send CMD42 and write the lock data structure */
+ /* Clear transfer direction select in transfer mode register */
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_HOST_TO_CARD);
+
+ /* Compute password length */
+ data_length = (uint32_t)((((uint32_t)lock->pwd_len + (uint32_t)1U) >> 1U) << 1U) + 2U;
+
+ /* Set block length */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(16)),
+ data_length,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ status = SDMMC_BLOCK_SD_lSingleBlockTransfer(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(42)),
+ (uint32_t)SDMMC_BLOCK_ARGUMENT0,
+ (uint16_t)data_length,
+ (uint32_t *)lock,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_WRITE_BUFFER);
+
+ while (XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc))
+ {
+ }
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(16)),
+ 512U,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ /* Wait for until the command OR data lines aren't busy */
+ while ((XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc)) ||
+ (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc)))
+ {
+ }
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ status = SDMMC_BLOCK_SD_lCheckLockStatus(obj, operation_mode);
+ }
+ }
+ }
+ return status;
+}
+
+/* Get the lock status from card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetLockStatus(SDMMC_BLOCK_t *const obj,
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t *lock_status)
+{
+ uint32_t card_status = 0UL;
+ uint32_t arg = 0UL;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ arg |= ((uint32_t)obj->sdmmc_sd->card_info.rca << SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ /* Send CMD13 to read card status */
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(13)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Lock/unlock status bit in the CSR register */
+ if (((uint32_t)card_status & (uint32_t)SDMMC_BLOCK_SD_CSR_CARD_IS_LOCKED_BITMASK) != (uint32_t)0)
+ {
+ *lock_status = SDMMC_BLOCK_CARD_LOCK_STATUS_LOCKED;
+ obj->card_state |= (uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED;
+ }
+ else
+ {
+ *lock_status = SDMMC_BLOCK_CARD_LOCK_STATUS_UNLOCKED;
+ obj->card_state &= (uint8_t)~(uint8_t)(SDMMC_BLOCK_CARD_STATE_LOCKED);
+ }
+ }
+
+ return status;
+}
+
+/* Get card's current state */
+uint8_t SDMMC_BLOCK_SD_GetState(SDMMC_BLOCK_t *obj)
+{
+ return (obj->card_state & 0xFU);
+}
+
+/* Get card type */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetCardType(SDMMC_BLOCK_t *const obj, uint32_t *card_type)
+{
+ *card_type = obj->card_type;
+
+ return SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+}
+
+/* Get CID register information of card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetCid(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ SDMMC_BLOCK_CID_t *temp = (SDMMC_BLOCK_CID_t *)buf;
+
+ temp->manufacturing_date = (uint16_t)((obj->sdmmc_sd->card_info.cid[0]) & 0xFFFU);
+ temp->product_serial_num = (obj->sdmmc_sd->card_info.cid[1] << 16U) | (obj->sdmmc_sd->card_info.cid[0] >> 16U);
+ temp->product_rev = (uint8_t)((obj->sdmmc_sd->card_info.cid[1] >> 16U) & 0xFFU);
+ temp->product_name[0] = (uint8_t)((obj->sdmmc_sd->card_info.cid[2] >> 24U) & 0xFFU);
+ temp->product_name[1] = (uint8_t)((obj->sdmmc_sd->card_info.cid[2] >> 16U) & 0xFFU);
+ temp->product_name[2] = (uint8_t)((obj->sdmmc_sd->card_info.cid[2] >> 8U) & 0xFFU);
+ temp->product_name[3] = (uint8_t)((obj->sdmmc_sd->card_info.cid[2] >> 0U) & 0xFFU);
+ temp->product_name[4] = (uint8_t)((obj->sdmmc_sd->card_info.cid[1] >> 24U) & 0xFFU);
+ temp->app_oem_id[0] = (uint8_t)((obj->sdmmc_sd->card_info.cid[3] >> 8U) & 0xFFU);
+ temp->app_oem_id[1] = (uint8_t)((obj->sdmmc_sd->card_info.cid[3]) & 0xFFU);
+ temp->manufacturer_id = (uint8_t)((obj->sdmmc_sd->card_info.cid[3] >> 16U) & 0xFFU);
+
+ return SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+}
+
+/* Get OCR information */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetOcr(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ *(uint32_t *)buf = obj->sdmmc_sd->card_info.ocr;
+
+ return SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+}
+
+/* Get CSD information */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetCsd(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ /*
+ * CSD Structure includes 7-bit CRC and 1-bit fixed bit
+ * which is not sent by the card. So, skip 1 byte before
+ * copying into the structure.
+ */
+ memcpy(((uint8_t *)buf + 1U), (void *)obj->sdmmc_sd->card_info.csd, 15U);
+
+ return SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+}
+
+/* Get number of sectors present on the card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetSectorCount(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+ uint32_t mult = 0U;
+
+ if (((uint32_t)obj->card_type & (uint32_t)SDMMC_BLOCK_CARD_TYPE_HIGH_CAPACITY) != (uint32_t)0U)
+ {
+ SDMMC_BLOCK_SDV2_CSD_t temp_csd_v2 = {0U};
+
+ /* Get CSD function */
+ status = SDMMC_BLOCK_SD_GetCsd(obj, (void *)&temp_csd_v2);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /*
+ * For High Capacity SD card, (C_SIZE field value + 1) * 1024
+ * gives the sector count
+ */
+ *(uint32_t *)buf = (uint32_t)(((((uint32_t)temp_csd_v2.dev_size_high << (uint32_t)16UL) |
+ ((uint32_t)temp_csd_v2.dev_size_low)) + (uint32_t)1UL) << (uint32_t)10UL);
+ }
+ }
+ /*
+ * For Standard SD (and MMC) cards:
+ * Sector Count = (Device Size + 1) * Mult, where Mult = 2 ^ C_SIZE_MULT
+ */
+ else
+ {
+ SDMMC_BLOCK_SDV1_CSD_t temp_csd_v1 = {0U};
+ /* Get CSD function */
+ status = SDMMC_BLOCK_SD_GetCsd(obj, (void *)&temp_csd_v1);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Left shift evaluates 1 * 2 ^ (TmpMmcCsd.DeviceSizeMult + 2) */
+ mult = (uint32_t)((uint32_t)temp_csd_v1.dev_size_mult + 2U);
+
+ /* Sector Count = device_size * mult */
+ *(uint32_t *)buf = (uint32_t)((((uint32_t)temp_csd_v1.dev_size_high << (uint32_t)2UL) |
+ ((uint32_t)temp_csd_v1.dev_size_low)) + (uint32_t)1UL) << mult;
+ }
+ }
+
+ return status;
+}
+
+/* Get sector size info from the card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetSectorSize(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ /* Sector Size is fixed to 512 bytes */
+ *(uint16_t *)buf = (uint16_t)512U;
+
+ return SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+}
+
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetBlockSize(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_SUCCESS;
+
+ /* SD high capacity card (CSD V2) */
+ if (((uint32_t)obj->card_type & (uint32_t)SDMMC_BLOCK_CARD_TYPE_HIGH_CAPACITY) != (uint32_t)0)
+ {
+ SDMMC_BLOCK_SDV2_CSD_t temp_csd_v2 = {0U};
+ /* Get CSD function */
+ status = SDMMC_BLOCK_SD_GetCsd(obj, (void *)&temp_csd_v2);
+ *(uint32_t *)buf = (uint32_t)((uint32_t)temp_csd_v2.erase_sector_size + (uint32_t)1U);
+ }
+ /* SD standard capacity card (CSD V1) */
+ else
+ {
+ SDMMC_BLOCK_SDV2_CSD_t temp_csd_v1 = {0U};
+ /* Get CSD function */
+ status = SDMMC_BLOCK_SD_GetCsd(obj, (void *)&temp_csd_v1);
+ *(uint32_t *)buf = (uint32_t)((uint32_t)temp_csd_v1.erase_sector_size + (uint32_t)1U);
+ }
+
+ return status;
+}
+
+/* Get SD status information */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_GetSdStatus(SDMMC_BLOCK_t *const obj, void *buf)
+{
+ uint32_t arg = 0U;
+ uint32_t card_status = 0U;
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+
+ /* Select the card (CMD7) */
+ status = SDMMC_BLOCK_SD_lSwitchToTransferState(obj);
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Send CMD55 (application specific command) */
+ arg |= (uint32_t)((uint32_t)obj->sdmmc_sd->card_info.rca << (uint32_t)SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_COMMON_COMMAND(55)),
+ arg,
+ XMC_SDMMC_RESPONSE_TYPE_R1,
+ &card_status);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Set transfer mode */
+ XMC_SDMMC_SetDataTransferDirection(obj->sdmmc_sd->sdmmc, XMC_SDMMC_DATA_TRANSFER_CARD_TO_HOST);
+
+ /* Read the SD status from the data line */
+ status = SDMMC_BLOCK_SD_lSingleBlockTransfer(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(59)),
+ (uint32_t)SDMMC_BLOCK_ARGUMENT0,
+ (uint16_t)64U,
+ (uint32_t *)buf,
+ SDMMC_BLOCK_SD_DATA_TRANSFER_READ_BUFFER);
+ }
+ }
+
+ return status;
+}
+
+/* Eject SD card */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_EjectCard(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_FAILURE;
+ uint32_t arg = 0U;
+
+ if ((obj->card_state & (uint16_t)SDMMC_BLOCK_CARD_STATE_NO_CARD) == 0U)
+ {
+ /* Send CMD15 to deactivate the card */
+ arg |= (uint32_t)((uint32_t)obj->sdmmc_sd->card_info.rca << (uint32_t)SDMMC_BLOCK_ARG_RCA_BITPOS);
+
+ status = SDMMC_BLOCK_SD_lSendCommand(obj,
+ &(SDMMC_BLOCK_SD_COMMAND(15)),
+ (uint32_t)arg,
+ (XMC_SDMMC_RESPONSE_TYPE_t)XMC_SDMMC_RESPONSE_TYPE_NO_RESPONSE,
+ NULL);
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ /* Card Cleanup */
+ SDMMC_BLOCK_SD_lCardCleanUp(obj);
+ obj->sdmmc_sd->mode_init_flag = false;
+ }
+ }
+
+ return status;
+}
+
+/*
+ * Initialize low level drivers, host controller, the card
+ * and read card registers.
+ */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_Start(SDMMC_BLOCK_t *const obj)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status = SDMMC_BLOCK_MODE_STATUS_HOST_CONTROLLER_INITIALIZED;
+
+ /* Check If host controller is already initialized */
+ if (((uint32_t)obj->card_state & (uint32_t)SDMMC_BLOCK_CARD_STATE_HC_INITIALIZED) == (uint32_t)0U)
+ {
+#if (SDMMC_BLOCK_POLLING_MODE == 0U)
+ /* Enable Interrupt */
+ NVIC_SetPriority(SDMMC0_0_IRQn,
+ NVIC_EncodePriority(NVIC_GetPriorityGrouping(),
+ obj->sdmmc_sd->int_priority,
+ obj->sdmmc_sd->int_sub_priority));
+
+ NVIC_ClearPendingIRQ(SDMMC0_0_IRQn);
+ NVIC_EnableIRQ(SDMMC0_0_IRQn);
+#endif
+
+ /* Host controller initialize */
+ status = SDMMC_BLOCK_SD_lHostControllerInit(obj);
+ }
+
+ return status;
+}
+
+/* De-assert the SDMMC peripheral */
+SDMMC_BLOCK_MODE_STATUS_t SDMMC_BLOCK_SD_Init(SDMMC_BLOCK_t *const obj)
+{
+ /* Enable SDMMC peripheral */
+ XMC_SDMMC_Enable(obj->sdmmc_sd->sdmmc);
+
+ /* Enable SCU clock for SDMMC */
+ XMC_SCU_CLOCK_EnableClock(XMC_SCU_CLOCK_MMC);
+
+ /* De-initialize host controller */
+ (void)SDMMC_BLOCK_SD_lHostControllerDeInit(obj);
+
+ /* Initialize LLD and host controller */
+ return SDMMC_BLOCK_SD_Start(obj);
+}
+
+/* Reads the data from the card */
+SDMMC_BLOCK_STATUS_t SDMMC_BLOCK_SD_ReadBlock(SDMMC_BLOCK_t *const obj,
+ uint8_t *read_buf,
+ uint32_t sector_num,
+ uint8_t sector_count)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ uint8_t disk_status;
+ SDMMC_BLOCK_STATUS_t res;
+
+ /* Check the status before reading data */
+ disk_status = obj->card_state;
+
+ if ((disk_status & (uint8_t)SDMMC_BLOCK_CARD_STATE_NOT_INITIALIZED) != (uint8_t)0U)
+ {
+ res = SDMMC_BLOCK_STATUS_NOTRDY;
+ }
+ else if ((disk_status & (uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED) != (uint8_t)0U)
+ {
+ res = SDMMC_BLOCK_STATUS_LOCKED;
+ }
+ else
+ {
+ /* Check for single block read or multiple block read based on sector count */
+ if (sector_count == (uint8_t)1U)
+ {
+ status = SDMMC_BLOCK_SD_lCardReadSingleBlock(obj, (uint32_t *)read_buf, sector_num);
+ }
+ else
+ {
+ status = SDMMC_BLOCK_SD_lCardReadMultipleBlocks(obj, (uint32_t *)read_buf, sector_num, (uint32_t)sector_count);
+ }
+
+ if (status == SDMMC_BLOCK_MODE_STATUS_SUCCESS)
+ {
+ res = SDMMC_BLOCK_STATUS_SUCCESS;
+ }
+ else if (status == SDMMC_BLOCK_MODE_STATUS_SECTOR_OUT_OF_BOUND)
+ {
+ res = SDMMC_BLOCK_STATUS_PARERR;
+ }
+ else
+ {
+ res = SDMMC_BLOCK_STATUS_FAILURE;
+ }
+ }
+
+ /* Wait for until the command OR data lines aren't busy */
+ while ((XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc)) || (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc)))
+ {
+ }
+
+ return res;
+}
+
+/* Writes the data on the card */
+SDMMC_BLOCK_STATUS_t SDMMC_BLOCK_SD_WriteBlock(SDMMC_BLOCK_t *const obj,
+ const uint8_t *write_buf,
+ uint32_t sector_num,
+ uint8_t sector_count)
+{
+ SDMMC_BLOCK_MODE_STATUS_t status;
+ uint8_t disk_status;
+ SDMMC_BLOCK_STATUS_t res;
+
+ /* Get card state */
+ disk_status = obj->card_state;
+
+ /* If the card is not initialized */
+ if ((disk_status & (uint8_t)SDMMC_BLOCK_CARD_STATE_NOT_INITIALIZED) != (uint8_t)0U)
+ {
+ res = SDMMC_BLOCK_STATUS_NOTRDY;
+ }
+ else if ((disk_status & (uint8_t)SDMMC_BLOCK_CARD_STATE_LOCKED) != (uint8_t)0U)
+ {
+ res = SDMMC_BLOCK_STATUS_LOCKED;
+ }
+ /* If the card is read only or write protected */
+ else if ((disk_status & (uint8_t)SDMMC_BLOCK_CARD_STATE_WRITE_PROTECTED) != (uint8_t)0U)
+ {
+ res = SDMMC_BLOCK_STATUS_WRPRT;
+ }
+#ifdef SDMMC_BLOCK_CARD_WRITE_PROTECT_SIGNAL
+ else if ((obj->sdwc != NULL) && (XMC_GPIO_GetInput(obj->sdwc->port, obj->sdwc->pin)))
+ {
+ res = SDMMC_BLOCK_STATUS_WRPRT;
+ }
+#endif /* SDMMC_BLOCK_CARD_WRITE_PROTECT_SIGNAL */
+ else
+ {
+ /* Check for single block write or multiple block write */
+ if (sector_count == (uint8_t)1U)
+ {
+ status = SDMMC_BLOCK_SD_lCardWriteSingleBlock(obj, (const uint32_t *)write_buf, sector_num);
+ }
+ else
+ {
+ status = SDMMC_BLOCK_SD_lCardWriteMultipleBlocks(obj,
+ (const uint32_t *)write_buf,
+ sector_num,
+ (uint32_t)sector_count);
+ }
+
+ if ((status == SDMMC_BLOCK_MODE_STATUS_SUCCESS) || (status == SDMMC_BLOCK_MODE_STATUS_BUFFER_READY))
+ {
+ res = SDMMC_BLOCK_STATUS_SUCCESS;
+ }
+ else if (status == SDMMC_BLOCK_MODE_STATUS_SECTOR_OUT_OF_BOUND)
+ {
+ res = SDMMC_BLOCK_STATUS_PARERR;
+ }
+ else
+ {
+ res = SDMMC_BLOCK_STATUS_FAILURE;
+ }
+ }
+
+ /* Wait for until the command OR data lines aren't busy */
+ while ((XMC_SDMMC_IsDataLineBusy(obj->sdmmc_sd->sdmmc)) || (XMC_SDMMC_IsCommandLineBusy(obj->sdmmc_sd->sdmmc)))
+ {
+ }
+
+ return res;
+}
+
+#endif /* SDMMC_BLOCK_SD */
+
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_private_sd.h b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_private_sd.h
new file mode 100644
index 00000000..6bec7078
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/SDMMC_BLOCK/sdmmc_block_private_sd.h
@@ -0,0 +1,263 @@
+/**
+ * @file sdmmc_block_private_sd.h
+ * @date 2016-08-24
+ *
+ * NOTE:
+ * This file is generated by DAVE. Any manual modification done to this file will be lost when the code is regenerated.
+ *
+ * @cond
+ ***********************************************************************************************************************
+ * SDMMC_BLOCK v4.0.22 - Configures the SD host to interface with the SDMMC card.
+ *
+ * Copyright (c) 2016-2017, 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
+ * --------------
+ *
+ * 2016-01-20:
+ * - Initial version.
+ *
+ * 2016-02-08:
+ * - Help Doc updated.
+ * - Bug fixes done.
+ *
+ * 2016-04-05:
+ * - MISRA fixes
+ *
+ * @endcond
+ *
+ */
+
+
+#ifndef SDMMC_BLOCK_SD_H
+#define SDMMC_BLOCK_SD_H
+
+/***********************************************************************************************************************
+ * HEADER FILES
+ **********************************************************************************************************************/
+
+#include
+#include "sdmmc_block.h"
+
+#ifdef SDMMC_BLOCK_SD
+
+/***********************************************************************************************************************
+ * LOCAL DATA
+ **********************************************************************************************************************/
+
+extern const XMC_SDMMC_COMMAND_t sdmmc_block_command[40];
+extern const uint8_t sdmmc_block_sd_hash_table[65];
+
+/***********************************************************************************************************************
+ * MACROS
+ **********************************************************************************************************************/
+
+/**
+ * @brief This structure stores the command register fields.
+ */
+#define SDMMC_BLOCK_COMMON_COMMAND(c) sdmmc_block_command[sdmmc_block_sd_hash_table[c]]
+#define SDMMC_BLOCK_SD_COMMAND(c) SDMMC_BLOCK_COMMON_COMMAND(c)
+
+#define SDMMC_BLOCK_ERROR_CMD_STATUS_BITMASK (0x000FU) /* Command line Int errors status bit-mask */
+#define SDMMC_BLOCK_ERROR_DATA_STATUS_BITMASK (0x0070U) /* Data line Error status bitmask */
+#define SDMMC_BLOCK_TX_BLOCK_SIZE_VALUE (0x0200U) /* Transfer block register */
+#define SDMMC_BLOCK_HC_RESPONSE1_BITPOS (0x10U) /* Response register */
+#define SDMMC_BLOCK_SWITCH_FUNC_GRP1_STATUS_BITMASK (0x0000000FU) /* Switch speed function bit-mask */
+#define SDMMC_BLOCK_SWITCH_FUNC_GRP1_STATUS_BITPOS (0x0U) /* Switch speed function bit-position */
+
+/*
+ * Append by 3 zeros since the SYSTIMER APP takes
+ * time in microseconds
+ */
+#define SDMMC_BLOCK_CARD_POWER_DELAY (20000U) /* Card power delay */
+#define SDMMC_BLOCK_DELAY_IN_TRANSFER (1000000U) /* Transfer delay */
+#define SDMMC_BLOCK_RESET_IN_DATA_TRANSFER (1000000U) /* Reset in data transfer */
+#define SDMMC_BLOCK_DELAY_IN_COMMAND (1000000U) /* Command delay */
+#define SDMMC_BLOCK_RESET_DELAY (500000U) /* Reset delay */
+#define SDMMC_BLOCK_CLOCK_STABLE_DELAY (1000000U) /* Clock stable delay */
+
+#define SDMMC_BLOCK_NUM_CARD_RESET_RETRIES (2U) /* Number of reset retries at card init */
+#define SDMMC_BLOCK_BLOCK_SIZE (512U) /* Block Size in bytes */
+#define SDMMC_BLOCK_NUM_QUADLETS_IN_BLOCK (SDMMC_BLOCK_BLOCK_SIZE >> 2U) /* Block size in quad bytes */
+
+/* Command index */
+#define SDMMC_BLOCK_GO_IDLE_STATE (0x00U) /* CMD0 */
+#define SDMMC_BLOCK_MMC_SEND_OP_COND (0x01U) /* MMC CMD1 */
+#define SDMMC_BLOCK_ALL_SEND_CID (0x02U) /* CMD2 */
+#define SDMMC_BLOCK_SEND_RELATIVE_ADDR (0x03U) /* CMD3 */
+#define SDMMC_BLOCK_SET_DSR (0x04U) /* CMD4 */
+#define SDMMC_BLOCK_MMC_SLEEP_AWAKE (0x05U) /* MMC CMD5 */
+#define SDMMC_BLOCK_SWITCH_FUNC (0x06U) /* CMD6 */
+#define SDMMC_BLOCK_SELECT_DESELECT_CARD (0x07U) /* CMD7 */
+#define SDMMC_BLOCK_SD_SEND_IF_COND (0x08U) /* SD CMD8 */
+#define SDMMC_BLOCK_MMC_SEND_EXT_CSD (0x08U) /* MMC CMD8 */
+#define SDMMC_BLOCK_SEND_CSD (0x09U) /* CMD9 */
+#define SDMMC_BLOCK_SEND_CID (0x0AU) /* CMD10 */
+#define SDMMC_BLOCK_STOP_TRANSMISSION (0x0CU) /* CMD12 */
+#define SDMMC_BLOCK_SEND_STATUS (0x0DU) /* CMD13 */
+#define SDMMC_BLOCK_GO_INACTIVE_STATE (0x0FU) /* CMD15 */
+#define SDMMC_BLOCK_SET_BLOCKLEN (0x10U) /* CMD16 */
+#define SDMMC_BLOCK_READ_SINGLE_BLOCK (0x11U) /* CMD17 */
+#define SDMMC_BLOCK_READ_MULTIPLE_BLOCK (0x12U) /* CMD18 */
+#define SDMMC_BLOCK_WRITE_BLOCK (0x18U) /* CMD24 */
+#define SDMMC_BLOCK_WRITE_MULTIPLE_BLOCK (0x19U) /* CMD25 */
+#define SDMMC_BLOCK_PROGRAM_CSD (0x1BU) /* CMD27 */
+#define SDMMC_BLOCK_SET_WRITE_PROT (0x1CU) /* CMD28 */
+#define SDMMC_BLOCK_CLR_WRITE_PROT (0x1DU) /* CMD29 */
+#define SDMMC_BLOCK_SEND_WRITE_PROT (0x1EU) /* CMD30 */
+#define SDMMC_BLOCK_ERASE_WR_BLK_START (0x20U) /* CMD32 */
+#define SDMMC_BLOCK_ERASE_WR_BLK_END (0x21U) /* CMD33 */
+#define SDMMC_BLOCK_ERASE_GROUP_START (0x23U) /* CMD35 */
+#define SDMMC_BLOCK_ERASE_GROUP_END (0x24U) /* CMD36 */
+#define SDMMC_BLOCK_ERASE (0x26U) /* CMD38 */
+#define SDMMC_BLOCK_LOCK_UNLOCK (0x2AU) /* CMD42 */
+#define SDMMC_BLOCK_APP_CMD (0x37U) /* CMD55 */
+#define SDMMC_BLOCK_GEN_CMD (0x38U) /* CMD56 */
+#define SDMMC_BLOCK_SET_BUS_WIDTH (0x06U) /* ACMD6 */
+#define SDMMC_BLOCK_SD_STATUS (0x0DU) /* ACMD13 */
+#define SDMMC_BLOCK_SEND_NUM_WR_BLOCKS (0x16U) /* ACMD22 */
+#define SDMMC_BLOCK_SET_WR_BLK_ERASE_COUNT (0x17U) /* ACMD23 */
+#define SDMMC_BLOCK_SD_SEND_OP_COND (0x29U) /* ACMD41 */
+#define SDMMC_BLOCK_SET_CLR_CARD_DETECT (0x2AU) /* ACMD42 */
+#define SDMMC_BLOCK_SEND_SCR (0x33U) /* ACMD51 */
+
+/* Start of Card Status Register i.e CSR Error Bits bitmask */
+#define SDMMC_BLOCK_SD_CSR_OUT_OF_RANGE_BITMASK (0x80000000U)
+#define SDMMC_BLOCK_SD_CSR_ADDRESS_ERROR_BITMASK (0x40000000U)
+#define SDMMC_BLOCK_SD_CSR_BLOCK_LEN_ERROR_BITMASK (0x20000000U)
+#define SDMMC_BLOCK_SD_CSR_ERASE_SEQ_ERROR_BITMASK (0x10000000U)
+#define SDMMC_BLOCK_SD_CSR_ERASE_PARAM_BITMASK (0x08000000U)
+#define SDMMC_BLOCK_SD_CSR_WP_VIOLATION_BITMASK (0x04000000U)
+#define SDMMC_BLOCK_SD_CSR_LOCK_UNLOCK_FAILED_BITMASK (0x01000000U)
+#define SDMMC_BLOCK_SD_CSR_COM_CRC_ERROR_BITMASK (0x00800000U)
+#define SDMMC_BLOCK_SD_CSR_ILLEGAL_COMMAND_BITMASK (0x00400000U)
+#define SDMMC_BLOCK_SD_CSR_CARD_ECC_FAILED_BITMASK (0x00200000U)
+#define SDMMC_BLOCK_SD_CSR_CC_ERROR_BITMASK (0x00100000U)
+#define SDMMC_BLOCK_SD_CSR_ERROR_BITMASK (0x00080000U)
+#define SDMMC_BLOCK_SD_CSR_CSD_OVERWRITE_BITMASK (0x00010000U)
+#define SDMMC_BLOCK_SD_CSR_WP_ERASE_SKIP_BITMASK (0x00008000U)
+#define SDMMC_BLOCK_SD_SWITCH_ERROR_BITMASK (0x00000080U)
+#define SDMMC_BLOCK_SD_CSR_ASK_SEQ_ERROR_BITMASK (0x00000008U)
+#define SDMMC_BLOCK_SD_CSR_CARD_IS_LOCKED_BITMASK (0x02000000U)
+#define SDMMC_BLOCK_SD_CSR_CURRENT_STATE_BITMASK (0x00001D00U)
+#define SDMMC_BLOCK_SD_CSR_CURRENT_STATE_BITPOS (0x00000009U)
+#define SDMMC_BLOCK_SD_CSR_CURRENT_STATE_TRANS_VALUE (0x00000004U)
+#define SDMMC_BLOCK_SD_CSR_CARD_IS_LOCKED_BITMASK (0x02000000U)
+
+/* Normal and error interrupt status defines */
+#define SDMMC_BLOCK_NORMAL_INT_STATUS_ENABLE (0x00F3U)
+#define SDMMC_BLOCK_ERROR_INT_STATUS_ENABLE (0xE0FFU)
+#define SDMMC_BLOCK_NORMAL_INT_SIGNAL_ENABLE (0x0033U)
+#define SDMMC_BLOCK_ERROR_INT_SIGNAL_ENABLE (0xE0FFU)
+
+/***********************************************************************************************************************
+ * ENUMS
+ **********************************************************************************************************************/
+
+/***********************************************************************************************************************
+ * DATA STRUCTURES
+ **********************************************************************************************************************/
+
+/***********************************************************************************************************************
+ * API PROTOTYPES
+ **********************************************************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetLockStatus(SDMMC_BLOCK_t *const obj, SDMMC_BLOCK_CARD_LOCK_STATUS_t *lock_stat);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_CardIdentificationProcess(SDMMC_BLOCK_t *const obj);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetSdStatus(SDMMC_BLOCK_t *const obj, void *buf);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetSectorCount(SDMMC_BLOCK_t *const obj, void *buf);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetCid(SDMMC_BLOCK_t *const obj, void *buf);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetOcr(SDMMC_BLOCK_t *const obj, void *buf);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetCsd(SDMMC_BLOCK_t *const obj, void *buf);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetCardType(SDMMC_BLOCK_t *const obj, uint32_t *card_type);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_EraseBlock(SDMMC_BLOCK_t *const obj, uint32_t start_addr, uint32_t end_addr);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetSectorSize(SDMMC_BLOCK_t *const obj, void *buf);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_GetBlockSize(SDMMC_BLOCK_t *const obj, void *buf);
+
+uint8_t
+SDMMC_BLOCK_SD_GetState(SDMMC_BLOCK_t *const obj);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_Init(SDMMC_BLOCK_t *const obj);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_CheckLockStatus(SDMMC_BLOCK_t *const obj,
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t mode);
+
+SDMMC_BLOCK_STATUS_t
+SDMMC_BLOCK_SD_ReadBlock(SDMMC_BLOCK_t *const obj,
+ uint8_t *read_buf,
+ uint32_t sector_num,
+ uint8_t sector_count);
+
+SDMMC_BLOCK_STATUS_t
+SDMMC_BLOCK_SD_WriteBlock(SDMMC_BLOCK_t *const obj,
+ const uint8_t *write_buf,
+ uint32_t sector_num,
+ uint8_t sector_count);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_LockUnlockCard(SDMMC_BLOCK_t *const obj,
+ SDMMC_BLOCK_LOCK_STRUCTURE_t *lock,
+ SDMMC_BLOCK_CARD_LOCK_STATUS_t mode);
+
+SDMMC_BLOCK_MODE_STATUS_t
+SDMMC_BLOCK_SD_EjectCard(SDMMC_BLOCK_t *const obj);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* #ifdef SDMMC_BLOCK_SD */
+
+#endif /* SDMMC_BLOCK_SD_H */
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/ffconf.h b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/ffconf.h
new file mode 100644
index 00000000..c51b9383
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/ffconf.h
@@ -0,0 +1,266 @@
+/*---------------------------------------------------------------------------/
+/ FatFs - FAT file system module configuration file R0.12 (C)ChaN, 2016
+/---------------------------------------------------------------------------*/
+
+#define _FFCONF 88100 /* Revision ID */
+
+/*---------------------------------------------------------------------------/
+/ Function Configurations
+/---------------------------------------------------------------------------*/
+
+#define _FS_READONLY 0
+/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
+/ Read-only configuration removes writing API functions, f_write(), f_sync(),
+/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
+/ and optional writing functions as well. */
+
+
+#define _FS_MINIMIZE 0
+/* This option defines minimization level to remove some basic API functions.
+/
+/ 0: All basic functions are enabled.
+/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
+/ are removed.
+/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
+/ 3: f_lseek() function is removed in addition to 2. */
+
+
+#define _USE_STRFUNC 2 /* 0:Disable or 1-2:Enable */
+/* This option switches string functions, f_gets(), f_putc(), f_puts() and
+/ f_printf().
+/
+/ 0: Disable string functions.
+/ 1: Enable without LF-CRLF conversion.
+/ 2: Enable with LF-CRLF conversion. */
+
+
+#define _USE_FIND 0
+/* This option switches filtered directory read functions, f_findfirst() and
+/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
+
+
+#define _USE_MKFS 0
+/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
+
+
+#define _USE_FASTSEEK 0
+/* This option switches fast seek function. (0:Disable or 1:Enable) */
+
+
+#define _USE_EXPAND 0
+/* This option switches f_expand function. (0:Disable or 1:Enable) */
+
+
+#define _USE_CHMOD 0
+/* This option switches attribute manipulation functions, f_chmod() and f_utime().
+/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
+
+
+#define _USE_LABEL 0
+/* This option switches volume label functions, f_getlabel() and f_setlabel().
+/ (0:Disable or 1:Enable) */
+
+
+#define _USE_FORWARD 0
+/* This option switches f_forward() function. (0:Disable or 1:Enable)
+/ To enable it, also _FS_TINY need to be 1. */
+
+
+/*---------------------------------------------------------------------------/
+/ Locale and Namespace Configurations
+/---------------------------------------------------------------------------*/
+
+#define _CODE_PAGE 437
+/* This option specifies the OEM code page to be used on the target system.
+/ Incorrect setting of the code page can cause a file open failure.
+/
+/ 1 - ASCII (No extended character. Non-LFN cfg. only)
+/ 437 - U.S.
+/ 720 - Arabic
+/ 737 - Greek
+/ 771 - KBL
+/ 775 - Baltic
+/ 850 - Latin 1
+/ 852 - Latin 2
+/ 855 - Cyrillic
+/ 857 - Turkish
+/ 860 - Portuguese
+/ 861 - Icelandic
+/ 862 - Hebrew
+/ 863 - Canadian French
+/ 864 - Arabic
+/ 865 - Nordic
+/ 866 - Russian
+/ 869 - Greek 2
+/ 932 - Japanese (DBCS)
+/ 936 - Simplified Chinese (DBCS)
+/ 949 - Korean (DBCS)
+/ 950 - Traditional Chinese (DBCS)
+*/
+
+
+#define _USE_LFN 1 /* 0 to 3 */
+#define _MAX_LFN 255
+/* The _USE_LFN switches the support of long file name (LFN).
+/
+/ 0: Disable support of LFN. _MAX_LFN has no effect.
+/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
+/ 2: Enable LFN with dynamic working buffer on the STACK.
+/ 3: Enable LFN with dynamic working buffer on the HEAP.
+/
+/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
+/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
+/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
+/ It should be set 255 to support full featured LFN operations.
+/ When use stack for the working buffer, take care on stack overflow. When use heap
+/ memory for the working buffer, memory management functions, ff_memalloc() and
+/ ff_memfree(), must be added to the project. */
+
+
+#define _LFN_UNICODE 0
+/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
+/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
+/ This option also affects behavior of string I/O functions. */
+
+
+#define _STRF_ENCODE 3
+/* When _LFN_UNICODE == 1, this option selects the character encoding on the file to
+/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
+/
+/ 0: ANSI/OEM
+/ 1: UTF-16LE
+/ 2: UTF-16BE
+/ 3: UTF-8
+/
+/ This option has no effect when _LFN_UNICODE == 0. */
+
+
+#define _FS_RPATH 0
+/* This option configures support of relative path.
+/
+/ 0: Disable relative path and remove related functions.
+/ 1: Enable relative path. f_chdir() and f_chdrive() are available.
+/ 2: f_getcwd() function is available in addition to 1.
+*/
+
+
+/*---------------------------------------------------------------------------/
+/ Drive/Volume Configurations
+/---------------------------------------------------------------------------*/
+
+#define _VOLUMES 1
+/* Number of volumes (logical drives) to be used. */
+
+
+#define _STR_VOLUME_ID 0
+#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
+/* _STR_VOLUME_ID switches string support of volume ID.
+/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
+/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
+/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
+/ the drive ID strings are: A-Z and 0-9. */
+
+
+#define _MULTI_PARTITION 0
+/* This option switches support of multi-partition on a physical drive.
+/ By default (0), each logical drive number is bound to the same physical drive
+/ number and only an FAT volume found on the physical drive will be mounted.
+/ When multi-partition is enabled (1), each logical drive number can be bound to
+/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
+/ funciton will be available. */
+
+
+#define _MIN_SS 512
+#define _MAX_SS 512
+/* These options configure the range of sector size to be supported. (512, 1024,
+/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
+/ harddisk. But a larger value may be required for on-board flash memory and some
+/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
+/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
+/ disk_ioctl() function. */
+
+
+#define _USE_TRIM 0
+/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
+/ To enable Trim function, also CTRL_TRIM command should be implemented to the
+/ disk_ioctl() function. */
+
+
+#define _FS_NOFSINFO 0
+/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
+/ option, and f_getfree() function at first time after volume mount will force
+/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
+/
+/ bit0=0: Use free cluster count in the FSINFO if available.
+/ bit0=1: Do not trust free cluster count in the FSINFO.
+/ bit1=0: Use last allocated cluster number in the FSINFO if available.
+/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
+*/
+
+
+
+/*---------------------------------------------------------------------------/
+/ System Configurations
+/---------------------------------------------------------------------------*/
+
+#define _FS_TINY 0
+/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
+/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes.
+/ Instead of private sector buffer eliminated from the file object, common sector
+/ buffer in the file system object (FATFS) is used for the file data transfer. */
+
+
+#define _FS_EXFAT 0
+/* This option switches support of exFAT file system in addition to the traditional
+/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled.
+/ Note that enabling exFAT discards C89 compatibility. */
+
+
+#define _FS_NORTC 1
+#define _NORTC_MON 3
+#define _NORTC_MDAY 1
+#define _NORTC_YEAR 2016
+/* The option _FS_NORTC switches timestamp functiton. If the system does not have
+/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
+/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
+/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
+/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
+/ added to the project to get current time form real-time clock. _NORTC_MON,
+/ _NORTC_MDAY and _NORTC_YEAR have no effect.
+/ These options have no effect at read-only configuration (_FS_READONLY = 1). */
+
+
+#define _FS_LOCK 0
+/* The option _FS_LOCK switches file lock function to control duplicated file open
+/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
+/ is 1.
+/
+/ 0: Disable file lock function. To avoid volume corruption, application program
+/ should avoid illegal open, remove and rename to the open objects.
+/ >0: Enable file lock function. The value defines how many files/sub-directories
+/ can be opened simultaneously under file lock control. Note that the file
+/ lock control is independent of re-entrancy. */
+
+
+#define _FS_REENTRANT 0
+#define _FS_TIMEOUT 1000
+#define _SYNC_t HANDLE
+/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
+/ module itself. Note that regardless of this option, file access to different
+/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
+/ and f_fdisk() function, are always not re-entrant. Only file/directory access
+/ to the same volume is under control of this function.
+/
+/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
+/ 1: Enable re-entrancy. Also user provided synchronization handlers,
+/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
+/ function, must be added to the project. Samples are available in
+/ option/syscall.c.
+/
+/ The _FS_TIMEOUT defines timeout period in unit of time tick.
+/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
+/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
+/ included somewhere in the scope of ff.c. */
+
+
+/*--- End of configuration options ---*/
diff --git a/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/mmc.c b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/mmc.c
new file mode 100644
index 00000000..9a22012e
--- /dev/null
+++ b/Target/Demo/ARMCM4_XMC4_XMC4700_Relax_Kit_Keil/Boot/lib/FatFS/mmc.c
@@ -0,0 +1,217 @@
+/*------------------------------------------------------------------------/
+/ MMCv3/SDv1/SDv2 (in SDIO mode) control module
+/-------------------------------------------------------------------------/
+/
+/ Copyright (C) 2013, ChaN, all right reserved.
+/
+/ * This software is a free software and there is NO WARRANTY.
+/ * No restriction on use. You can use, modify and redistribute it for
+/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
+/ * Redistributions of source code must retain the above copyright notice.
+/
+/-------------------------------------------------------------------------*/
+
+
+/*
+ * This file was modified from a sample available from the FatFs
+ * web site. It was modified to work with a Infineon XMC4700 Relax Kit
+ * evaluation board. It is based on the DAVE 4 SDMMC_BLOCK app, which was modified
+ * to work with an existing timer and for operation in polling mode.
+ *
+ */
+#include "diskio.h"
+#include "boot.h"
+#include "sdmmc_block.h"
+
+
+static volatile
+DSTATUS Stat = STA_NOINIT; /* Disk status */
+
+const
+DRESULT FATFS_errorcodes[5] = {
+ RES_OK ,
+ RES_ERROR,
+ RES_WRPRT,
+ RES_NOTRDY,
+ RES_PARERR
+ };
+const
+DSTATUS FATFS_statuscodes[4] = {
+ (DSTATUS)0,
+ (DSTATUS)STA_NOINIT,
+ (DSTATUS)STA_NODISK,
+ (DSTATUS)STA_PROTECT
+ };
+
+/*--------------------------------------------------------------------------
+
+ Public Functions
+
+---------------------------------------------------------------------------*/
+
+
+/*-----------------------------------------------------------------------*/
+/* Initialize Disk Drive */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_initialize (
+ BYTE pdrv /* Physical drive number (0) */
+)
+{
+ DSTATUS diskstatus;
+ uint32_t status;
+
+ /* Make sure the SDMMC block is initialized. Note that it has a protection
+ * against mutiple initialization.
+ */
+ SDMMC_BLOCK_Init(&SDMMC_BLOCK_0);
+
+ /* If drive number is greater than the maximum drives allowed */
+ if (pdrv > 0)
+ {
+ diskstatus = (DSTATUS)((uint8_t)STA_NODISK | (uint8_t)STA_NOINIT);
+ }
+ else
+ {
+ /* Call the Initialize function. */
+ status = SDMMC_BLOCK_Initialize(&SDMMC_BLOCK_0);
+ /* Fatfs to Device Abstraction Layer Error Code Mapping */
+ diskstatus = FATFS_statuscodes[status];
+ }
+
+ return (diskstatus);
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Get Disk Status */
+/*-----------------------------------------------------------------------*/
+
+DSTATUS disk_status (
+ BYTE pdrv /* Physical drive nmuber (0) */
+)
+{
+ DSTATUS diskstatus;
+ uint32_t status;
+
+ /* If drive number is greater than the maximum drives allowed */
+ if (pdrv > 0)
+ {
+ diskstatus = (DSTATUS)((uint8_t)STA_NODISK | (uint8_t)STA_NOINIT);
+ }
+ else
+ {
+ /* Call the Initialize function.*/
+ status = SDMMC_BLOCK_GetStatus(&SDMMC_BLOCK_0);
+ /* Fatfs to Block Layer Error Code Mapping */
+ diskstatus = FATFS_statuscodes[status];
+ }
+ return (diskstatus);
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Read Sector(s) */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_read (
+ BYTE pdrv, /* Physical drive nmuber to identify the drive */
+ BYTE *buff, /* Data buffer to store read data */
+ DWORD sector, /* Sector address in LBA */
+ UINT count /* Number of sectors to read */
+)
+{
+ DRESULT diskresult;
+ uint32_t result;
+
+ /* If drive number is greater than the maximum drives allowed */
+ if (pdrv > 0)
+ {
+ diskresult = RES_PARERR;
+ }
+ /* If sector count is less than 1. Minimum 1 sector is needed*/
+ else if (count < (uint8_t)1)
+ {
+ diskresult = RES_PARERR;
+ }
+ /*Call the ReadBlk function.*/
+ else
+ {
+ result = (uint32_t)SDMMC_BLOCK_ReadBlock(&SDMMC_BLOCK_0, (uint8_t *)buff,
+ (uint32_t)sector, count);
+
+ /* FatFs to Device Abstraction Layer Error Code Mapping */
+ diskresult = FATFS_errorcodes[result];
+ }
+ return (diskresult);
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Write Sector(s) */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_write (
+ BYTE pdrv, /* Physical drive nmuber to identify the drive */
+ const BYTE *buff, /* Data to be written */
+ DWORD sector, /* Sector address in LBA */
+ UINT count /* Number of sectors to write */
+)
+{
+ DRESULT diskresult;
+ uint32_t result;
+
+ /* If drive number is greater than the maximum drives allowed */
+ if (pdrv > 0)
+ {
+ diskresult = RES_PARERR;
+ }
+ /* If sector count is less than 1. Minimum 1 sector is needed*/
+ else if (count < (uint8_t)1)
+ {
+ diskresult = RES_PARERR;
+ }
+ /*Call the WriteBlk function.*/
+ else
+ {
+ result = (uint32_t)SDMMC_BLOCK_WriteBlock(&SDMMC_BLOCK_0,(uint8_t *)buff,
+ (uint32_t)sector, count);
+ /* FatFs to Device Abstraction Layer Error Code Mapping */
+ diskresult = FATFS_errorcodes[result];
+ }
+ return (diskresult);
+}
+
+
+
+/*-----------------------------------------------------------------------*/
+/* Miscellaneous Functions */
+/*-----------------------------------------------------------------------*/
+
+DRESULT disk_ioctl (
+ BYTE pdrv, /* Physical drive nmuber (0) */
+ BYTE cmd, /* Control code */
+ void *buff /* Buffer to send/receive data block */
+)
+{
+ DRESULT diskresult;
+ uint32_t result;
+ if (pdrv > 0)
+ {
+ diskresult = RES_PARERR;
+ }
+ /*Call the Ioctl function.*/
+ else
+ {
+ result = SDMMC_BLOCK_Ioctl(&SDMMC_BLOCK_0, cmd, buff);
+ /* FatFs to Block Layer Error Code Mapping */
+ diskresult = FATFS_errorcodes[result];
+ }
+ return (diskresult);
+}
+
+
+