STM32H735xx HAL User Manual
stm32h7xx_hal_mmc.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32h7xx_hal_mmc.c
00004   * @author  MCD Application Team
00005   * @brief   MMC card HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Secure Digital (MMC) peripheral:
00008   *           + Initialization and de-initialization functions
00009   *           + IO operation functions
00010   *           + Peripheral Control functions
00011   *           + MMC card Control functions
00012   *
00013   ******************************************************************************
00014   * @attention
00015   *
00016   * Copyright (c) 2017 STMicroelectronics.
00017   * All rights reserved.
00018   *
00019   * This software is licensed under terms that can be found in the LICENSE file
00020   * in the root directory of this software component.
00021   * If no LICENSE file comes with this software, it is provided AS-IS.
00022   *
00023   ******************************************************************************
00024   @verbatim
00025   ==============================================================================
00026                         ##### How to use this driver #####
00027   ==============================================================================
00028   [..]
00029     This driver implements a high level communication layer for read and write from/to
00030     this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
00031     the user in HAL_MMC_MspInit() function (MSP layer).
00032     Basically, the MSP layer configuration should be the same as we provide in the
00033     examples.
00034     You can easily tailor this configuration according to hardware resources.
00035 
00036   [..]
00037     This driver is a generic layered driver for SDMMC memories which uses the HAL
00038     SDMMC driver functions to interface with MMC and eMMC cards devices.
00039     It is used as follows:
00040 
00041     (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
00042         (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
00043         (##) SDMMC pins configuration for MMC card
00044             (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
00045             (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
00046                   and according to your pin assignment;
00047         (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
00048              and HAL_MMC_WriteBlocks_IT() APIs).
00049             (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
00050             (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
00051             (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
00052                   and __HAL_MMC_DISABLE_IT() inside the communication process.
00053             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
00054                   and __HAL_MMC_CLEAR_IT()
00055         (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used.
00056 
00057     (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
00058 
00059 
00060   *** MMC Card Initialization and configuration ***
00061   ================================================
00062   [..]
00063     To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
00064     SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
00065     This function provide the following operations:
00066 
00067     (#) Initialize the SDMMC peripheral interface with defaullt configuration.
00068         The initialization process is done at 400KHz. You can change or adapt
00069         this frequency by adjusting the "ClockDiv" field.
00070         The MMC Card frequency (SDMMC_CK) is computed as follows:
00071 
00072            SDMMC_CK = SDMMCCLK / (2 * ClockDiv)
00073 
00074         In initialization mode and according to the MMC Card standard,
00075         make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
00076 
00077         This phase of initialization is done through SDMMC_Init() and
00078         SDMMC_PowerState_ON() SDMMC low level APIs.
00079 
00080     (#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
00081         This phase allows the card initialization and identification
00082         and check the MMC Card type (Standard Capacity or High Capacity)
00083         The initialization flow is compatible with MMC standard.
00084 
00085         This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
00086         of plug-off plug-in.
00087 
00088     (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
00089         frequency by adjusting the "ClockDiv" field.
00090         In transfer mode and according to the MMC Card standard, make sure that the
00091         SDMMC_CK frequency doesn't exceed 25MHz and 100MHz in High-speed mode switch.
00092 
00093     (#) Select the corresponding MMC Card according to the address read with the step 2.
00094 
00095     (#) Configure the MMC Card in wide bus mode: 4-bits data.
00096 
00097   *** MMC Card Read operation ***
00098   ==============================
00099   [..]
00100     (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
00101         This function support only 512-bytes block length (the block size should be
00102         chosen as 512 bytes).
00103         You can choose either one block read operation or multiple block read operation
00104         by adjusting the "NumberOfBlocks" parameter.
00105         After this, you have to ensure that the transfer is done correctly. The check is done
00106         through HAL_MMC_GetCardState() function for MMC card state.
00107 
00108     (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
00109         This function support only 512-bytes block length (the block size should be
00110         chosen as 512 bytes).
00111         You can choose either one block read operation or multiple block read operation
00112         by adjusting the "NumberOfBlocks" parameter.
00113         After this, you have to ensure that the transfer is done correctly. The check is done
00114         through HAL_MMC_GetCardState() function for MMC card state.
00115         You could also check the DMA transfer process through the MMC Rx interrupt event.
00116 
00117     (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
00118         This function allows the read of 512 bytes blocks.
00119         You can choose either one block read operation or multiple block read operation
00120         by adjusting the "NumberOfBlocks" parameter.
00121         After this, you have to ensure that the transfer is done correctly. The check is done
00122         through HAL_MMC_GetCardState() function for MMC card state.
00123         You could also check the IT transfer process through the MMC Rx interrupt event.
00124 
00125   *** MMC Card Write operation ***
00126   ===============================
00127   [..]
00128     (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
00129         This function support only 512-bytes block length (the block size should be
00130         chosen as 512 bytes).
00131         You can choose either one block read operation or multiple block read operation
00132         by adjusting the "NumberOfBlocks" parameter.
00133         After this, you have to ensure that the transfer is done correctly. The check is done
00134         through HAL_MMC_GetCardState() function for MMC card state.
00135 
00136     (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
00137         This function support only 512-bytes block length (the block size should be
00138         chosen as 512 byte).
00139         You can choose either one block read operation or multiple block read operation
00140         by adjusting the "NumberOfBlocks" parameter.
00141         After this, you have to ensure that the transfer is done correctly. The check is done
00142         through HAL_MMC_GetCardState() function for MMC card state.
00143         You could also check the DMA transfer process through the MMC Tx interrupt event.
00144 
00145     (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
00146         This function allows the read of 512 bytes blocks.
00147         You can choose either one block read operation or multiple block read operation
00148         by adjusting the "NumberOfBlocks" parameter.
00149         After this, you have to ensure that the transfer is done correctly. The check is done
00150         through HAL_MMC_GetCardState() function for MMC card state.
00151         You could also check the IT transfer process through the MMC Tx interrupt event.
00152 
00153   *** MMC card information ***
00154   ===========================
00155   [..]
00156     (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
00157         It returns useful information about the MMC card such as block size, card type,
00158         block number ...
00159 
00160   *** MMC card CSD register ***
00161   ============================
00162   [..]
00163     (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
00164         Some of the CSD parameters are useful for card initialization and identification.
00165 
00166   *** MMC card CID register ***
00167   ============================
00168   [..]
00169     (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
00170         Some of the CID parameters are useful for card initialization and identification.
00171 
00172   *** MMC HAL driver macros list ***
00173   ==================================
00174   [..]
00175     Below the list of most used macros in MMC HAL driver.
00176 
00177     (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
00178     (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
00179     (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
00180     (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
00181 
00182   [..]
00183     (@) You can refer to the MMC HAL driver header file for more useful macros
00184 
00185   *** Callback registration ***
00186   =============================================
00187   [..]
00188     The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
00189     allows the user to configure dynamically the driver callbacks.
00190 
00191     Use Functions HAL_MMC_RegisterCallback() to register a user callback,
00192     it allows to register following callbacks:
00193       (+) TxCpltCallback : callback when a transmission transfer is completed.
00194       (+) RxCpltCallback : callback when a reception transfer is completed.
00195       (+) ErrorCallback : callback when error occurs.
00196       (+) AbortCpltCallback : callback when abort is completed.
00197       (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
00198       (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
00199       (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
00200       (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
00201       (+) MspInitCallback    : MMC MspInit.
00202       (+) MspDeInitCallback  : MMC MspDeInit.
00203     This function takes as parameters the HAL peripheral handle, the Callback ID
00204     and a pointer to the user callback function.
00205 
00206     Use function HAL_MMC_UnRegisterCallback() to reset a callback to the default
00207     weak (surcharged) function. It allows to reset following callbacks:
00208       (+) TxCpltCallback : callback when a transmission transfer is completed.
00209       (+) RxCpltCallback : callback when a reception transfer is completed.
00210       (+) ErrorCallback : callback when error occurs.
00211       (+) AbortCpltCallback : callback when abort is completed.
00212       (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
00213       (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
00214       (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
00215       (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
00216       (+) MspInitCallback    : MMC MspInit.
00217       (+) MspDeInitCallback  : MMC MspDeInit.
00218     This function) takes as parameters the HAL peripheral handle and the Callback ID.
00219 
00220     By default, after the HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
00221     all callbacks are reset to the corresponding legacy weak (surcharged) functions.
00222     Exception done for MspInit and MspDeInit callbacks that are respectively
00223     reset to the legacy weak (surcharged) functions in the HAL_MMC_Init
00224     and HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
00225     If not, MspInit or MspDeInit are not null, the HAL_MMC_Init and HAL_MMC_DeInit
00226     keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
00227 
00228     Callbacks can be registered/unregistered in READY state only.
00229     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
00230     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
00231     during the Init/DeInit.
00232     In that case first register the MspInit/MspDeInit user callbacks
00233     using HAL_MMC_RegisterCallback before calling HAL_MMC_DeInit
00234     or HAL_MMC_Init function.
00235 
00236     When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
00237     not defined, the callback registering feature is not available
00238     and weak (surcharged) callbacks are used.
00239 
00240   @endverbatim
00241   ******************************************************************************
00242   */
00243 
00244 /* Includes ------------------------------------------------------------------*/
00245 #include "stm32h7xx_hal.h"
00246 
00247 /** @addtogroup STM32H7xx_HAL_Driver
00248   * @{
00249   */
00250 
00251 /** @defgroup MMC MMC
00252   * @brief MMC HAL module driver
00253   * @{
00254   */
00255 
00256 #ifdef HAL_MMC_MODULE_ENABLED
00257 
00258 /* Private typedef -----------------------------------------------------------*/
00259 /* Private define ------------------------------------------------------------*/
00260 /** @addtogroup MMC_Private_Defines
00261   * @{
00262   */
00263 #if defined (VDD_VALUE) && (VDD_VALUE <= 1950U)
00264 #define MMC_VOLTAGE_RANGE               EMMC_LOW_VOLTAGE_RANGE
00265 
00266 #define MMC_EXT_CSD_PWR_CL_26_INDEX     201
00267 #define MMC_EXT_CSD_PWR_CL_52_INDEX     200
00268 #define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238
00269 
00270 #define MMC_EXT_CSD_PWR_CL_26_POS       8
00271 #define MMC_EXT_CSD_PWR_CL_52_POS       0
00272 #define MMC_EXT_CSD_PWR_CL_DDR_52_POS   16
00273 #else
00274 #define MMC_VOLTAGE_RANGE               EMMC_HIGH_VOLTAGE_RANGE
00275 
00276 #define MMC_EXT_CSD_PWR_CL_26_INDEX     203
00277 #define MMC_EXT_CSD_PWR_CL_52_INDEX     202
00278 #define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239
00279 
00280 #define MMC_EXT_CSD_PWR_CL_26_POS       24
00281 #define MMC_EXT_CSD_PWR_CL_52_POS       16
00282 #define MMC_EXT_CSD_PWR_CL_DDR_52_POS   24
00283 #endif /* (VDD_VALUE) && (VDD_VALUE <= 1950U)*/
00284 
00285 #define MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_INDEX 216
00286 #define MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_POS   0
00287 #define MMC_EXT_CSD_S_A_TIMEOUT_INDEX             217
00288 #define MMC_EXT_CSD_S_A_TIMEOUT_POS               8
00289 
00290 /* Frequencies used in the driver for clock divider calculation */
00291 #define MMC_INIT_FREQ                   400000U   /* Initialization phase : 400 kHz max */
00292 #define MMC_HIGH_SPEED_FREQ             52000000U /* High speed phase : 52 MHz max */
00293 /**
00294   * @}
00295   */
00296 
00297 /* Private macro -------------------------------------------------------------*/
00298 /* Private variables ---------------------------------------------------------*/
00299 /* Private function prototypes -----------------------------------------------*/
00300 /* Private functions ---------------------------------------------------------*/
00301 /** @defgroup MMC_Private_Functions MMC Private Functions
00302   * @{
00303   */
00304 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
00305 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
00306 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
00307 static void     MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
00308 static void     MMC_Write_IT(MMC_HandleTypeDef *hmmc);
00309 static void     MMC_Read_IT(MMC_HandleTypeDef *hmmc);
00310 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state);
00311 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state);
00312 static HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex,
00313                                         uint32_t Timeout);
00314 static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide, uint32_t Speed);
00315 
00316 /**
00317   * @}
00318   */
00319 /* Exported functions --------------------------------------------------------*/
00320 /** @addtogroup MMC_Exported_Functions
00321   * @{
00322   */
00323 
00324 /** @addtogroup MMC_Exported_Functions_Group1
00325   *  @brief   Initialization and de-initialization functions
00326   *
00327 @verbatim
00328   ==============================================================================
00329           ##### Initialization and de-initialization functions #####
00330   ==============================================================================
00331   [..]
00332     This section provides functions allowing to initialize/de-initialize the MMC
00333     card device to be ready for use.
00334 
00335 @endverbatim
00336   * @{
00337   */
00338 
00339 /**
00340   * @brief  Initializes the MMC according to the specified parameters in the
00341             MMC_HandleTypeDef and create the associated handle.
00342   * @param  hmmc: Pointer to the MMC handle
00343   * @retval HAL status
00344   */
00345 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
00346 {
00347   /* Check the MMC handle allocation */
00348   if (hmmc == NULL)
00349   {
00350     return HAL_ERROR;
00351   }
00352 
00353   /* Check the parameters */
00354   assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
00355   assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge));
00356   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
00357   assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide));
00358   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
00359   assert_param(IS_SDMMC_CLKDIV(hmmc->Init.ClockDiv));
00360 
00361   if (hmmc->State == HAL_MMC_STATE_RESET)
00362   {
00363     /* Allocate lock resource and initialize it */
00364     hmmc->Lock = HAL_UNLOCKED;
00365 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
00366     /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
00367     hmmc->TxCpltCallback    = HAL_MMC_TxCpltCallback;
00368     hmmc->RxCpltCallback    = HAL_MMC_RxCpltCallback;
00369     hmmc->ErrorCallback     = HAL_MMC_ErrorCallback;
00370     hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
00371     hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback;
00372     hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback;
00373     hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback;
00374     hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback;
00375 
00376     if (hmmc->MspInitCallback == NULL)
00377     {
00378       hmmc->MspInitCallback = HAL_MMC_MspInit;
00379     }
00380 
00381     /* Init the low level hardware */
00382     hmmc->MspInitCallback(hmmc);
00383 #else
00384     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
00385     HAL_MMC_MspInit(hmmc);
00386 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
00387   }
00388 
00389   hmmc->State = HAL_MMC_STATE_BUSY;
00390 
00391   /* Initialize the Card parameters */
00392   if (HAL_MMC_InitCard(hmmc) == HAL_ERROR)
00393   {
00394     return HAL_ERROR;
00395   }
00396 
00397   /* Initialize the error code */
00398   hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
00399 
00400   /* Initialize the MMC operation */
00401   hmmc->Context = MMC_CONTEXT_NONE;
00402 
00403   /* Initialize the MMC state */
00404   hmmc->State = HAL_MMC_STATE_READY;
00405 
00406   /* Configure bus width */
00407   if (hmmc->Init.BusWide != SDMMC_BUS_WIDE_1B)
00408   {
00409     if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK)
00410     {
00411       return HAL_ERROR;
00412     }
00413   }
00414 
00415   return HAL_OK;
00416 }
00417 
00418 /**
00419   * @brief  Initializes the MMC Card.
00420   * @param  hmmc: Pointer to MMC handle
00421   * @note   This function initializes the MMC card. It could be used when a card
00422             re-initialization is needed.
00423   * @retval HAL status
00424   */
00425 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
00426 {
00427   uint32_t errorstate;
00428   MMC_InitTypeDef Init;
00429   uint32_t sdmmc_clk;
00430 
00431   /* Default SDMMC peripheral configuration for MMC card initialization */
00432   Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
00433   Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
00434   Init.BusWide             = SDMMC_BUS_WIDE_1B;
00435   Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
00436 
00437   /* Init Clock should be less or equal to 400Khz*/
00438   sdmmc_clk     = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
00439   if (sdmmc_clk == 0U)
00440   {
00441     hmmc->State = HAL_MMC_STATE_READY;
00442     hmmc->ErrorCode = SDMMC_ERROR_INVALID_PARAMETER;
00443     return HAL_ERROR;
00444   }
00445   Init.ClockDiv = sdmmc_clk / (2U * MMC_INIT_FREQ);
00446 
00447 #if (USE_SD_TRANSCEIVER != 0U)
00448   Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
00449 #endif /* USE_SD_TRANSCEIVER */
00450 
00451   /* Initialize SDMMC peripheral interface with default configuration */
00452   (void)SDMMC_Init(hmmc->Instance, Init);
00453 
00454   /* Set Power State to ON */
00455   (void)SDMMC_PowerState_ON(hmmc->Instance);
00456 
00457   /* wait 74 Cycles: required power up waiting time before starting
00458      the MMC initialization sequence */
00459   sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv);
00460   HAL_Delay(1U + (74U * 1000U / (sdmmc_clk)));
00461 
00462   /* Identify card operating voltage */
00463   errorstate = MMC_PowerON(hmmc);
00464   if (errorstate != HAL_MMC_ERROR_NONE)
00465   {
00466     hmmc->State = HAL_MMC_STATE_READY;
00467     hmmc->ErrorCode |= errorstate;
00468     return HAL_ERROR;
00469   }
00470 
00471   /* Card initialization */
00472   errorstate = MMC_InitCard(hmmc);
00473   if (errorstate != HAL_MMC_ERROR_NONE)
00474   {
00475     hmmc->State = HAL_MMC_STATE_READY;
00476     hmmc->ErrorCode |= errorstate;
00477     return HAL_ERROR;
00478   }
00479 
00480   /* Set Block Size for Card */
00481   errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
00482   if (errorstate != HAL_MMC_ERROR_NONE)
00483   {
00484     /* Clear all the static flags */
00485     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00486     hmmc->ErrorCode |= errorstate;
00487     hmmc->State = HAL_MMC_STATE_READY;
00488     return HAL_ERROR;
00489   }
00490 
00491   return HAL_OK;
00492 }
00493 
00494 /**
00495   * @brief  De-Initializes the MMC card.
00496   * @param  hmmc: Pointer to MMC handle
00497   * @retval HAL status
00498   */
00499 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
00500 {
00501   /* Check the MMC handle allocation */
00502   if (hmmc == NULL)
00503   {
00504     return HAL_ERROR;
00505   }
00506 
00507   /* Check the parameters */
00508   assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
00509 
00510   hmmc->State = HAL_MMC_STATE_BUSY;
00511 
00512   /* Set MMC power state to off */
00513   MMC_PowerOFF(hmmc);
00514 
00515 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
00516   if (hmmc->MspDeInitCallback == NULL)
00517   {
00518     hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
00519   }
00520 
00521   /* DeInit the low level hardware */
00522   hmmc->MspDeInitCallback(hmmc);
00523 #else
00524   /* De-Initialize the MSP layer */
00525   HAL_MMC_MspDeInit(hmmc);
00526 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
00527 
00528   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
00529   hmmc->State = HAL_MMC_STATE_RESET;
00530 
00531   return HAL_OK;
00532 }
00533 
00534 
00535 /**
00536   * @brief  Initializes the MMC MSP.
00537   * @param  hmmc: Pointer to MMC handle
00538   * @retval None
00539   */
00540 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
00541 {
00542   /* Prevent unused argument(s) compilation warning */
00543   UNUSED(hmmc);
00544 
00545   /* NOTE : This function Should not be modified, when the callback is needed,
00546             the HAL_MMC_MspInit could be implemented in the user file
00547    */
00548 }
00549 
00550 /**
00551   * @brief  De-Initialize MMC MSP.
00552   * @param  hmmc: Pointer to MMC handle
00553   * @retval None
00554   */
00555 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
00556 {
00557   /* Prevent unused argument(s) compilation warning */
00558   UNUSED(hmmc);
00559 
00560   /* NOTE : This function Should not be modified, when the callback is needed,
00561             the HAL_MMC_MspDeInit could be implemented in the user file
00562    */
00563 }
00564 
00565 /**
00566   * @}
00567   */
00568 
00569 /** @addtogroup MMC_Exported_Functions_Group2
00570   *  @brief   Data transfer functions
00571   *
00572 @verbatim
00573   ==============================================================================
00574                         ##### IO operation functions #####
00575   ==============================================================================
00576   [..]
00577     This subsection provides a set of functions allowing to manage the data
00578     transfer from/to MMC card.
00579 
00580 @endverbatim
00581   * @{
00582   */
00583 
00584 /**
00585   * @brief  Reads block(s) from a specified address in a card. The Data transfer
00586   *         is managed by polling mode.
00587   * @note   This API should be followed by a check on the card state through
00588   *         HAL_MMC_GetCardState().
00589   * @param  hmmc: Pointer to MMC handle
00590   * @param  pData: pointer to the buffer that will contain the received data
00591   * @param  BlockAdd: Block Address from where data is to be read
00592   * @param  NumberOfBlocks: Number of MMC blocks to read
00593   * @param  Timeout: Specify timeout value
00594   * @retval HAL status
00595   */
00596 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd,
00597                                      uint32_t NumberOfBlocks, uint32_t Timeout)
00598 {
00599   SDMMC_DataInitTypeDef config;
00600   uint32_t errorstate;
00601   uint32_t tickstart = HAL_GetTick();
00602   uint32_t count;
00603   uint32_t data;
00604   uint32_t dataremaining;
00605   uint32_t add = BlockAdd;
00606   uint8_t *tempbuff = pData;
00607 
00608   if (NULL == pData)
00609   {
00610     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00611     return HAL_ERROR;
00612   }
00613 
00614   if (hmmc->State == HAL_MMC_STATE_READY)
00615   {
00616     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
00617 
00618     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00619     {
00620       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00621       return HAL_ERROR;
00622     }
00623 
00624     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
00625     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS)
00626          & 0x000000FFU) != 0x0U)
00627     {
00628       if ((NumberOfBlocks % 8U) != 0U)
00629       {
00630         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
00631         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
00632         return HAL_ERROR;
00633       }
00634 
00635       if ((BlockAdd % 8U) != 0U)
00636       {
00637         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
00638         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
00639         return HAL_ERROR;
00640       }
00641     }
00642 
00643     hmmc->State = HAL_MMC_STATE_BUSY;
00644 
00645     /* Initialize data control register */
00646     hmmc->Instance->DCTRL = 0U;
00647 
00648     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
00649     {
00650       add *= 512U;
00651     }
00652 
00653     /* Configure the MMC DPSM (Data Path State Machine) */
00654     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00655     config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
00656     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
00657     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
00658     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
00659     config.DPSM          = SDMMC_DPSM_DISABLE;
00660     (void)SDMMC_ConfigData(hmmc->Instance, &config);
00661     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
00662 
00663     /* Read block(s) in polling mode */
00664     if (NumberOfBlocks > 1U)
00665     {
00666       hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
00667 
00668       /* Read Multi Block command */
00669       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
00670     }
00671     else
00672     {
00673       hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
00674 
00675       /* Read Single Block command */
00676       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
00677     }
00678     if (errorstate != HAL_MMC_ERROR_NONE)
00679     {
00680       /* Clear all the static flags */
00681       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00682       hmmc->ErrorCode |= errorstate;
00683       hmmc->State = HAL_MMC_STATE_READY;
00684       return HAL_ERROR;
00685     }
00686 
00687     /* Poll on SDMMC flags */
00688     dataremaining = config.DataLength;
00689     while (!__HAL_MMC_GET_FLAG(hmmc,
00690                                SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
00691     {
00692       if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
00693       {
00694         /* Read data from SDMMC Rx FIFO */
00695         for (count = 0U; count < 8U; count++)
00696         {
00697           data = SDMMC_ReadFIFO(hmmc->Instance);
00698           *tempbuff = (uint8_t)(data & 0xFFU);
00699           tempbuff++;
00700           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
00701           tempbuff++;
00702           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
00703           tempbuff++;
00704           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
00705           tempbuff++;
00706         }
00707         dataremaining -= 32U;
00708       }
00709 
00710       if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
00711       {
00712         /* Clear all the static flags */
00713         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00714         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
00715         hmmc->State = HAL_MMC_STATE_READY;
00716         return HAL_TIMEOUT;
00717       }
00718     }
00719     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
00720 
00721     /* Send stop transmission command in case of multiblock read */
00722     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
00723     {
00724       /* Send stop transmission command */
00725       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
00726       if (errorstate != HAL_MMC_ERROR_NONE)
00727       {
00728         /* Clear all the static flags */
00729         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00730         hmmc->ErrorCode |= errorstate;
00731         hmmc->State = HAL_MMC_STATE_READY;
00732         return HAL_ERROR;
00733       }
00734     }
00735 
00736     /* Get error state */
00737     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
00738     {
00739       /* Clear all the static flags */
00740       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00741       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
00742       hmmc->State = HAL_MMC_STATE_READY;
00743       return HAL_ERROR;
00744     }
00745     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
00746     {
00747       /* Clear all the static flags */
00748       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00749       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
00750       hmmc->State = HAL_MMC_STATE_READY;
00751       return HAL_ERROR;
00752     }
00753     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
00754     {
00755       /* Clear all the static flags */
00756       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00757       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
00758       hmmc->State = HAL_MMC_STATE_READY;
00759       return HAL_ERROR;
00760     }
00761     else
00762     {
00763       /* Nothing to do */
00764     }
00765 
00766     /* Clear all the static flags */
00767     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
00768 
00769     hmmc->State = HAL_MMC_STATE_READY;
00770 
00771     return HAL_OK;
00772   }
00773   else
00774   {
00775     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
00776     return HAL_ERROR;
00777   }
00778 }
00779 
00780 /**
00781   * @brief  Allows to write block(s) to a specified address in a card. The Data
00782   *         transfer is managed by polling mode.
00783   * @note   This API should be followed by a check on the card state through
00784   *         HAL_MMC_GetCardState().
00785   * @param  hmmc: Pointer to MMC handle
00786   * @param  pData: pointer to the buffer that will contain the data to transmit
00787   * @param  BlockAdd: Block Address where data will be written
00788   * @param  NumberOfBlocks: Number of MMC blocks to write
00789   * @param  Timeout: Specify timeout value
00790   * @retval HAL status
00791   */
00792 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd,
00793                                       uint32_t NumberOfBlocks, uint32_t Timeout)
00794 {
00795   SDMMC_DataInitTypeDef config;
00796   uint32_t errorstate;
00797   uint32_t tickstart = HAL_GetTick();
00798   uint32_t count;
00799   uint32_t data;
00800   uint32_t dataremaining;
00801   uint32_t add = BlockAdd;
00802   uint8_t *tempbuff = pData;
00803 
00804   if (NULL == pData)
00805   {
00806     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00807     return HAL_ERROR;
00808   }
00809 
00810   if (hmmc->State == HAL_MMC_STATE_READY)
00811   {
00812     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
00813 
00814     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00815     {
00816       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00817       return HAL_ERROR;
00818     }
00819 
00820     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
00821     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
00822     {
00823       if ((NumberOfBlocks % 8U) != 0U)
00824       {
00825         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
00826         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
00827         return HAL_ERROR;
00828       }
00829 
00830       if ((BlockAdd % 8U) != 0U)
00831       {
00832         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
00833         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
00834         return HAL_ERROR;
00835       }
00836     }
00837 
00838     hmmc->State = HAL_MMC_STATE_BUSY;
00839 
00840     /* Initialize data control register */
00841     hmmc->Instance->DCTRL = 0U;
00842 
00843     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
00844     {
00845       add *= 512U;
00846     }
00847 
00848     /* Configure the MMC DPSM (Data Path State Machine) */
00849     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00850     config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
00851     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
00852     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
00853     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
00854     config.DPSM          = SDMMC_DPSM_DISABLE;
00855     (void)SDMMC_ConfigData(hmmc->Instance, &config);
00856     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
00857 
00858     /* Write Blocks in Polling mode */
00859     if (NumberOfBlocks > 1U)
00860     {
00861       hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
00862 
00863       /* Write Multi Block command */
00864       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
00865     }
00866     else
00867     {
00868       hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
00869 
00870       /* Write Single Block command */
00871       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
00872     }
00873     if (errorstate != HAL_MMC_ERROR_NONE)
00874     {
00875       /* Clear all the static flags */
00876       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00877       hmmc->ErrorCode |= errorstate;
00878       hmmc->State = HAL_MMC_STATE_READY;
00879       return HAL_ERROR;
00880     }
00881 
00882     /* Write block(s) in polling mode */
00883     dataremaining = config.DataLength;
00884     while (!__HAL_MMC_GET_FLAG(hmmc,
00885                                SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
00886     {
00887       if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
00888       {
00889         /* Write data to SDMMC Tx FIFO */
00890         for (count = 0U; count < 8U; count++)
00891         {
00892           data = (uint32_t)(*tempbuff);
00893           tempbuff++;
00894           data |= ((uint32_t)(*tempbuff) << 8U);
00895           tempbuff++;
00896           data |= ((uint32_t)(*tempbuff) << 16U);
00897           tempbuff++;
00898           data |= ((uint32_t)(*tempbuff) << 24U);
00899           tempbuff++;
00900           (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
00901         }
00902         dataremaining -= 32U;
00903       }
00904 
00905       if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
00906       {
00907         /* Clear all the static flags */
00908         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00909         hmmc->ErrorCode |= errorstate;
00910         hmmc->State = HAL_MMC_STATE_READY;
00911         return HAL_TIMEOUT;
00912       }
00913     }
00914     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
00915 
00916     /* Send stop transmission command in case of multiblock write */
00917     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
00918     {
00919       /* Send stop transmission command */
00920       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
00921       if (errorstate != HAL_MMC_ERROR_NONE)
00922       {
00923         /* Clear all the static flags */
00924         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00925         hmmc->ErrorCode |= errorstate;
00926         hmmc->State = HAL_MMC_STATE_READY;
00927         return HAL_ERROR;
00928       }
00929     }
00930 
00931     /* Get error state */
00932     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
00933     {
00934       /* Clear all the static flags */
00935       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00936       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
00937       hmmc->State = HAL_MMC_STATE_READY;
00938       return HAL_ERROR;
00939     }
00940     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
00941     {
00942       /* Clear all the static flags */
00943       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00944       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
00945       hmmc->State = HAL_MMC_STATE_READY;
00946       return HAL_ERROR;
00947     }
00948     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR))
00949     {
00950       /* Clear all the static flags */
00951       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00952       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
00953       hmmc->State = HAL_MMC_STATE_READY;
00954       return HAL_ERROR;
00955     }
00956     else
00957     {
00958       /* Nothing to do */
00959     }
00960 
00961     /* Clear all the static flags */
00962     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
00963 
00964     hmmc->State = HAL_MMC_STATE_READY;
00965 
00966     return HAL_OK;
00967   }
00968   else
00969   {
00970     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
00971     return HAL_ERROR;
00972   }
00973 }
00974 
00975 /**
00976   * @brief  Reads block(s) from a specified address in a card. The Data transfer
00977   *         is managed in interrupt mode.
00978   * @note   This API should be followed by a check on the card state through
00979   *         HAL_MMC_GetCardState().
00980   * @note   You could also check the IT transfer process through the MMC Rx
00981   *         interrupt event.
00982   * @param  hmmc: Pointer to MMC handle
00983   * @param  pData: Pointer to the buffer that will contain the received data
00984   * @param  BlockAdd: Block Address from where data is to be read
00985   * @param  NumberOfBlocks: Number of blocks to read.
00986   * @retval HAL status
00987   */
00988 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData,
00989                                         uint32_t BlockAdd, uint32_t NumberOfBlocks)
00990 {
00991   SDMMC_DataInitTypeDef config;
00992   uint32_t errorstate;
00993   uint32_t add = BlockAdd;
00994 
00995   if (NULL == pData)
00996   {
00997     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00998     return HAL_ERROR;
00999   }
01000 
01001   if (hmmc->State == HAL_MMC_STATE_READY)
01002   {
01003     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
01004 
01005     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
01006     {
01007       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01008       return HAL_ERROR;
01009     }
01010 
01011     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
01012     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
01013     {
01014       if ((NumberOfBlocks % 8U) != 0U)
01015       {
01016         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
01017         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
01018         return HAL_ERROR;
01019       }
01020 
01021       if ((BlockAdd % 8U) != 0U)
01022       {
01023         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
01024         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
01025         return HAL_ERROR;
01026       }
01027     }
01028 
01029     hmmc->State = HAL_MMC_STATE_BUSY;
01030 
01031     /* Initialize data control register */
01032     hmmc->Instance->DCTRL = 0U;
01033 
01034     hmmc->pRxBuffPtr = pData;
01035     hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
01036 
01037     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
01038     {
01039       add *= 512U;
01040     }
01041 
01042     /* Configure the MMC DPSM (Data Path State Machine) */
01043     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01044     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
01045     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
01046     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
01047     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
01048     config.DPSM          = SDMMC_DPSM_DISABLE;
01049     (void)SDMMC_ConfigData(hmmc->Instance, &config);
01050     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
01051 
01052     /* Read Blocks in IT mode */
01053     if (NumberOfBlocks > 1U)
01054     {
01055       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
01056 
01057       /* Read Multi Block command */
01058       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
01059     }
01060     else
01061     {
01062       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
01063 
01064       /* Read Single Block command */
01065       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
01066     }
01067 
01068     if (errorstate != HAL_MMC_ERROR_NONE)
01069     {
01070       /* Clear all the static flags */
01071       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01072       hmmc->ErrorCode |= errorstate;
01073       hmmc->State = HAL_MMC_STATE_READY;
01074       return HAL_ERROR;
01075     }
01076 
01077     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND |
01078                                SDMMC_FLAG_RXFIFOHF));
01079 
01080     return HAL_OK;
01081   }
01082   else
01083   {
01084     return HAL_BUSY;
01085   }
01086 }
01087 
01088 /**
01089   * @brief  Writes block(s) to a specified address in a card. The Data transfer
01090   *         is managed in interrupt mode.
01091   * @note   This API should be followed by a check on the card state through
01092   *         HAL_MMC_GetCardState().
01093   * @note   You could also check the IT transfer process through the MMC Tx
01094   *         interrupt event.
01095   * @param  hmmc: Pointer to MMC handle
01096   * @param  pData: Pointer to the buffer that will contain the data to transmit
01097   * @param  BlockAdd: Block Address where data will be written
01098   * @param  NumberOfBlocks: Number of blocks to write
01099   * @retval HAL status
01100   */
01101 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData,
01102                                          uint32_t BlockAdd, uint32_t NumberOfBlocks)
01103 {
01104   SDMMC_DataInitTypeDef config;
01105   uint32_t errorstate;
01106   uint32_t add = BlockAdd;
01107 
01108   if (NULL == pData)
01109   {
01110     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01111     return HAL_ERROR;
01112   }
01113 
01114   if (hmmc->State == HAL_MMC_STATE_READY)
01115   {
01116     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
01117 
01118     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
01119     {
01120       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01121       return HAL_ERROR;
01122     }
01123 
01124     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
01125     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
01126     {
01127       if ((NumberOfBlocks % 8U) != 0U)
01128       {
01129         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
01130         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
01131         return HAL_ERROR;
01132       }
01133 
01134       if ((BlockAdd % 8U) != 0U)
01135       {
01136         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
01137         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
01138         return HAL_ERROR;
01139       }
01140     }
01141 
01142     hmmc->State = HAL_MMC_STATE_BUSY;
01143 
01144     /* Initialize data control register */
01145     hmmc->Instance->DCTRL = 0U;
01146 
01147     hmmc->pTxBuffPtr = pData;
01148     hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
01149 
01150     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
01151     {
01152       add *= 512U;
01153     }
01154 
01155     /* Configure the MMC DPSM (Data Path State Machine) */
01156     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01157     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
01158     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
01159     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
01160     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
01161     config.DPSM          = SDMMC_DPSM_DISABLE;
01162     (void)SDMMC_ConfigData(hmmc->Instance, &config);
01163 
01164     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
01165 
01166     /* Write Blocks in Polling mode */
01167     if (NumberOfBlocks > 1U)
01168     {
01169       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
01170 
01171       /* Write Multi Block command */
01172       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
01173     }
01174     else
01175     {
01176       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
01177 
01178       /* Write Single Block command */
01179       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
01180     }
01181     if (errorstate != HAL_MMC_ERROR_NONE)
01182     {
01183       /* Clear all the static flags */
01184       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01185       hmmc->ErrorCode |= errorstate;
01186       hmmc->State = HAL_MMC_STATE_READY;
01187       return HAL_ERROR;
01188     }
01189 
01190     /* Enable transfer interrupts */
01191     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND |
01192                                SDMMC_FLAG_TXFIFOHE));
01193 
01194     return HAL_OK;
01195   }
01196   else
01197   {
01198     return HAL_BUSY;
01199   }
01200 }
01201 
01202 /**
01203   * @brief  Reads block(s) from a specified address in a card. The Data transfer
01204   *         is managed by DMA mode.
01205   * @note   This API should be followed by a check on the card state through
01206   *         HAL_MMC_GetCardState().
01207   * @note   You could also check the DMA transfer process through the MMC Rx
01208   *         interrupt event.
01209   * @param  hmmc: Pointer MMC handle
01210   * @param  pData: Pointer to the buffer that will contain the received data
01211   * @param  BlockAdd: Block Address from where data is to be read
01212   * @param  NumberOfBlocks: Number of blocks to read.
01213   * @retval HAL status
01214   */
01215 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData,
01216                                          uint32_t BlockAdd, uint32_t NumberOfBlocks)
01217 {
01218   SDMMC_DataInitTypeDef config;
01219   uint32_t errorstate;
01220   uint32_t add = BlockAdd;
01221 
01222   if (NULL == pData)
01223   {
01224     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01225     return HAL_ERROR;
01226   }
01227 
01228   if (hmmc->State == HAL_MMC_STATE_READY)
01229   {
01230     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
01231 
01232     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
01233     {
01234       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01235       return HAL_ERROR;
01236     }
01237 
01238     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
01239     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
01240     {
01241       if ((NumberOfBlocks % 8U) != 0U)
01242       {
01243         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
01244         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
01245         return HAL_ERROR;
01246       }
01247 
01248       if ((BlockAdd % 8U) != 0U)
01249       {
01250         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
01251         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
01252         return HAL_ERROR;
01253       }
01254     }
01255 
01256     hmmc->State = HAL_MMC_STATE_BUSY;
01257 
01258     /* Initialize data control register */
01259     hmmc->Instance->DCTRL = 0U;
01260 
01261     hmmc->pRxBuffPtr = pData;
01262     hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
01263 
01264     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
01265     {
01266       add *= 512U;
01267     }
01268 
01269     /* Configure the MMC DPSM (Data Path State Machine) */
01270     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01271     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
01272     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
01273     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
01274     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
01275     config.DPSM          = SDMMC_DPSM_DISABLE;
01276     (void)SDMMC_ConfigData(hmmc->Instance, &config);
01277 
01278     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
01279     hmmc->Instance->IDMABASE0 = (uint32_t) pData ;
01280     hmmc->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
01281 
01282     /* Read Blocks in DMA mode */
01283     if (NumberOfBlocks > 1U)
01284     {
01285       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
01286 
01287       /* Read Multi Block command */
01288       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
01289     }
01290     else
01291     {
01292       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
01293 
01294       /* Read Single Block command */
01295       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
01296     }
01297     if (errorstate != HAL_MMC_ERROR_NONE)
01298     {
01299       /* Clear all the static flags */
01300       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01301       hmmc->ErrorCode = errorstate;
01302       hmmc->State = HAL_MMC_STATE_READY;
01303       return HAL_ERROR;
01304     }
01305 
01306     /* Enable transfer interrupts */
01307     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
01308 
01309     return HAL_OK;
01310   }
01311   else
01312   {
01313     return HAL_BUSY;
01314   }
01315 }
01316 
01317 /**
01318   * @brief  Writes block(s) to a specified address in a card. The Data transfer
01319   *         is managed by DMA mode.
01320   * @note   This API should be followed by a check on the card state through
01321   *         HAL_MMC_GetCardState().
01322   * @note   You could also check the DMA transfer process through the MMC Tx
01323   *         interrupt event.
01324   * @param  hmmc: Pointer to MMC handle
01325   * @param  pData: Pointer to the buffer that will contain the data to transmit
01326   * @param  BlockAdd: Block Address where data will be written
01327   * @param  NumberOfBlocks: Number of blocks to write
01328   * @retval HAL status
01329   */
01330 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData,
01331                                           uint32_t BlockAdd, uint32_t NumberOfBlocks)
01332 {
01333   SDMMC_DataInitTypeDef config;
01334   uint32_t errorstate;
01335   uint32_t add = BlockAdd;
01336 
01337   if (NULL == pData)
01338   {
01339     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01340     return HAL_ERROR;
01341   }
01342 
01343   if (hmmc->State == HAL_MMC_STATE_READY)
01344   {
01345     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
01346 
01347     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
01348     {
01349       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01350       return HAL_ERROR;
01351     }
01352 
01353     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
01354     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
01355     {
01356       if ((NumberOfBlocks % 8U) != 0U)
01357       {
01358         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
01359         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
01360         return HAL_ERROR;
01361       }
01362 
01363       if ((BlockAdd % 8U) != 0U)
01364       {
01365         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
01366         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
01367         return HAL_ERROR;
01368       }
01369     }
01370 
01371     hmmc->State = HAL_MMC_STATE_BUSY;
01372 
01373     /* Initialize data control register */
01374     hmmc->Instance->DCTRL = 0U;
01375 
01376     hmmc->pTxBuffPtr = pData;
01377     hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
01378 
01379     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
01380     {
01381       add *= 512U;
01382     }
01383 
01384     /* Configure the MMC DPSM (Data Path State Machine) */
01385     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01386     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
01387     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
01388     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
01389     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
01390     config.DPSM          = SDMMC_DPSM_DISABLE;
01391     (void)SDMMC_ConfigData(hmmc->Instance, &config);
01392 
01393     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
01394 
01395     hmmc->Instance->IDMABASE0 = (uint32_t) pData ;
01396     hmmc->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
01397 
01398     /* Write Blocks in Polling mode */
01399     if (NumberOfBlocks > 1U)
01400     {
01401       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
01402 
01403       /* Write Multi Block command */
01404       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
01405     }
01406     else
01407     {
01408       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
01409 
01410       /* Write Single Block command */
01411       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
01412     }
01413     if (errorstate != HAL_MMC_ERROR_NONE)
01414     {
01415       /* Clear all the static flags */
01416       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01417       hmmc->ErrorCode |= errorstate;
01418       hmmc->State = HAL_MMC_STATE_READY;
01419       return HAL_ERROR;
01420     }
01421 
01422     /* Enable transfer interrupts */
01423     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
01424 
01425     return HAL_OK;
01426   }
01427   else
01428   {
01429     return HAL_BUSY;
01430   }
01431 }
01432 
01433 /**
01434   * @brief  Erases the specified memory area of the given MMC card.
01435   * @note   This API should be followed by a check on the card state through
01436   *         HAL_MMC_GetCardState().
01437   * @param  hmmc: Pointer to MMC handle
01438   * @param  BlockStartAdd: Start Block address
01439   * @param  BlockEndAdd: End Block address
01440   * @retval HAL status
01441   */
01442 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
01443 {
01444   uint32_t errorstate;
01445   uint32_t start_add = BlockStartAdd;
01446   uint32_t end_add = BlockEndAdd;
01447 
01448   if (hmmc->State == HAL_MMC_STATE_READY)
01449   {
01450     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
01451 
01452     if (end_add < start_add)
01453     {
01454       hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01455       return HAL_ERROR;
01456     }
01457 
01458     if (end_add > (hmmc->MmcCard.LogBlockNbr))
01459     {
01460       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01461       return HAL_ERROR;
01462     }
01463 
01464     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
01465     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS)
01466          & 0x000000FFU) != 0x0U)
01467     {
01468       if (((start_add % 8U) != 0U) || ((end_add % 8U) != 0U))
01469       {
01470         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
01471         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
01472         return HAL_ERROR;
01473       }
01474     }
01475 
01476     hmmc->State = HAL_MMC_STATE_BUSY;
01477 
01478     /* Check if the card command class supports erase command */
01479     if (((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
01480     {
01481       /* Clear all the static flags */
01482       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01483       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
01484       hmmc->State = HAL_MMC_STATE_READY;
01485       return HAL_ERROR;
01486     }
01487 
01488     if ((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
01489     {
01490       /* Clear all the static flags */
01491       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01492       hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
01493       hmmc->State = HAL_MMC_STATE_READY;
01494       return HAL_ERROR;
01495     }
01496 
01497     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
01498     {
01499       start_add *= 512U;
01500       end_add   *= 512U;
01501     }
01502 
01503     /* Send CMD35 MMC_ERASE_GRP_START with argument as addr  */
01504     errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
01505     if (errorstate != HAL_MMC_ERROR_NONE)
01506     {
01507       /* Clear all the static flags */
01508       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01509       hmmc->ErrorCode |= errorstate;
01510       hmmc->State = HAL_MMC_STATE_READY;
01511       return HAL_ERROR;
01512     }
01513 
01514     /* Send CMD36 MMC_ERASE_GRP_END with argument as addr  */
01515     errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
01516     if (errorstate != HAL_MMC_ERROR_NONE)
01517     {
01518       /* Clear all the static flags */
01519       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01520       hmmc->ErrorCode |= errorstate;
01521       hmmc->State = HAL_MMC_STATE_READY;
01522       return HAL_ERROR;
01523     }
01524 
01525     /* Send CMD38 ERASE */
01526     errorstate = SDMMC_CmdErase(hmmc->Instance, 0UL);
01527     if (errorstate != HAL_MMC_ERROR_NONE)
01528     {
01529       /* Clear all the static flags */
01530       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
01531       hmmc->ErrorCode |= errorstate;
01532       hmmc->State = HAL_MMC_STATE_READY;
01533       return HAL_ERROR;
01534     }
01535 
01536     hmmc->State = HAL_MMC_STATE_READY;
01537 
01538     return HAL_OK;
01539   }
01540   else
01541   {
01542     return HAL_BUSY;
01543   }
01544 }
01545 
01546 /**
01547   * @brief  This function handles MMC card interrupt request.
01548   * @param  hmmc: Pointer to MMC handle
01549   * @retval None
01550   */
01551 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
01552 {
01553   uint32_t errorstate;
01554   uint32_t context = hmmc->Context;
01555 
01556   /* Check for SDMMC interrupt flags */
01557   if ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
01558   {
01559     MMC_Read_IT(hmmc);
01560   }
01561 
01562   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) != RESET)
01563   {
01564     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND);
01565 
01566     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND  | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
01567                          SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR  | SDMMC_IT_TXFIFOHE | \
01568                          SDMMC_IT_RXFIFOHF);
01569 
01570     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
01571     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
01572 
01573     if ((context & MMC_CONTEXT_DMA) != 0U)
01574     {
01575       hmmc->Instance->DLEN = 0;
01576       hmmc->Instance->DCTRL = 0;
01577       hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA ;
01578 
01579       /* Stop Transfer for Write Multi blocks or Read Multi blocks */
01580       if (((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
01581       {
01582         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
01583         if (errorstate != HAL_MMC_ERROR_NONE)
01584         {
01585           hmmc->ErrorCode |= errorstate;
01586 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01587           hmmc->ErrorCallback(hmmc);
01588 #else
01589           HAL_MMC_ErrorCallback(hmmc);
01590 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01591         }
01592       }
01593 
01594       /* Clear all the static flags */
01595       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
01596 
01597       hmmc->State = HAL_MMC_STATE_READY;
01598       if (((context & MMC_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
01599       {
01600 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01601         hmmc->TxCpltCallback(hmmc);
01602 #else
01603         HAL_MMC_TxCpltCallback(hmmc);
01604 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01605       }
01606       if (((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
01607       {
01608 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01609         hmmc->RxCpltCallback(hmmc);
01610 #else
01611         HAL_MMC_RxCpltCallback(hmmc);
01612 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01613       }
01614     }
01615     else if ((context & MMC_CONTEXT_IT) != 0U)
01616     {
01617       /* Stop Transfer for Write Multi blocks or Read Multi blocks */
01618       if (((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
01619       {
01620         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
01621         if (errorstate != HAL_MMC_ERROR_NONE)
01622         {
01623           hmmc->ErrorCode |= errorstate;
01624 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01625           hmmc->ErrorCallback(hmmc);
01626 #else
01627           HAL_MMC_ErrorCallback(hmmc);
01628 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01629         }
01630       }
01631 
01632       /* Clear all the static flags */
01633       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
01634 
01635       hmmc->State = HAL_MMC_STATE_READY;
01636       if (((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
01637       {
01638 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01639         hmmc->RxCpltCallback(hmmc);
01640 #else
01641         HAL_MMC_RxCpltCallback(hmmc);
01642 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01643       }
01644       else
01645       {
01646 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01647         hmmc->TxCpltCallback(hmmc);
01648 #else
01649         HAL_MMC_TxCpltCallback(hmmc);
01650 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01651       }
01652     }
01653     else
01654     {
01655       /* Nothing to do */
01656     }
01657   }
01658 
01659   else if ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
01660   {
01661     MMC_Write_IT(hmmc);
01662   }
01663 
01664   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL |
01665                               SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
01666   {
01667     /* Set Error code */
01668     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL) != RESET)
01669     {
01670       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
01671     }
01672     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DTIMEOUT) != RESET)
01673     {
01674       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
01675     }
01676     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXOVERR) != RESET)
01677     {
01678       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
01679     }
01680     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXUNDERR) != RESET)
01681     {
01682       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
01683     }
01684 
01685     /* Clear All flags */
01686     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
01687 
01688     /* Disable all interrupts */
01689     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
01690                          SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR);
01691 
01692     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
01693     hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
01694     hmmc->Instance->CMD |= SDMMC_CMD_CMDSTOP;
01695     hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
01696     hmmc->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP);
01697     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DABORT);
01698 
01699     if ((context & MMC_CONTEXT_IT) != 0U)
01700     {
01701       /* Set the MMC state to ready to be able to start again the process */
01702       hmmc->State = HAL_MMC_STATE_READY;
01703 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01704       hmmc->ErrorCallback(hmmc);
01705 #else
01706       HAL_MMC_ErrorCallback(hmmc);
01707 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01708     }
01709     else if ((context & MMC_CONTEXT_DMA) != 0U)
01710     {
01711       if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
01712       {
01713         /* Disable Internal DMA */
01714         __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
01715         hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
01716 
01717         /* Set the MMC state to ready to be able to start again the process */
01718         hmmc->State = HAL_MMC_STATE_READY;
01719 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01720         hmmc->ErrorCallback(hmmc);
01721 #else
01722         HAL_MMC_ErrorCallback(hmmc);
01723 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01724       }
01725     }
01726     else
01727     {
01728       /* Nothing to do */
01729     }
01730   }
01731 
01732   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_IDMABTC) != RESET)
01733   {
01734     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_IT_IDMABTC);
01735     if (READ_BIT(hmmc->Instance->IDMACTRL, SDMMC_IDMA_IDMABACT) == 0U)
01736     {
01737       /* Current buffer is buffer0, Transfer complete for buffer1 */
01738       if ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
01739       {
01740 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01741         hmmc->Write_DMADblBuf1CpltCallback(hmmc);
01742 #else
01743         HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(hmmc);
01744 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01745       }
01746       else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
01747       {
01748 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01749         hmmc->Read_DMADblBuf1CpltCallback(hmmc);
01750 #else
01751         HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(hmmc);
01752 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01753       }
01754     }
01755     else /* MMC_DMA_BUFFER1 */
01756     {
01757       /* Current buffer is buffer1, Transfer complete for buffer0 */
01758       if ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
01759       {
01760 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01761         hmmc->Write_DMADblBuf0CpltCallback(hmmc);
01762 #else
01763         HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(hmmc);
01764 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01765       }
01766       else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
01767       {
01768 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01769         hmmc->Read_DMADblBuf0CpltCallback(hmmc);
01770 #else
01771         HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(hmmc);
01772 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
01773       }
01774     }
01775   }
01776 
01777   else
01778   {
01779     /* Nothing to do */
01780   }
01781 }
01782 
01783 /**
01784   * @brief return the MMC state
01785   * @param hmmc: Pointer to mmc handle
01786   * @retval HAL state
01787   */
01788 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
01789 {
01790   return hmmc->State;
01791 }
01792 
01793 /**
01794   * @brief  Return the MMC error code
01795   * @param  hmmc : Pointer to a MMC_HandleTypeDef structure that contains
01796   *              the configuration information.
01797   * @retval MMC Error Code
01798   */
01799 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
01800 {
01801   return hmmc->ErrorCode;
01802 }
01803 
01804 /**
01805   * @brief Tx Transfer completed callbacks
01806   * @param hmmc: Pointer to MMC handle
01807   * @retval None
01808   */
01809 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
01810 {
01811   /* Prevent unused argument(s) compilation warning */
01812   UNUSED(hmmc);
01813 
01814   /* NOTE : This function should not be modified, when the callback is needed,
01815             the HAL_MMC_TxCpltCallback can be implemented in the user file
01816    */
01817 }
01818 
01819 /**
01820   * @brief Rx Transfer completed callbacks
01821   * @param hmmc: Pointer MMC handle
01822   * @retval None
01823   */
01824 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
01825 {
01826   /* Prevent unused argument(s) compilation warning */
01827   UNUSED(hmmc);
01828 
01829   /* NOTE : This function should not be modified, when the callback is needed,
01830             the HAL_MMC_RxCpltCallback can be implemented in the user file
01831    */
01832 }
01833 
01834 /**
01835   * @brief MMC error callbacks
01836   * @param hmmc: Pointer MMC handle
01837   * @retval None
01838   */
01839 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
01840 {
01841   /* Prevent unused argument(s) compilation warning */
01842   UNUSED(hmmc);
01843 
01844   /* NOTE : This function should not be modified, when the callback is needed,
01845             the HAL_MMC_ErrorCallback can be implemented in the user file
01846    */
01847 }
01848 
01849 /**
01850   * @brief MMC Abort callbacks
01851   * @param hmmc: Pointer MMC handle
01852   * @retval None
01853   */
01854 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
01855 {
01856   /* Prevent unused argument(s) compilation warning */
01857   UNUSED(hmmc);
01858 
01859   /* NOTE : This function should not be modified, when the callback is needed,
01860             the HAL_MMC_AbortCallback can be implemented in the user file
01861    */
01862 }
01863 
01864 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
01865 /**
01866   * @brief  Register a User MMC Callback
01867   *         To be used instead of the weak (surcharged) predefined callback
01868   * @param hmmc : MMC handle
01869   * @param CallbackId : ID of the callback to be registered
01870   *        This parameter can be one of the following values:
01871   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID                 MMC Tx Complete Callback ID
01872   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID                 MMC Rx Complete Callback ID
01873   *          @arg @ref HAL_MMC_ERROR_CB_ID                   MMC Error Callback ID
01874   *          @arg @ref HAL_MMC_ABORT_CB_ID                   MMC Abort Callback ID
01875   *          @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID  MMC DMA Rx Double buffer 0 Callback ID
01876   *          @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID  MMC DMA Rx Double buffer 1 Callback ID
01877   *          @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID
01878   *          @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID
01879   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID                MMC MspInit Callback ID
01880   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID              MMC MspDeInit Callback ID
01881   * @param pCallback : pointer to the Callback function
01882   * @retval status
01883   */
01884 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId,
01885                                            pMMC_CallbackTypeDef pCallback)
01886 {
01887   HAL_StatusTypeDef status = HAL_OK;
01888 
01889   if (pCallback == NULL)
01890   {
01891     /* Update the error code */
01892     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
01893     return HAL_ERROR;
01894   }
01895 
01896   /* Process locked */
01897   __HAL_LOCK(hmmc);
01898 
01899   if (hmmc->State == HAL_MMC_STATE_READY)
01900   {
01901     switch (CallbackId)
01902     {
01903       case HAL_MMC_TX_CPLT_CB_ID :
01904         hmmc->TxCpltCallback = pCallback;
01905         break;
01906       case HAL_MMC_RX_CPLT_CB_ID :
01907         hmmc->RxCpltCallback = pCallback;
01908         break;
01909       case HAL_MMC_ERROR_CB_ID :
01910         hmmc->ErrorCallback = pCallback;
01911         break;
01912       case HAL_MMC_ABORT_CB_ID :
01913         hmmc->AbortCpltCallback = pCallback;
01914         break;
01915       case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID :
01916         hmmc->Read_DMADblBuf0CpltCallback = pCallback;
01917         break;
01918       case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID :
01919         hmmc->Read_DMADblBuf1CpltCallback = pCallback;
01920         break;
01921       case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
01922         hmmc->Write_DMADblBuf0CpltCallback = pCallback;
01923         break;
01924       case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
01925         hmmc->Write_DMADblBuf1CpltCallback = pCallback;
01926         break;
01927       case HAL_MMC_MSP_INIT_CB_ID :
01928         hmmc->MspInitCallback = pCallback;
01929         break;
01930       case HAL_MMC_MSP_DEINIT_CB_ID :
01931         hmmc->MspDeInitCallback = pCallback;
01932         break;
01933       default :
01934         /* Update the error code */
01935         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
01936         /* update return status */
01937         status =  HAL_ERROR;
01938         break;
01939     }
01940   }
01941   else if (hmmc->State == HAL_MMC_STATE_RESET)
01942   {
01943     switch (CallbackId)
01944     {
01945       case HAL_MMC_MSP_INIT_CB_ID :
01946         hmmc->MspInitCallback = pCallback;
01947         break;
01948       case HAL_MMC_MSP_DEINIT_CB_ID :
01949         hmmc->MspDeInitCallback = pCallback;
01950         break;
01951       default :
01952         /* Update the error code */
01953         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
01954         /* update return status */
01955         status =  HAL_ERROR;
01956         break;
01957     }
01958   }
01959   else
01960   {
01961     /* Update the error code */
01962     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
01963     /* update return status */
01964     status =  HAL_ERROR;
01965   }
01966 
01967   /* Release Lock */
01968   __HAL_UNLOCK(hmmc);
01969   return status;
01970 }
01971 
01972 /**
01973   * @brief  Unregister a User MMC Callback
01974   *         MMC Callback is redirected to the weak (surcharged) predefined callback
01975   * @param hmmc : MMC handle
01976   * @param CallbackId : ID of the callback to be unregistered
01977   *        This parameter can be one of the following values:
01978   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID                 MMC Tx Complete Callback ID
01979   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID                 MMC Rx Complete Callback ID
01980   *          @arg @ref HAL_MMC_ERROR_CB_ID                   MMC Error Callback ID
01981   *          @arg @ref HAL_MMC_ABORT_CB_ID                   MMC Abort Callback ID
01982   *          @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID  MMC DMA Rx Double buffer 0 Callback ID
01983   *          @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID  MMC DMA Rx Double buffer 1 Callback ID
01984   *          @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID
01985   *          @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID
01986   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID                MMC MspInit Callback ID
01987   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID              MMC MspDeInit Callback ID
01988   * @retval status
01989   */
01990 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
01991 {
01992   HAL_StatusTypeDef status = HAL_OK;
01993 
01994   /* Process locked */
01995   __HAL_LOCK(hmmc);
01996 
01997   if (hmmc->State == HAL_MMC_STATE_READY)
01998   {
01999     switch (CallbackId)
02000     {
02001       case HAL_MMC_TX_CPLT_CB_ID :
02002         hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
02003         break;
02004       case HAL_MMC_RX_CPLT_CB_ID :
02005         hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
02006         break;
02007       case HAL_MMC_ERROR_CB_ID :
02008         hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
02009         break;
02010       case HAL_MMC_ABORT_CB_ID :
02011         hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
02012         break;
02013       case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID :
02014         hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback;
02015         break;
02016       case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID :
02017         hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback;
02018         break;
02019       case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
02020         hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback;
02021         break;
02022       case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
02023         hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback;
02024         break;
02025       case HAL_MMC_MSP_INIT_CB_ID :
02026         hmmc->MspInitCallback = HAL_MMC_MspInit;
02027         break;
02028       case HAL_MMC_MSP_DEINIT_CB_ID :
02029         hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
02030         break;
02031       default :
02032         /* Update the error code */
02033         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
02034         /* update return status */
02035         status =  HAL_ERROR;
02036         break;
02037     }
02038   }
02039   else if (hmmc->State == HAL_MMC_STATE_RESET)
02040   {
02041     switch (CallbackId)
02042     {
02043       case HAL_MMC_MSP_INIT_CB_ID :
02044         hmmc->MspInitCallback = HAL_MMC_MspInit;
02045         break;
02046       case HAL_MMC_MSP_DEINIT_CB_ID :
02047         hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
02048         break;
02049       default :
02050         /* Update the error code */
02051         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
02052         /* update return status */
02053         status =  HAL_ERROR;
02054         break;
02055     }
02056   }
02057   else
02058   {
02059     /* Update the error code */
02060     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
02061     /* update return status */
02062     status =  HAL_ERROR;
02063   }
02064 
02065   /* Release Lock */
02066   __HAL_UNLOCK(hmmc);
02067   return status;
02068 }
02069 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
02070 
02071 /**
02072   * @}
02073   */
02074 
02075 /** @addtogroup MMC_Exported_Functions_Group3
02076   *  @brief   management functions
02077   *
02078 @verbatim
02079   ==============================================================================
02080                       ##### Peripheral Control functions #####
02081   ==============================================================================
02082   [..]
02083     This subsection provides a set of functions allowing to control the MMC card
02084     operations and get the related information
02085 
02086 @endverbatim
02087   * @{
02088   */
02089 
02090 /**
02091   * @brief  Returns information the information of the card which are stored on
02092   *         the CID register.
02093   * @param  hmmc: Pointer to MMC handle
02094   * @param  pCID: Pointer to a HAL_MMC_CIDTypedef structure that
02095   *         contains all CID register parameters
02096   * @retval HAL status
02097   */
02098 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
02099 {
02100   pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
02101 
02102   pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
02103 
02104   pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
02105 
02106   pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
02107 
02108   pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
02109 
02110   pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
02111 
02112   pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
02113 
02114   pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
02115 
02116   pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
02117 
02118   pCID->Reserved2 = 1U;
02119 
02120   return HAL_OK;
02121 }
02122 
02123 /**
02124   * @brief  Returns information the information of the card which are stored on
02125   *         the CSD register.
02126   * @param  hmmc: Pointer to MMC handle
02127   * @param  pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
02128   *         contains all CSD register parameters
02129   * @retval HAL status
02130   */
02131 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
02132 {
02133   uint32_t block_nbr = 0;
02134 
02135   pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
02136 
02137   pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
02138 
02139   pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
02140 
02141   pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
02142 
02143   pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
02144 
02145   pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
02146 
02147   pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
02148 
02149   pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
02150 
02151   pCSD->PartBlockRead   = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
02152 
02153   pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
02154 
02155   pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
02156 
02157   pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
02158 
02159   pCSD->Reserved2 = 0U; /*!< Reserved */
02160 
02161   if (MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
02162   {
02163     return HAL_ERROR;
02164   }
02165 
02166   if (hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
02167   {
02168     pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
02169 
02170     pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
02171 
02172     pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
02173 
02174     pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
02175 
02176     pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
02177 
02178     pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
02179 
02180     hmmc->MmcCard.BlockNbr  = (pCSD->DeviceSize + 1U) ;
02181     hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
02182     hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
02183 
02184     hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
02185     hmmc->MmcCard.LogBlockSize = 512U;
02186   }
02187   else if (hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
02188   {
02189     hmmc->MmcCard.BlockNbr = block_nbr;
02190     hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
02191     hmmc->MmcCard.BlockSize = 512U;
02192     hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
02193   }
02194   else
02195   {
02196     /* Clear all the static flags */
02197     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02198     hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
02199     hmmc->State = HAL_MMC_STATE_READY;
02200     return HAL_ERROR;
02201   }
02202 
02203   pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
02204 
02205   pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
02206 
02207   pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
02208 
02209   pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
02210 
02211   pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
02212 
02213   pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
02214 
02215   pCSD->MaxWrBlockLen = (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
02216 
02217   pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
02218 
02219   pCSD->Reserved3 = 0;
02220 
02221   pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
02222 
02223   pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
02224 
02225   pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
02226 
02227   pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
02228 
02229   pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
02230 
02231   pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
02232 
02233   pCSD->ECC = (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
02234 
02235   pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
02236 
02237   pCSD->Reserved4 = 1;
02238 
02239   return HAL_OK;
02240 }
02241 
02242 /**
02243   * @brief  Gets the MMC card info.
02244   * @param  hmmc: Pointer to MMC handle
02245   * @param  pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
02246   *         will contain the MMC card status information
02247   * @retval HAL status
02248   */
02249 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
02250 {
02251   pCardInfo->CardType     = (uint32_t)(hmmc->MmcCard.CardType);
02252   pCardInfo->Class        = (uint32_t)(hmmc->MmcCard.Class);
02253   pCardInfo->RelCardAdd   = (uint32_t)(hmmc->MmcCard.RelCardAdd);
02254   pCardInfo->BlockNbr     = (uint32_t)(hmmc->MmcCard.BlockNbr);
02255   pCardInfo->BlockSize    = (uint32_t)(hmmc->MmcCard.BlockSize);
02256   pCardInfo->LogBlockNbr  = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
02257   pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
02258 
02259   return HAL_OK;
02260 }
02261 
02262 /**
02263   * @brief  Returns information the information of the card which are stored on
02264   *         the Extended CSD register.
02265   * @param  hmmc Pointer to MMC handle
02266   * @param  pExtCSD Pointer to a memory area (512 bytes) that contains all
02267   *         Extended CSD register parameters
02268   * @param  Timeout Specify timeout value
02269   * @retval HAL status
02270   */
02271 HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout)
02272 {
02273   SDMMC_DataInitTypeDef config;
02274   uint32_t errorstate;
02275   uint32_t tickstart = HAL_GetTick();
02276   uint32_t count;
02277   uint32_t *tmp_buf;
02278 
02279   if (NULL == pExtCSD)
02280   {
02281     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
02282     return HAL_ERROR;
02283   }
02284 
02285   if (hmmc->State == HAL_MMC_STATE_READY)
02286   {
02287     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
02288 
02289     hmmc->State = HAL_MMC_STATE_BUSY;
02290 
02291     /* Initialize data control register */
02292     hmmc->Instance->DCTRL = 0;
02293 
02294     /* Initiaize the destination pointer */
02295     tmp_buf = pExtCSD;
02296 
02297     /* Configure the MMC DPSM (Data Path State Machine) */
02298     config.DataTimeOut   = SDMMC_DATATIMEOUT;
02299     config.DataLength    = 512U;
02300     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
02301     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
02302     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
02303     config.DPSM          = SDMMC_DPSM_DISABLE;
02304     (void)SDMMC_ConfigData(hmmc->Instance, &config);
02305     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
02306 
02307     /* Send ExtCSD Read command to Card */
02308     errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
02309     if (errorstate != HAL_MMC_ERROR_NONE)
02310     {
02311       /* Clear all the static flags */
02312       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02313       hmmc->ErrorCode |= errorstate;
02314       hmmc->State = HAL_MMC_STATE_READY;
02315       return HAL_ERROR;
02316     }
02317 
02318     /* Poll on SDMMC flags */
02319     while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR |
02320                                SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
02321     {
02322       if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
02323       {
02324         /* Read data from SDMMC Rx FIFO */
02325         for (count = 0U; count < 8U; count++)
02326         {
02327           *tmp_buf = SDMMC_ReadFIFO(hmmc->Instance);
02328           tmp_buf++;
02329         }
02330       }
02331 
02332       if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
02333       {
02334         /* Clear all the static flags */
02335         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02336         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
02337         hmmc->State = HAL_MMC_STATE_READY;
02338         return HAL_TIMEOUT;
02339       }
02340     }
02341 
02342     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
02343 
02344     /* Get error state */
02345     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
02346     {
02347       /* Clear all the static flags */
02348       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02349       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
02350       hmmc->State = HAL_MMC_STATE_READY;
02351       return HAL_ERROR;
02352     }
02353     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
02354     {
02355       /* Clear all the static flags */
02356       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02357       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
02358       hmmc->State = HAL_MMC_STATE_READY;
02359       return HAL_ERROR;
02360     }
02361     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
02362     {
02363       /* Clear all the static flags */
02364       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02365       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
02366       hmmc->State = HAL_MMC_STATE_READY;
02367       return HAL_ERROR;
02368     }
02369     else
02370     {
02371       /* Nothing to do */
02372     }
02373 
02374     /* Clear all the static flags */
02375     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
02376     hmmc->State = HAL_MMC_STATE_READY;
02377   }
02378 
02379   return HAL_OK;
02380 }
02381 
02382 /**
02383   * @brief  Enables wide bus operation for the requested card if supported by
02384   *         card.
02385   * @param  hmmc: Pointer to MMC handle
02386   * @param  WideMode: Specifies the MMC card wide bus mode
02387   *          This parameter can be one of the following values:
02388   *            @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
02389   *            @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
02390   *            @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
02391   * @retval HAL status
02392   */
02393 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
02394 {
02395   uint32_t count;
02396   SDMMC_InitTypeDef Init;
02397   uint32_t errorstate;
02398   uint32_t response = 0U;
02399 
02400   /* Check the parameters */
02401   assert_param(IS_SDMMC_BUS_WIDE(WideMode));
02402 
02403   /* Change State */
02404   hmmc->State = HAL_MMC_STATE_BUSY;
02405 
02406   /* Check and update the power class if needed */
02407   if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U)
02408   {
02409     if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U)
02410     {
02411       errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_DDR);
02412     }
02413     else
02414     {
02415       errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_HIGH);
02416     }
02417   }
02418   else
02419   {
02420     errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_DEFAULT);
02421   }
02422 
02423   if (errorstate == HAL_MMC_ERROR_NONE)
02424   {
02425     if (WideMode == SDMMC_BUS_WIDE_8B)
02426     {
02427       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
02428     }
02429     else if (WideMode == SDMMC_BUS_WIDE_4B)
02430     {
02431       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
02432     }
02433     else if (WideMode == SDMMC_BUS_WIDE_1B)
02434     {
02435       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
02436     }
02437     else
02438     {
02439       /* WideMode is not a valid argument*/
02440       errorstate = HAL_MMC_ERROR_PARAM;
02441     }
02442 
02443     /* Check for switch error and violation of the trial number of sending CMD 13 */
02444     if (errorstate == HAL_MMC_ERROR_NONE)
02445     {
02446       /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
02447       count = SDMMC_MAX_TRIAL;
02448       do
02449       {
02450         errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
02451         if (errorstate != HAL_MMC_ERROR_NONE)
02452         {
02453           break;
02454         }
02455 
02456         /* Get command response */
02457         response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
02458         count--;
02459       } while (((response & 0x100U) == 0U) && (count != 0U));
02460 
02461       /* Check the status after the switch command execution */
02462       if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
02463       {
02464         /* Check the bit SWITCH_ERROR of the device status */
02465         if ((response & 0x80U) != 0U)
02466         {
02467           errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
02468         }
02469         else
02470         {
02471           /* Configure the SDMMC peripheral */
02472           Init = hmmc->Init;
02473           Init.BusWide = WideMode;
02474           (void)SDMMC_Init(hmmc->Instance, Init);
02475         }
02476       }
02477       else if (count == 0U)
02478       {
02479         errorstate = SDMMC_ERROR_TIMEOUT;
02480       }
02481       else
02482       {
02483         /* Nothing to do */
02484       }
02485     }
02486   }
02487 
02488   /* Change State */
02489   hmmc->State = HAL_MMC_STATE_READY;
02490 
02491   if (errorstate != HAL_MMC_ERROR_NONE)
02492   {
02493     /* Clear all the static flags */
02494     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02495     hmmc->ErrorCode |= errorstate;
02496     return HAL_ERROR;
02497   }
02498 
02499   return HAL_OK;
02500 }
02501 
02502 /**
02503   * @brief  Configure the speed bus mode
02504   * @param  hmmc: Pointer to the MMC handle
02505   * @param  SpeedMode: Specifies the MMC card speed bus mode
02506   *          This parameter can be one of the following values:
02507   *            @arg SDMMC_SPEED_MODE_AUTO: Max speed mode supported by the card
02508   *            @arg SDMMC_SPEED_MODE_DEFAULT: Default Speed (MMC @ 26MHz)
02509   *            @arg SDMMC_SPEED_MODE_HIGH: High Speed (MMC @ 52 MHz)
02510   *            @arg SDMMC_SPEED_MODE_DDR: High Speed DDR (MMC DDR @ 52 MHz)
02511   * @retval HAL status
02512   */
02513 
02514 HAL_StatusTypeDef HAL_MMC_ConfigSpeedBusOperation(MMC_HandleTypeDef *hmmc, uint32_t SpeedMode)
02515 {
02516   uint32_t tickstart;
02517   HAL_StatusTypeDef status = HAL_OK;
02518   uint32_t device_type;
02519   uint32_t errorstate;
02520 
02521   /* Check the parameters */
02522   assert_param(IS_SDMMC_SPEED_MODE(SpeedMode));
02523 
02524   /* Change State */
02525   hmmc->State = HAL_MMC_STATE_BUSY;
02526 
02527   /* Field DEVICE_TYPE [196 = 49*4] of Extended CSD register */
02528   device_type = (hmmc->Ext_CSD[49] & 0x000000FFU);
02529 
02530   switch (SpeedMode)
02531   {
02532     case SDMMC_SPEED_MODE_AUTO:
02533     {
02534       if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
02535       {
02536         /* High Speed DDR mode allowed */
02537         errorstate = MMC_HighSpeed(hmmc, ENABLE);
02538         if (errorstate != HAL_MMC_ERROR_NONE)
02539         {
02540           hmmc->ErrorCode |= errorstate;
02541         }
02542         else
02543         {
02544           if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_CLKDIV) != 0U)
02545           {
02546             /* DDR mode not supported with CLKDIV = 0 */
02547             errorstate = MMC_DDR_Mode(hmmc, ENABLE);
02548             if (errorstate != HAL_MMC_ERROR_NONE)
02549             {
02550               hmmc->ErrorCode |= errorstate;
02551             }
02552           }
02553         }
02554       }
02555       else if ((device_type & 0x02U) != 0U)
02556       {
02557         /* High Speed mode allowed */
02558         errorstate = MMC_HighSpeed(hmmc, ENABLE);
02559         if (errorstate != HAL_MMC_ERROR_NONE)
02560         {
02561           hmmc->ErrorCode |= errorstate;
02562         }
02563       }
02564       else
02565       {
02566         /* Nothing to do : keep current speed */
02567       }
02568       break;
02569     }
02570     case SDMMC_SPEED_MODE_DDR:
02571     {
02572       if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
02573       {
02574         /* High Speed DDR mode allowed */
02575         errorstate = MMC_HighSpeed(hmmc, ENABLE);
02576         if (errorstate != HAL_MMC_ERROR_NONE)
02577         {
02578           hmmc->ErrorCode |= errorstate;
02579         }
02580         else
02581         {
02582           if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_CLKDIV) != 0U)
02583           {
02584             /* DDR mode not supported with CLKDIV = 0 */
02585             errorstate = MMC_DDR_Mode(hmmc, ENABLE);
02586             if (errorstate != HAL_MMC_ERROR_NONE)
02587             {
02588               hmmc->ErrorCode |= errorstate;
02589             }
02590           }
02591         }
02592       }
02593       else
02594       {
02595         /* High Speed DDR mode not allowed */
02596         hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
02597         status = HAL_ERROR;
02598       }
02599       break;
02600     }
02601     case SDMMC_SPEED_MODE_HIGH:
02602     {
02603       if ((device_type & 0x02U) != 0U)
02604       {
02605         /* High Speed mode allowed */
02606         errorstate = MMC_HighSpeed(hmmc, ENABLE);
02607         if (errorstate != HAL_MMC_ERROR_NONE)
02608         {
02609           hmmc->ErrorCode |= errorstate;
02610         }
02611       }
02612       else
02613       {
02614         /* High Speed mode not allowed */
02615         hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
02616         status = HAL_ERROR;
02617       }
02618       break;
02619     }
02620     case SDMMC_SPEED_MODE_DEFAULT:
02621     {
02622       if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U)
02623       {
02624         /* High Speed DDR mode activated */
02625         errorstate = MMC_DDR_Mode(hmmc, DISABLE);
02626         if (errorstate != HAL_MMC_ERROR_NONE)
02627         {
02628           hmmc->ErrorCode |= errorstate;
02629         }
02630       }
02631       if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U)
02632       {
02633         /* High Speed mode activated */
02634         errorstate = MMC_HighSpeed(hmmc, DISABLE);
02635         if (errorstate != HAL_MMC_ERROR_NONE)
02636         {
02637           hmmc->ErrorCode |= errorstate;
02638         }
02639       }
02640       break;
02641     }
02642     default:
02643       hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
02644       status = HAL_ERROR;
02645       break;
02646   }
02647 
02648   /* Verify that MMC card is ready to use after Speed mode switch*/
02649   tickstart = HAL_GetTick();
02650   while ((HAL_MMC_GetCardState(hmmc) != HAL_MMC_CARD_TRANSFER))
02651   {
02652     if ((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
02653     {
02654       hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
02655       hmmc->State = HAL_MMC_STATE_READY;
02656       return HAL_TIMEOUT;
02657     }
02658   }
02659 
02660   /* Change State */
02661   hmmc->State = HAL_MMC_STATE_READY;
02662   return status;
02663 }
02664 
02665 /**
02666   * @brief  Gets the current mmc card data state.
02667   * @param  hmmc: pointer to MMC handle
02668   * @retval Card state
02669   */
02670 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
02671 {
02672   uint32_t cardstate;
02673   uint32_t errorstate;
02674   uint32_t resp1 = 0U;
02675 
02676   errorstate = MMC_SendStatus(hmmc, &resp1);
02677   if (errorstate != HAL_MMC_ERROR_NONE)
02678   {
02679     hmmc->ErrorCode |= errorstate;
02680   }
02681 
02682   cardstate = ((resp1 >> 9U) & 0x0FU);
02683 
02684   return (HAL_MMC_CardStateTypeDef)cardstate;
02685 }
02686 
02687 /**
02688   * @brief  Abort the current transfer and disable the MMC.
02689   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
02690   *                the configuration information for MMC module.
02691   * @retval HAL status
02692   */
02693 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
02694 {
02695   HAL_MMC_CardStateTypeDef CardState;
02696 
02697   /* DIsable All interrupts */
02698   __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
02699                        SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR);
02700 
02701   /* Clear All flags */
02702   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
02703 
02704   /* If IDMA Context, disable Internal DMA */
02705   hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
02706 
02707   hmmc->State = HAL_MMC_STATE_READY;
02708 
02709   /* Initialize the MMC operation */
02710   hmmc->Context = MMC_CONTEXT_NONE;
02711 
02712   CardState = HAL_MMC_GetCardState(hmmc);
02713   if ((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02714   {
02715     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
02716   }
02717   if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02718   {
02719     return HAL_ERROR;
02720   }
02721   return HAL_OK;
02722 }
02723 
02724 /**
02725   * @brief  Abort the current transfer and disable the MMC (IT mode).
02726   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
02727   *                the configuration information for MMC module.
02728   * @retval HAL status
02729   */
02730 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
02731 {
02732   HAL_MMC_CardStateTypeDef CardState;
02733 
02734   /* DIsable All interrupts */
02735   __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
02736                        SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR);
02737 
02738   /* If IDMA Context, disable Internal DMA */
02739   hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
02740 
02741   /* Clear All flags */
02742   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
02743 
02744   CardState = HAL_MMC_GetCardState(hmmc);
02745   hmmc->State = HAL_MMC_STATE_READY;
02746 
02747   if ((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02748   {
02749     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
02750   }
02751   if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02752   {
02753     return HAL_ERROR;
02754   }
02755   else
02756   {
02757 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
02758     hmmc->AbortCpltCallback(hmmc);
02759 #else
02760     HAL_MMC_AbortCallback(hmmc);
02761 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
02762   }
02763 
02764   return HAL_OK;
02765 }
02766 
02767 /**
02768   * @brief  Perform specific commands sequence for the different type of erase.
02769   * @note   This API should be followed by a check on the card state through
02770   *         HAL_MMC_GetCardState().
02771   * @param  hmmc Pointer to MMC handle
02772   * @param  EraseType Specifies the type of erase to be performed
02773   *          This parameter can be one of the following values:
02774   *             @arg HAL_MMC_TRIM Erase the write blocks identified by CMD35 & 36
02775   *             @arg HAL_MMC_ERASE Erase the erase groups identified by CMD35 & 36
02776   *             @arg HAL_MMC_DISCARD Discard the write blocks identified by CMD35 & 36
02777   *             @arg HAL_MMC_SECURE_ERASE Perform a secure purge according SRT on the erase groups identified
02778   *                  by CMD35 & 36
02779   *             @arg HAL_MMC_SECURE_TRIM_STEP1 Mark the write blocks identified by CMD35 & 36 for secure erase
02780   *             @arg HAL_MMC_SECURE_TRIM_STEP2 Perform a secure purge according SRT on the write blocks
02781   *                  previously identified
02782   * @param  BlockStartAdd Start Block address
02783   * @param  BlockEndAdd End Block address
02784   * @retval HAL status
02785   */
02786 HAL_StatusTypeDef HAL_MMC_EraseSequence(MMC_HandleTypeDef *hmmc, uint32_t EraseType,
02787                                         uint32_t BlockStartAdd, uint32_t BlockEndAdd)
02788 {
02789   uint32_t errorstate;
02790   uint32_t start_add = BlockStartAdd;
02791   uint32_t end_add = BlockEndAdd;
02792   uint32_t tickstart = HAL_GetTick();
02793 
02794   /* Check the erase type value is correct */
02795   assert_param(IS_MMC_ERASE_TYPE(EraseType));
02796 
02797   /* Check the coherence between start and end address */
02798   if (end_add < start_add)
02799   {
02800     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
02801     return HAL_ERROR;
02802   }
02803 
02804   /* Check that the end address is not out of range of device memory */
02805   if (end_add > (hmmc->MmcCard.LogBlockNbr))
02806   {
02807     hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
02808     return HAL_ERROR;
02809   }
02810 
02811   /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
02812   if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
02813   {
02814     if (((start_add % 8U) != 0U) || ((end_add % 8U) != 0U))
02815     {
02816       /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
02817       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
02818       return HAL_ERROR;
02819     }
02820   }
02821 
02822   /* Check if the card command class supports erase command */
02823   if (((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
02824   {
02825     hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
02826     return HAL_ERROR;
02827   }
02828 
02829   /* Check the state of the driver */
02830   if (hmmc->State == HAL_MMC_STATE_READY)
02831   {
02832     /* Change State */
02833     hmmc->State = HAL_MMC_STATE_BUSY;
02834 
02835     /* Check that the card is not locked */
02836     if ((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
02837     {
02838       hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
02839       hmmc->State = HAL_MMC_STATE_READY;
02840       return HAL_ERROR;
02841     }
02842 
02843     /* In case of low capacity card, the address is not block number but bytes */
02844     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
02845     {
02846       start_add *= 512U;
02847       end_add   *= 512U;
02848     }
02849 
02850     /* Send CMD35 MMC_ERASE_GRP_START with start address as argument */
02851     errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
02852     if (errorstate == HAL_MMC_ERROR_NONE)
02853     {
02854       /* Send CMD36 MMC_ERASE_GRP_END with end address as argument */
02855       errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
02856       if (errorstate == HAL_MMC_ERROR_NONE)
02857       {
02858         /* Send CMD38 ERASE with erase type as argument */
02859         errorstate = SDMMC_CmdErase(hmmc->Instance, EraseType);
02860         if (errorstate == HAL_MMC_ERROR_NONE)
02861         {
02862           if ((EraseType == HAL_MMC_SECURE_ERASE) || (EraseType == HAL_MMC_SECURE_TRIM_STEP2))
02863           {
02864             /* Wait that the device is ready by checking the D0 line */
02865             while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
02866             {
02867               if ((HAL_GetTick() - tickstart) >= SDMMC_MAXERASETIMEOUT)
02868               {
02869                 errorstate = HAL_MMC_ERROR_TIMEOUT;
02870               }
02871             }
02872 
02873             /* Clear the flag corresponding to end D0 bus line */
02874             __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
02875           }
02876         }
02877       }
02878     }
02879 
02880     /* Change State */
02881     hmmc->State = HAL_MMC_STATE_READY;
02882 
02883     /* Manage errors */
02884     if (errorstate != HAL_MMC_ERROR_NONE)
02885     {
02886       /* Clear all the static flags */
02887       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02888       hmmc->ErrorCode |= errorstate;
02889 
02890       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
02891       {
02892         return HAL_ERROR;
02893       }
02894       else
02895       {
02896         return HAL_TIMEOUT;
02897       }
02898     }
02899     else
02900     {
02901       return HAL_OK;
02902     }
02903   }
02904   else
02905   {
02906     return HAL_BUSY;
02907   }
02908 }
02909 
02910 /**
02911   * @brief  Perform sanitize operation on the device.
02912   * @note   This API should be followed by a check on the card state through
02913   *         HAL_MMC_GetCardState().
02914   * @param  hmmc Pointer to MMC handle
02915   * @retval HAL status
02916   */
02917 HAL_StatusTypeDef HAL_MMC_Sanitize(MMC_HandleTypeDef *hmmc)
02918 {
02919   uint32_t errorstate;
02920   uint32_t response = 0U;
02921   uint32_t count;
02922   uint32_t tickstart = HAL_GetTick();
02923 
02924   /* Check the state of the driver */
02925   if (hmmc->State == HAL_MMC_STATE_READY)
02926   {
02927     /* Change State */
02928     hmmc->State = HAL_MMC_STATE_BUSY;
02929 
02930     /* Index : 165 - Value : 0x01 */
02931     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03A50100U);
02932     if (errorstate == HAL_MMC_ERROR_NONE)
02933     {
02934       /* Wait that the device is ready by checking the D0 line */
02935       while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
02936       {
02937         if ((HAL_GetTick() - tickstart) >= SDMMC_MAXERASETIMEOUT)
02938         {
02939           errorstate = HAL_MMC_ERROR_TIMEOUT;
02940         }
02941       }
02942 
02943       /* Clear the flag corresponding to end D0 bus line */
02944       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
02945 
02946       if (errorstate == HAL_MMC_ERROR_NONE)
02947       {
02948         /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
02949         count = SDMMC_MAX_TRIAL;
02950         do
02951         {
02952           errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
02953           if (errorstate != HAL_MMC_ERROR_NONE)
02954           {
02955             break;
02956           }
02957 
02958           /* Get command response */
02959           response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
02960           count--;
02961         } while (((response & 0x100U) == 0U) && (count != 0U));
02962 
02963         /* Check the status after the switch command execution */
02964         if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
02965         {
02966           /* Check the bit SWITCH_ERROR of the device status */
02967           if ((response & 0x80U) != 0U)
02968           {
02969             errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
02970           }
02971         }
02972         else if (count == 0U)
02973         {
02974           errorstate = SDMMC_ERROR_TIMEOUT;
02975         }
02976         else
02977         {
02978           /* Nothing to do */
02979         }
02980       }
02981     }
02982 
02983     /* Change State */
02984     hmmc->State = HAL_MMC_STATE_READY;
02985 
02986     /* Manage errors */
02987     if (errorstate != HAL_MMC_ERROR_NONE)
02988     {
02989       /* Clear all the static flags */
02990       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
02991       hmmc->ErrorCode |= errorstate;
02992 
02993       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
02994       {
02995         return HAL_ERROR;
02996       }
02997       else
02998       {
02999         return HAL_TIMEOUT;
03000       }
03001     }
03002     else
03003     {
03004       return HAL_OK;
03005     }
03006   }
03007   else
03008   {
03009     return HAL_BUSY;
03010   }
03011 }
03012 
03013 /**
03014   * @brief  Configure the Secure Removal Type (SRT) in the Extended CSD register.
03015   * @note   This API should be followed by a check on the card state through
03016   *         HAL_MMC_GetCardState().
03017   * @param  hmmc Pointer to MMC handle
03018   * @param  SRTMode Specifies the type of erase to be performed
03019   *          This parameter can be one of the following values:
03020   *            @arg HAL_MMC_SRT_ERASE Information removed by an erase
03021   *            @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character
03022   *                 followed by an erase
03023   *            @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character,
03024   *                 its complement then a random character
03025   *            @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined
03026   * @retval HAL status
03027   */
03028 HAL_StatusTypeDef HAL_MMC_ConfigSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t SRTMode)
03029 {
03030   uint32_t srt;
03031   uint32_t errorstate;
03032   uint32_t response = 0U;
03033   uint32_t count;
03034 
03035   /* Check the erase type value is correct */
03036   assert_param(IS_MMC_SRT_TYPE(SRTMode));
03037 
03038   /* Check the state of the driver */
03039   if (hmmc->State == HAL_MMC_STATE_READY)
03040   {
03041     /* Get the supported values by the device */
03042     if (HAL_MMC_GetSupportedSecRemovalType(hmmc, &srt) == HAL_OK)
03043     {
03044       /* Change State */
03045       hmmc->State = HAL_MMC_STATE_BUSY;
03046 
03047       /* Check the value passed as parameter is supported by the device */
03048       if ((SRTMode & srt) != 0U)
03049       {
03050         /* Index : 16 - Value : SRTMode */
03051         srt |= ((POSITION_VAL(SRTMode)) << 4U);
03052         errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03100000U | (srt << 8U)));
03053         if (errorstate == HAL_MMC_ERROR_NONE)
03054         {
03055           /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03056           count = SDMMC_MAX_TRIAL;
03057           do
03058           {
03059             errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03060             if (errorstate != HAL_MMC_ERROR_NONE)
03061             {
03062               break;
03063             }
03064 
03065             /* Get command response */
03066             response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03067             count--;
03068           } while (((response & 0x100U) == 0U) && (count != 0U));
03069 
03070           /* Check the status after the switch command execution */
03071           if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
03072           {
03073             /* Check the bit SWITCH_ERROR of the device status */
03074             if ((response & 0x80U) != 0U)
03075             {
03076               errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
03077             }
03078           }
03079           else if (count == 0U)
03080           {
03081             errorstate = SDMMC_ERROR_TIMEOUT;
03082           }
03083           else
03084           {
03085             /* Nothing to do */
03086           }
03087         }
03088       }
03089       else
03090       {
03091         errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
03092       }
03093 
03094       /* Change State */
03095       hmmc->State = HAL_MMC_STATE_READY;
03096     }
03097     else
03098     {
03099       errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
03100     }
03101 
03102     /* Manage errors */
03103     if (errorstate != HAL_MMC_ERROR_NONE)
03104     {
03105       /* Clear all the static flags */
03106       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03107       hmmc->ErrorCode |= errorstate;
03108       return HAL_ERROR;
03109     }
03110     else
03111     {
03112       return HAL_OK;
03113     }
03114   }
03115   else
03116   {
03117     return HAL_BUSY;
03118   }
03119 }
03120 
03121 /**
03122   * @brief  Gets the supported values of the the Secure Removal Type (SRT).
03123   * @param  hmmc pointer to MMC handle
03124   * @param  SupportedSRT pointer for supported SRT value
03125   *          This parameter is a bit field of the following values:
03126   *            @arg HAL_MMC_SRT_ERASE Information removed by an erase
03127   *            @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character followed
03128   *                  by an erase
03129   *            @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character,
03130   *                 its complement then a random character
03131   *            @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined
03132   * @retval HAL status
03133   */
03134 HAL_StatusTypeDef HAL_MMC_GetSupportedSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t *SupportedSRT)
03135 {
03136   /* Check the state of the driver */
03137   if (hmmc->State == HAL_MMC_STATE_READY)
03138   {
03139     /* Change State */
03140     hmmc->State = HAL_MMC_STATE_BUSY;
03141 
03142     /* Read field SECURE_REMOVAL_TYPE [16 = 4*4] of the Extended CSD register */
03143     *SupportedSRT = (hmmc->Ext_CSD[4] & 0x0000000FU); /* Bits [3:0] of field 16 */
03144 
03145     /* Change State */
03146     hmmc->State = HAL_MMC_STATE_READY;
03147 
03148     return HAL_OK;
03149   }
03150   else
03151   {
03152     return HAL_BUSY;
03153   }
03154 }
03155 
03156 /**
03157   * @brief  Switch the device from Standby State to Sleep State.
03158   * @param  hmmc pointer to MMC handle
03159   * @retval HAL status
03160   */
03161 HAL_StatusTypeDef HAL_MMC_SleepDevice(MMC_HandleTypeDef *hmmc)
03162 {
03163   uint32_t errorstate,
03164            sleep_timeout,
03165            timeout,
03166            count,
03167            response = 0U  ;
03168   uint32_t tickstart = HAL_GetTick();
03169 
03170   /* Check the state of the driver */
03171   if (hmmc->State == HAL_MMC_STATE_READY)
03172   {
03173     /* Change State */
03174     hmmc->State = HAL_MMC_STATE_BUSY;
03175 
03176     /* Set the power-off notification to powered-on : Ext_CSD[34] = 1 */
03177     errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220100U));
03178     if (errorstate == HAL_MMC_ERROR_NONE)
03179     {
03180       /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03181       count = SDMMC_MAX_TRIAL;
03182       do
03183       {
03184         errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03185         if (errorstate != HAL_MMC_ERROR_NONE)
03186         {
03187           break;
03188         }
03189 
03190         /* Get command response */
03191         response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03192         count--;
03193       } while (((response & 0x100U) == 0U) && (count != 0U));
03194 
03195       /* Check the status after the switch command execution */
03196       if (count == 0U)
03197       {
03198         errorstate = SDMMC_ERROR_TIMEOUT;
03199       }
03200       else if (errorstate == HAL_MMC_ERROR_NONE)
03201       {
03202         /* Check the bit SWITCH_ERROR of the device status */
03203         if ((response & 0x80U) != 0U)
03204         {
03205           errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
03206         }
03207         else
03208         {
03209           /* Set the power-off notification to sleep notification : Ext_CSD[34] = 4 */
03210           errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220400U));
03211           if (errorstate == HAL_MMC_ERROR_NONE)
03212           {
03213             /* Field SLEEP_NOTIFICATION_TIME [216] */
03214             sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_INDEX / 4)] >>
03215                               MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_POS) & 0x000000FFU);
03216 
03217             /* Sleep/Awake Timeout = 10µs * 2^SLEEP_NOTIFICATION_TIME */
03218             /* In HAL, the tick interrupt occurs each ms */
03219             if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U))
03220             {
03221               sleep_timeout = 0x17U; /* Max register value defined is 0x17 */
03222             }
03223             timeout = (((1UL << sleep_timeout) / 100U) + 1U);
03224 
03225             /* Wait that the device is ready by checking the D0 line */
03226             while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
03227             {
03228               if ((HAL_GetTick() - tickstart) >= timeout)
03229               {
03230                 errorstate = SDMMC_ERROR_TIMEOUT;
03231               }
03232             }
03233 
03234             /* Clear the flag corresponding to end D0 bus line */
03235             __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
03236 
03237             if (errorstate == HAL_MMC_ERROR_NONE)
03238             {
03239               /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03240               count = SDMMC_MAX_TRIAL;
03241               do
03242               {
03243                 errorstate = SDMMC_CmdSendStatus(hmmc->Instance,
03244                                                  (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03245                 if (errorstate != HAL_MMC_ERROR_NONE)
03246                 {
03247                   break;
03248                 }
03249 
03250                 /* Get command response */
03251                 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03252                 count--;
03253               } while (((response & 0x100U) == 0U) && (count != 0U));
03254 
03255               /* Check the status after the switch command execution */
03256               if (count == 0U)
03257               {
03258                 errorstate = SDMMC_ERROR_TIMEOUT;
03259               }
03260               else if (errorstate == HAL_MMC_ERROR_NONE)
03261               {
03262                 /* Check the bit SWITCH_ERROR of the device status */
03263                 if ((response & 0x80U) != 0U)
03264                 {
03265                   errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
03266                 }
03267                 else
03268                 {
03269                   /* Switch the device in stand-by mode */
03270                   (void)SDMMC_CmdSelDesel(hmmc->Instance, 0U);
03271 
03272                   /* Field S_A_TIEMOUT [217] */
03273                   sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_S_A_TIMEOUT_INDEX / 4)] >>
03274                                     MMC_EXT_CSD_S_A_TIMEOUT_POS) & 0x000000FFU);
03275 
03276                   /* Sleep/Awake Timeout = 100ns * 2^S_A_TIMEOUT */
03277                   /* In HAL, the tick interrupt occurs each ms */
03278                   if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U))
03279                   {
03280                     sleep_timeout = 0x17U; /* Max register value defined is 0x17 */
03281                   }
03282                   timeout = (((1UL << sleep_timeout) / 10000U) + 1U);
03283 
03284                   if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_STANDBY)
03285                   {
03286                     /* Send CMD5 CMD_MMC_SLEEP_AWAKE with RCA and SLEEP as argument */
03287                     errorstate = SDMMC_CmdSleepMmc(hmmc->Instance,
03288                                                    ((hmmc->MmcCard.RelCardAdd << 16U) | (0x1U << 15U)));
03289                     if (errorstate == HAL_MMC_ERROR_NONE)
03290                     {
03291                       /* Wait that the device is ready by checking the D0 line */
03292                       while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
03293                       {
03294                         if ((HAL_GetTick() - tickstart) >= timeout)
03295                         {
03296                           errorstate = SDMMC_ERROR_TIMEOUT;
03297                         }
03298                       }
03299 
03300                       /* Clear the flag corresponding to end D0 bus line */
03301                       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
03302                     }
03303                   }
03304                   else
03305                   {
03306                     errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE;
03307                   }
03308                 }
03309               }
03310               else
03311               {
03312                 /* Nothing to do */
03313               }
03314             }
03315           }
03316         }
03317       }
03318       else
03319       {
03320         /* Nothing to do */
03321       }
03322     }
03323 
03324     /* Change State */
03325     hmmc->State = HAL_MMC_STATE_READY;
03326 
03327     /* Manage errors */
03328     if (errorstate != HAL_MMC_ERROR_NONE)
03329     {
03330       /* Clear all the static flags */
03331       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03332       hmmc->ErrorCode |= errorstate;
03333 
03334       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
03335       {
03336         return HAL_ERROR;
03337       }
03338       else
03339       {
03340         return HAL_TIMEOUT;
03341       }
03342     }
03343     else
03344     {
03345       return HAL_OK;
03346     }
03347   }
03348   else
03349   {
03350     return HAL_BUSY;
03351   }
03352 }
03353 
03354 /**
03355   * @brief  Switch the device from Sleep State to Standby State.
03356   * @param  hmmc pointer to MMC handle
03357   * @retval HAL status
03358   */
03359 HAL_StatusTypeDef HAL_MMC_AwakeDevice(MMC_HandleTypeDef *hmmc)
03360 {
03361   uint32_t errorstate;
03362   uint32_t sleep_timeout;
03363   uint32_t timeout;
03364   uint32_t count;
03365   uint32_t response = 0U;
03366   uint32_t tickstart = HAL_GetTick();
03367 
03368   /* Check the state of the driver */
03369   if (hmmc->State == HAL_MMC_STATE_READY)
03370   {
03371     /* Change State */
03372     hmmc->State = HAL_MMC_STATE_BUSY;
03373 
03374     /* Field S_A_TIEMOUT [217] */
03375     sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_S_A_TIMEOUT_INDEX / 4)] >> MMC_EXT_CSD_S_A_TIMEOUT_POS) &
03376                      0x000000FFU);
03377 
03378     /* Sleep/Awake Timeout = 100ns * 2^S_A_TIMEOUT */
03379     /* In HAL, the tick interrupt occurs each ms */
03380     if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U))
03381     {
03382       sleep_timeout = 0x17U; /* Max register value defined is 0x17 */
03383     }
03384     timeout = (((1UL << sleep_timeout) / 10000U) + 1U);
03385 
03386     /* Send CMD5 CMD_MMC_SLEEP_AWAKE with RCA and AWAKE as argument */
03387     errorstate = SDMMC_CmdSleepMmc(hmmc->Instance, (hmmc->MmcCard.RelCardAdd << 16U));
03388     if (errorstate == HAL_MMC_ERROR_NONE)
03389     {
03390       /* Wait that the device is ready by checking the D0 line */
03391       while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
03392       {
03393         if ((HAL_GetTick() - tickstart) >= timeout)
03394         {
03395           errorstate = SDMMC_ERROR_TIMEOUT;
03396         }
03397       }
03398 
03399       /* Clear the flag corresponding to end D0 bus line */
03400       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
03401 
03402       if (errorstate == HAL_MMC_ERROR_NONE)
03403       {
03404         if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_STANDBY)
03405         {
03406           /* Switch the device in transfer mode */
03407           errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (hmmc->MmcCard.RelCardAdd << 16U));
03408           if (errorstate == HAL_MMC_ERROR_NONE)
03409           {
03410             if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_TRANSFER)
03411             {
03412               /* Set the power-off notification to powered-on : Ext_CSD[34] = 1 */
03413               errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220100U));
03414               if (errorstate == HAL_MMC_ERROR_NONE)
03415               {
03416                 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03417                 count = SDMMC_MAX_TRIAL;
03418                 do
03419                 {
03420                   errorstate = SDMMC_CmdSendStatus(hmmc->Instance,
03421                                                    (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03422                   if (errorstate != HAL_MMC_ERROR_NONE)
03423                   {
03424                     break;
03425                   }
03426 
03427                   /* Get command response */
03428                   response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03429                   count--;
03430                 } while (((response & 0x100U) == 0U) && (count != 0U));
03431 
03432                 /* Check the status after the switch command execution */
03433                 if (count == 0U)
03434                 {
03435                   errorstate = SDMMC_ERROR_TIMEOUT;
03436                 }
03437                 else if (errorstate == HAL_MMC_ERROR_NONE)
03438                 {
03439                   /* Check the bit SWITCH_ERROR of the device status */
03440                   if ((response & 0x80U) != 0U)
03441                   {
03442                     errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
03443                   }
03444                 }
03445                 else
03446                 {
03447                   /* NOthing to do */
03448                 }
03449               }
03450             }
03451             else
03452             {
03453               errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE;
03454             }
03455           }
03456         }
03457         else
03458         {
03459           errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE;
03460         }
03461       }
03462     }
03463 
03464     /* Change State */
03465     hmmc->State = HAL_MMC_STATE_READY;
03466 
03467     /* Manage errors */
03468     if (errorstate != HAL_MMC_ERROR_NONE)
03469     {
03470       /* Clear all the static flags */
03471       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03472       hmmc->ErrorCode |= errorstate;
03473 
03474       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
03475       {
03476         return HAL_ERROR;
03477       }
03478       else
03479       {
03480         return HAL_TIMEOUT;
03481       }
03482     }
03483     else
03484     {
03485       return HAL_OK;
03486     }
03487   }
03488   else
03489   {
03490     return HAL_BUSY;
03491   }
03492 }
03493 /**
03494   * @}
03495   */
03496 
03497 /**
03498   * @}
03499   */
03500 
03501 /* Private function ----------------------------------------------------------*/
03502 /** @addtogroup MMC_Private_Functions
03503   * @{
03504   */
03505 
03506 
03507 /**
03508   * @brief  Initializes the mmc card.
03509   * @param  hmmc: Pointer to MMC handle
03510   * @retval MMC Card error state
03511   */
03512 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
03513 {
03514   HAL_MMC_CardCSDTypeDef CSD;
03515   uint32_t errorstate;
03516   uint16_t mmc_rca = 2U;
03517   MMC_InitTypeDef Init;
03518 
03519   /* Check the power State */
03520   if (SDMMC_GetPowerState(hmmc->Instance) == 0U)
03521   {
03522     /* Power off */
03523     return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
03524   }
03525 
03526   /* Send CMD2 ALL_SEND_CID */
03527   errorstate = SDMMC_CmdSendCID(hmmc->Instance);
03528   if (errorstate != HAL_MMC_ERROR_NONE)
03529   {
03530     return errorstate;
03531   }
03532   else
03533   {
03534     /* Get Card identification number data */
03535     hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03536     hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
03537     hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
03538     hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
03539   }
03540 
03541   /* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */
03542   /* MMC Card publishes its RCA. */
03543   errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca);
03544   if (errorstate != HAL_MMC_ERROR_NONE)
03545   {
03546     return errorstate;
03547   }
03548 
03549   /* Get the MMC card RCA */
03550   hmmc->MmcCard.RelCardAdd = mmc_rca;
03551 
03552   /* Send CMD9 SEND_CSD with argument as card's RCA */
03553   errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
03554   if (errorstate != HAL_MMC_ERROR_NONE)
03555   {
03556     return errorstate;
03557   }
03558   else
03559   {
03560     /* Get Card Specific Data */
03561     hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03562     hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
03563     hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
03564     hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
03565   }
03566 
03567   /* Get the Card Class */
03568   hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U);
03569 
03570   /* Select the Card */
03571   errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03572   if (errorstate != HAL_MMC_ERROR_NONE)
03573   {
03574     return errorstate;
03575   }
03576 
03577   /* Get CSD parameters */
03578   if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
03579   {
03580     return hmmc->ErrorCode;
03581   }
03582 
03583   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03584   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03585   if (errorstate != HAL_MMC_ERROR_NONE)
03586   {
03587     hmmc->ErrorCode |= errorstate;
03588   }
03589 
03590 
03591   /* Get Extended CSD parameters */
03592   if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != HAL_OK)
03593   {
03594     return hmmc->ErrorCode;
03595   }
03596 
03597   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03598   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03599   if (errorstate != HAL_MMC_ERROR_NONE)
03600   {
03601     hmmc->ErrorCode |= errorstate;
03602   }
03603 
03604   /* Configure the SDMMC peripheral */
03605   Init = hmmc->Init;
03606   Init.BusWide = SDMMC_BUS_WIDE_1B;
03607   (void)SDMMC_Init(hmmc->Instance, Init);
03608 
03609   /* All cards are initialized */
03610   return HAL_MMC_ERROR_NONE;
03611 }
03612 
03613 /**
03614   * @brief  Enquires cards about their operating voltage and configures clock
03615   *         controls and stores MMC information that will be needed in future
03616   *         in the MMC handle.
03617   * @param  hmmc: Pointer to MMC handle
03618   * @retval error state
03619   */
03620 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
03621 {
03622   __IO uint32_t count = 0U;
03623   uint32_t response = 0U;
03624   uint32_t validvoltage = 0U;
03625   uint32_t errorstate;
03626 
03627   /* CMD0: GO_IDLE_STATE */
03628   errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
03629   if (errorstate != HAL_MMC_ERROR_NONE)
03630   {
03631     return errorstate;
03632   }
03633 
03634   while (validvoltage == 0U)
03635   {
03636     if (count++ == SDMMC_MAX_VOLT_TRIAL)
03637     {
03638       return HAL_MMC_ERROR_INVALID_VOLTRANGE;
03639     }
03640 
03641     /* SEND CMD1 APP_CMD with voltage range as argument */
03642     errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE);
03643     if (errorstate != HAL_MMC_ERROR_NONE)
03644     {
03645       return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
03646     }
03647 
03648     /* Get command response */
03649     response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03650 
03651     /* Get operating voltage*/
03652     validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
03653   }
03654 
03655   /* When power routine is finished and command returns valid voltage */
03656   if (((response & (0xFF000000U)) >> 24) == 0xC0U)
03657   {
03658     hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
03659   }
03660   else
03661   {
03662     hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
03663   }
03664 
03665   return HAL_MMC_ERROR_NONE;
03666 }
03667 
03668 /**
03669   * @brief  Turns the SDMMC output signals off.
03670   * @param  hmmc: Pointer to MMC handle
03671   * @retval None
03672   */
03673 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
03674 {
03675   /* Set Power State to OFF */
03676   (void)SDMMC_PowerState_OFF(hmmc->Instance);
03677 }
03678 
03679 /**
03680   * @brief  Returns the current card's status.
03681   * @param  hmmc: Pointer to MMC handle
03682   * @param  pCardStatus: pointer to the buffer that will contain the MMC card
03683   *         status (Card Status register)
03684   * @retval error state
03685   */
03686 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
03687 {
03688   uint32_t errorstate;
03689 
03690   if (pCardStatus == NULL)
03691   {
03692     return HAL_MMC_ERROR_PARAM;
03693   }
03694 
03695   /* Send Status command */
03696   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
03697   if (errorstate != HAL_MMC_ERROR_NONE)
03698   {
03699     return errorstate;
03700   }
03701 
03702   /* Get MMC card status */
03703   *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03704 
03705   return HAL_MMC_ERROR_NONE;
03706 }
03707 
03708 /**
03709   * @brief  Reads extended CSD register to get the sectors number of the device
03710   * @param  hmmc: Pointer to MMC handle
03711   * @param  pFieldData: Pointer to the read buffer
03712   * @param  FieldIndex: Index of the field to be read
03713   * @param  Timeout: Specify timeout value
03714   * @retval HAL status
03715   */
03716 static HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData,
03717                                         uint16_t FieldIndex, uint32_t Timeout)
03718 {
03719   SDMMC_DataInitTypeDef config;
03720   uint32_t errorstate;
03721   uint32_t tickstart = HAL_GetTick();
03722   uint32_t count;
03723   uint32_t i = 0;
03724   uint32_t tmp_data;
03725 
03726   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
03727 
03728   /* Initialize data control register */
03729   hmmc->Instance->DCTRL = 0;
03730 
03731   /* Configure the MMC DPSM (Data Path State Machine) */
03732   config.DataTimeOut   = SDMMC_DATATIMEOUT;
03733   config.DataLength    = 512U;
03734   config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
03735   config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
03736   config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
03737   config.DPSM          = SDMMC_DPSM_ENABLE;
03738   (void)SDMMC_ConfigData(hmmc->Instance, &config);
03739 
03740   /* Set Block Size for Card */
03741   errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
03742   if (errorstate != HAL_MMC_ERROR_NONE)
03743   {
03744     /* Clear all the static flags */
03745     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03746     hmmc->ErrorCode |= errorstate;
03747     hmmc->State = HAL_MMC_STATE_READY;
03748     return HAL_ERROR;
03749   }
03750 
03751   /* Poll on SDMMC flags */
03752   while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
03753                              SDMMC_FLAG_DATAEND))
03754   {
03755     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
03756     {
03757       /* Read data from SDMMC Rx FIFO */
03758       for (count = 0U; count < 8U; count++)
03759       {
03760         tmp_data = SDMMC_ReadFIFO(hmmc->Instance);
03761         /* eg : SEC_COUNT   : FieldIndex = 212 => i+count = 53 */
03762         /*      DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
03763         if ((i + count) == ((uint32_t)FieldIndex / 4U))
03764         {
03765           *pFieldData = tmp_data;
03766         }
03767       }
03768       i += 8U;
03769     }
03770 
03771     if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
03772     {
03773       /* Clear all the static flags */
03774       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03775       hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
03776       hmmc->State = HAL_MMC_STATE_READY;
03777       return HAL_TIMEOUT;
03778     }
03779   }
03780 
03781   /* Get error state */
03782   if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
03783   {
03784     /* Clear all the static flags */
03785     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03786     hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
03787     hmmc->State = HAL_MMC_STATE_READY;
03788     return HAL_ERROR;
03789   }
03790   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
03791   {
03792     /* Clear all the static flags */
03793     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03794     hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
03795     hmmc->State = HAL_MMC_STATE_READY;
03796     return HAL_ERROR;
03797   }
03798   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
03799   {
03800     /* Clear all the static flags */
03801     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
03802     hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
03803     hmmc->State = HAL_MMC_STATE_READY;
03804     return HAL_ERROR;
03805   }
03806   else
03807   {
03808     /* Nothing to do */
03809   }
03810 
03811   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03812   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
03813   if (errorstate != HAL_MMC_ERROR_NONE)
03814   {
03815     hmmc->ErrorCode |= errorstate;
03816   }
03817 
03818   /* Clear all the static flags */
03819   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
03820 
03821   hmmc->State = HAL_MMC_STATE_READY;
03822 
03823   return HAL_OK;
03824 }
03825 
03826 /**
03827   * @brief  Wrap up reading in non-blocking mode.
03828   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
03829   *              the configuration information.
03830   * @retval None
03831   */
03832 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
03833 {
03834   uint32_t count;
03835   uint32_t data;
03836   uint8_t *tmp;
03837 
03838   tmp = hmmc->pRxBuffPtr;
03839 
03840   if (hmmc->RxXferSize >= 32U)
03841   {
03842     /* Read data from SDMMC Rx FIFO */
03843     for (count = 0U; count < 8U; count++)
03844     {
03845       data = SDMMC_ReadFIFO(hmmc->Instance);
03846       *tmp = (uint8_t)(data & 0xFFU);
03847       tmp++;
03848       *tmp = (uint8_t)((data >> 8U) & 0xFFU);
03849       tmp++;
03850       *tmp = (uint8_t)((data >> 16U) & 0xFFU);
03851       tmp++;
03852       *tmp = (uint8_t)((data >> 24U) & 0xFFU);
03853       tmp++;
03854     }
03855 
03856     hmmc->pRxBuffPtr = tmp;
03857     hmmc->RxXferSize -= 32U;
03858   }
03859 }
03860 
03861 /**
03862   * @brief  Wrap up writing in non-blocking mode.
03863   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
03864   *              the configuration information.
03865   * @retval None
03866   */
03867 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
03868 {
03869   uint32_t count;
03870   uint32_t data;
03871   uint8_t *tmp;
03872 
03873   tmp = hmmc->pTxBuffPtr;
03874 
03875   if (hmmc->TxXferSize >= 32U)
03876   {
03877     /* Write data to SDMMC Tx FIFO */
03878     for (count = 0U; count < 8U; count++)
03879     {
03880       data = (uint32_t)(*tmp);
03881       tmp++;
03882       data |= ((uint32_t)(*tmp) << 8U);
03883       tmp++;
03884       data |= ((uint32_t)(*tmp) << 16U);
03885       tmp++;
03886       data |= ((uint32_t)(*tmp) << 24U);
03887       tmp++;
03888       (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
03889     }
03890 
03891     hmmc->pTxBuffPtr = tmp;
03892     hmmc->TxXferSize -= 32U;
03893   }
03894 }
03895 
03896 /**
03897   * @brief  Switches the MMC card to high speed mode.
03898   * @param  hmmc: MMC handle
03899   * @param  state: State of high speed mode
03900   * @retval MMC Card error state
03901   */
03902 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state)
03903 {
03904   uint32_t errorstate = HAL_MMC_ERROR_NONE;
03905   uint32_t response = 0U;
03906   uint32_t count;
03907   uint32_t sdmmc_clk;
03908   SDMMC_InitTypeDef Init;
03909 
03910   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) && (state == DISABLE))
03911   {
03912     errorstate = MMC_PwrClassUpdate(hmmc, (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS), SDMMC_SPEED_MODE_DEFAULT);
03913     if (errorstate == HAL_MMC_ERROR_NONE)
03914     {
03915       /* Index : 185 - Value : 0 */
03916       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90000U);
03917     }
03918   }
03919 
03920   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) == 0U) && (state != DISABLE))
03921   {
03922     errorstate = MMC_PwrClassUpdate(hmmc, (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS), SDMMC_SPEED_MODE_HIGH);
03923     if (errorstate == HAL_MMC_ERROR_NONE)
03924     {
03925       /* Index : 185 - Value : 1 */
03926       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90100U);
03927     }
03928   }
03929 
03930   if (errorstate == HAL_MMC_ERROR_NONE)
03931   {
03932     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
03933     count = SDMMC_MAX_TRIAL;
03934     do
03935     {
03936       errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
03937       if (errorstate != HAL_MMC_ERROR_NONE)
03938       {
03939         break;
03940       }
03941 
03942       /* Get command response */
03943       response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
03944       count--;
03945     } while (((response & 0x100U) == 0U) && (count != 0U));
03946 
03947     /* Check the status after the switch command execution */
03948     if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
03949     {
03950       /* Check the bit SWITCH_ERROR of the device status */
03951       if ((response & 0x80U) != 0U)
03952       {
03953         errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
03954       }
03955       else
03956       {
03957         /* Configure high speed */
03958         Init.ClockEdge           = hmmc->Init.ClockEdge;
03959         Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
03960         Init.BusWide             = (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS);
03961         Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
03962 
03963         if (state == DISABLE)
03964         {
03965           Init.ClockDiv = hmmc->Init.ClockDiv;
03966           (void)SDMMC_Init(hmmc->Instance, Init);
03967 
03968           CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
03969         }
03970         else
03971         {
03972           /* High Speed Clock should be less or equal to 52MHz*/
03973           sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
03974 
03975           if (sdmmc_clk == 0U)
03976           {
03977             errorstate = SDMMC_ERROR_INVALID_PARAMETER;
03978           }
03979           else
03980           {
03981             if (sdmmc_clk <= MMC_HIGH_SPEED_FREQ)
03982             {
03983               Init.ClockDiv = 0;
03984             }
03985             else
03986             {
03987               Init.ClockDiv = (sdmmc_clk / (2U * MMC_HIGH_SPEED_FREQ)) + 1U;
03988             }
03989             (void)SDMMC_Init(hmmc->Instance, Init);
03990 
03991             SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
03992           }
03993         }
03994       }
03995     }
03996     else if (count == 0U)
03997     {
03998       errorstate = SDMMC_ERROR_TIMEOUT;
03999     }
04000     else
04001     {
04002       /* Nothing to do */
04003     }
04004   }
04005 
04006   return errorstate;
04007 }
04008 
04009 /**
04010   * @brief  Switches the MMC card to Double Data Rate (DDR) mode.
04011   * @param  hmmc: MMC handle
04012   * @param  state: State of DDR mode
04013   * @retval MMC Card error state
04014   */
04015 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state)
04016 {
04017   uint32_t errorstate = HAL_MMC_ERROR_NONE;
04018   uint32_t response = 0U;
04019   uint32_t count;
04020 
04021   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) && (state == DISABLE))
04022   {
04023     if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
04024     {
04025       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_4B, SDMMC_SPEED_MODE_HIGH);
04026       if (errorstate == HAL_MMC_ERROR_NONE)
04027       {
04028         /* Index : 183 - Value : 1 */
04029         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
04030       }
04031     }
04032     else
04033     {
04034       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_8B, SDMMC_SPEED_MODE_HIGH);
04035       if (errorstate == HAL_MMC_ERROR_NONE)
04036       {
04037         /* Index : 183 - Value : 2 */
04038         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
04039       }
04040     }
04041   }
04042 
04043   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) == 0U) && (state != DISABLE))
04044   {
04045     if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
04046     {
04047       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_4B, SDMMC_SPEED_MODE_DDR);
04048       if (errorstate == HAL_MMC_ERROR_NONE)
04049       {
04050         /* Index : 183 - Value : 5 */
04051         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70500U);
04052       }
04053     }
04054     else
04055     {
04056       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_8B, SDMMC_SPEED_MODE_DDR);
04057       if (errorstate == HAL_MMC_ERROR_NONE)
04058       {
04059         /* Index : 183 - Value : 6 */
04060         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70600U);
04061       }
04062     }
04063   }
04064 
04065   if (errorstate == HAL_MMC_ERROR_NONE)
04066   {
04067     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
04068     count = SDMMC_MAX_TRIAL;
04069     do
04070     {
04071       errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
04072       if (errorstate != HAL_MMC_ERROR_NONE)
04073       {
04074         break;
04075       }
04076 
04077       /* Get command response */
04078       response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
04079       count--;
04080     } while (((response & 0x100U) == 0U) && (count != 0U));
04081 
04082     /* Check the status after the switch command execution */
04083     if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
04084     {
04085       /* Check the bit SWITCH_ERROR of the device status */
04086       if ((response & 0x80U) != 0U)
04087       {
04088         errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
04089       }
04090       else
04091       {
04092         /* Configure DDR mode */
04093         if (state == DISABLE)
04094         {
04095           CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
04096         }
04097         else
04098         {
04099           SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
04100         }
04101       }
04102     }
04103     else if (count == 0U)
04104     {
04105       errorstate = SDMMC_ERROR_TIMEOUT;
04106     }
04107     else
04108     {
04109       /* Nothing to do */
04110     }
04111   }
04112 
04113   return errorstate;
04114 }
04115 
04116 /**
04117   * @brief  Update the power class of the device.
04118   * @param  hmmc MMC handle
04119   * @param  Wide Wide of MMC bus
04120   * @param  Speed Speed of the MMC bus
04121   * @retval MMC Card error state
04122   */
04123 static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide, uint32_t Speed)
04124 {
04125   uint32_t count;
04126   uint32_t response = 0U;
04127   uint32_t errorstate = HAL_MMC_ERROR_NONE;
04128   uint32_t power_class;
04129   uint32_t supported_pwr_class;
04130 
04131   if ((Wide == SDMMC_BUS_WIDE_8B) || (Wide == SDMMC_BUS_WIDE_4B))
04132   {
04133     power_class = 0U; /* Default value after power-on or software reset */
04134 
04135     /* Read the PowerClass field of the Extended CSD register */
04136     if (MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */
04137     {
04138       errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
04139     }
04140     else
04141     {
04142       power_class = ((power_class >> 24U) & 0x000000FFU);
04143     }
04144 
04145     /* Get the supported PowerClass field of the Extended CSD register */
04146     if (Speed == SDMMC_SPEED_MODE_DDR)
04147     {
04148       /* Field PWR_CL_DDR_52_xxx [238 or 239] */
04149       supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_DDR_52_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_DDR_52_POS) &
04150                              0x000000FFU);
04151     }
04152     else if (Speed == SDMMC_SPEED_MODE_HIGH)
04153     {
04154       /* Field PWR_CL_52_xxx [200 or 202] */
04155       supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_52_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_52_POS) &
04156                              0x000000FFU);
04157     }
04158     else
04159     {
04160       /* Field PWR_CL_26_xxx [201 or 203] */
04161       supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_26_POS) &
04162                              0x000000FFU);
04163     }
04164 
04165     if (errorstate == HAL_MMC_ERROR_NONE)
04166     {
04167       if (Wide == SDMMC_BUS_WIDE_8B)
04168       {
04169         /* Bit [7:4]: power class for 8-bits bus configuration - Bit [3:0]: power class for 4-bits bus configuration */
04170         supported_pwr_class = (supported_pwr_class >> 4U);
04171       }
04172 
04173       if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU))
04174       {
04175         /* Need to change current power class */
04176         errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U)));
04177 
04178         if (errorstate == HAL_MMC_ERROR_NONE)
04179         {
04180           /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
04181           count = SDMMC_MAX_TRIAL;
04182           do
04183           {
04184             errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
04185             if (errorstate != HAL_MMC_ERROR_NONE)
04186             {
04187               break;
04188             }
04189 
04190             /* Get command response */
04191             response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
04192             count--;
04193           } while (((response & 0x100U) == 0U) && (count != 0U));
04194 
04195           /* Check the status after the switch command execution */
04196           if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
04197           {
04198             /* Check the bit SWITCH_ERROR of the device status */
04199             if ((response & 0x80U) != 0U)
04200             {
04201               errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
04202             }
04203           }
04204           else if (count == 0U)
04205           {
04206             errorstate = SDMMC_ERROR_TIMEOUT;
04207           }
04208           else
04209           {
04210             /* Nothing to do */
04211           }
04212         }
04213       }
04214     }
04215   }
04216 
04217   return errorstate;
04218 }
04219 
04220 /**
04221   * @brief Read DMA Buffer 0 Transfer completed callbacks
04222   * @param hmmc: MMC handle
04223   * @retval None
04224   */
04225 __weak void HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc)
04226 {
04227   /* Prevent unused argument(s) compilation warning */
04228   UNUSED(hmmc);
04229 
04230   /* NOTE : This function should not be modified, when the callback is needed,
04231             the HAL_MMCEx_Read_DMADoubleBuf0CpltCallback can be implemented in the user file
04232    */
04233 }
04234 
04235 /**
04236   * @brief Read DMA Buffer 1 Transfer completed callbacks
04237   * @param hmmc: MMC handle
04238   * @retval None
04239   */
04240 __weak void HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc)
04241 {
04242   /* Prevent unused argument(s) compilation warning */
04243   UNUSED(hmmc);
04244 
04245   /* NOTE : This function should not be modified, when the callback is needed,
04246             the HAL_MMCEx_Read_DMADoubleBuf1CpltCallback can be implemented in the user file
04247    */
04248 }
04249 
04250 /**
04251   * @brief Write DMA Buffer 0 Transfer completed callbacks
04252   * @param hmmc: MMC handle
04253   * @retval None
04254   */
04255 __weak void HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc)
04256 {
04257   /* Prevent unused argument(s) compilation warning */
04258   UNUSED(hmmc);
04259 
04260   /* NOTE : This function should not be modified, when the callback is needed,
04261             the HAL_MMCEx_Write_DMADoubleBuf0CpltCallback can be implemented in the user file
04262    */
04263 }
04264 
04265 /**
04266   * @brief Write DMA Buffer 1 Transfer completed callbacks
04267   * @param hmmc: MMC handle
04268   * @retval None
04269   */
04270 __weak void HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc)
04271 {
04272   /* Prevent unused argument(s) compilation warning */
04273   UNUSED(hmmc);
04274 
04275   /* NOTE : This function should not be modified, when the callback is needed,
04276             the HAL_MMCEx_Write_DMADoubleBuf1CpltCallback can be implemented in the user file
04277    */
04278 }
04279 
04280 /**
04281   * @}
04282   */
04283 
04284 #endif /* HAL_MMC_MODULE_ENABLED */
04285 
04286 /**
04287   * @}
04288   */
04289 
04290 /**
04291   * @}
04292   */