STM32F439xx HAL User Manual
stm32f4xx_hal_mmc.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32f4xx_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   @verbatim
00014   ==============================================================================
00015                         ##### How to use this driver #####
00016   ==============================================================================
00017   [..]
00018     This driver implements a high level communication layer for read and write from/to 
00019     this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by 
00020     the user in HAL_MMC_MspInit() function (MSP layer).                             
00021     Basically, the MSP layer configuration should be the same as we provide in the 
00022     examples.
00023     You can easily tailor this configuration according to hardware resources.
00024 
00025   [..]
00026     This driver is a generic layered driver for SDMMC memories which uses the HAL 
00027     SDMMC driver functions to interface with MMC and eMMC cards devices. 
00028     It is used as follows:
00029  
00030     (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
00031         (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE(); 
00032         (##) SDMMC pins configuration for MMC card
00033             (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();   
00034             (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
00035                   and according to your pin assignment;
00036         (##) DMA Configuration if you need to use DMA process (HAL_MMC_ReadBlocks_DMA()
00037              and HAL_MMC_WriteBlocks_DMA() APIs).
00038             (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE(); 
00039             (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled. 
00040         (##) NVIC configuration if you need to use interrupt process when using DMA transfer.
00041             (+++) Configure the SDMMC and DMA interrupt priorities using functions
00042                   HAL_NVIC_SetPriority(); DMA priority is superior to SDMMC's priority
00043             (+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ()
00044             (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT() 
00045                   and __HAL_MMC_DISABLE_IT() inside the communication process.
00046             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
00047                   and __HAL_MMC_CLEAR_IT()
00048         (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
00049              and HAL_MMC_WriteBlocks_IT() APIs).
00050             (+++) Configure the SDMMC interrupt priorities using function
00051                   HAL_NVIC_SetPriority();
00052             (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
00053             (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT() 
00054                   and __HAL_MMC_DISABLE_IT() inside the communication process.
00055             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
00056                   and __HAL_MMC_CLEAR_IT()
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 IP (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 / (ClockDiv + 2)
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 is set to 24MHz. You can change or adapt this frequency by adjusting 
00090         the "ClockDiv" field.
00091         In transfer mode and according to the MMC Card standard, make sure that the 
00092         SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
00093         To be able to use a frequency higher than 24MHz, you should use the SDMMC 
00094         peripheral in bypass mode. Refer to the corresponding reference manual 
00095         for more details.
00096   
00097     (#) Select the corresponding MMC Card according to the address read with the step 2.
00098     
00099     (#) Configure the MMC Card in wide bus mode: 4-bits data.
00100   
00101   *** MMC Card Read operation ***
00102   ==============================
00103   [..] 
00104     (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks(). 
00105         This function allows the read of 512 bytes blocks.
00106         You can choose either one block read operation or multiple block read operation 
00107         by adjusting the "NumberOfBlocks" parameter.
00108         After this, you have to ensure that the transfer is done correctly. The check is done
00109         through HAL_MMC_GetCardState() function for MMC card state.
00110 
00111     (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
00112         This function allows the read of 512 bytes blocks.
00113         You can choose either one block read operation or multiple block read operation 
00114         by adjusting the "NumberOfBlocks" parameter.
00115         After this, you have to ensure that the transfer is done correctly. The check is done
00116         through HAL_MMC_GetCardState() function for MMC card state.
00117         You could also check the DMA transfer process through the MMC Rx interrupt event.
00118 
00119     (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
00120         This function allows the read of 512 bytes blocks.
00121         You can choose either one block read operation or multiple block read operation 
00122         by adjusting the "NumberOfBlocks" parameter.
00123         After this, you have to ensure that the transfer is done correctly. The check is done
00124         through HAL_MMC_GetCardState() function for MMC card state.
00125         You could also check the IT transfer process through the MMC Rx interrupt event.
00126   
00127   *** MMC Card Write operation ***
00128   =============================== 
00129   [..] 
00130     (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks(). 
00131         This function allows the read of 512 bytes blocks.
00132         You can choose either one block read operation or multiple block read operation 
00133         by adjusting the "NumberOfBlocks" parameter.
00134         After this, you have to ensure that the transfer is done correctly. The check is done
00135         through HAL_MMC_GetCardState() function for MMC card state.
00136 
00137     (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
00138         This function allows the read of 512 bytes blocks.
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 status ***
00154   ====================== 
00155   [..]
00156     (+) The MMC Status contains status bits that are related to the MMC Memory 
00157         Card proprietary features. To get MMC card status use the HAL_MMC_GetCardStatus().
00158 
00159   *** MMC card information ***
00160   =========================== 
00161   [..]
00162     (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
00163         It returns useful information about the MMC card such as block size, card type,
00164         block number ...
00165 
00166   *** MMC card CSD register ***
00167   ============================
00168   [..]
00169     (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
00170         Some of the CSD parameters are useful for card initialization and identification.
00171 
00172   *** MMC card CID register ***
00173   ============================
00174   [..]
00175     (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
00176         Some of the CID parameters are useful for card initialization and identification.
00177 
00178   *** MMC HAL driver macros list ***
00179   ==================================
00180   [..]
00181     Below the list of most used macros in MMC HAL driver.
00182        
00183     (+) __HAL_MMC_ENABLE : Enable the MMC device
00184     (+) __HAL_MMC_DISABLE : Disable the MMC device
00185     (+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer
00186     (+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer
00187     (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
00188     (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
00189     (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
00190     (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
00191     
00192    [..]
00193     (@) You can refer to the MMC HAL driver header file for more useful macros 
00194       
00195   @endverbatim
00196   ******************************************************************************
00197   * @attention
00198   *
00199   * <h2><center>&copy; COPYRIGHT(c) 2017 STMicroelectronics</center></h2>
00200   *
00201   * Redistribution and use in source and binary forms, with or without modification,
00202   * are permitted provided that the following conditions are met:
00203   *   1. Redistributions of source code must retain the above copyright notice,
00204   *      this list of conditions and the following disclaimer.
00205   *   2. Redistributions in binary form must reproduce the above copyright notice,
00206   *      this list of conditions and the following disclaimer in the documentation
00207   *      and/or other materials provided with the distribution.
00208   *   3. Neither the name of STMicroelectronics nor the names of its contributors
00209   *      may be used to endorse or promote products derived from this software
00210   *      without specific prior written permission.
00211   *
00212   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00213   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00214   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00215   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
00216   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00217   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00218   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00219   * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00220   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
00221   * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00222   *
00223   ******************************************************************************
00224   */ 
00225 
00226 /* Includes ------------------------------------------------------------------*/
00227 #include "stm32f4xx_hal.h"
00228 
00229 /** @addtogroup STM32F4xx_HAL_Driver
00230   * @{
00231   */
00232 
00233 /** @addtogroup MMC 
00234   * @{
00235   */
00236 
00237 #ifdef HAL_MMC_MODULE_ENABLED
00238 
00239 #if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || \
00240     defined(STM32F427xx) || defined(STM32F437xx) || defined(STM32F429xx) || defined(STM32F439xx) || \
00241     defined(STM32F401xC) || defined(STM32F401xE) || defined(STM32F411xE) || defined(STM32F446xx) || \
00242     defined(STM32F469xx) || defined(STM32F479xx) || defined(STM32F412Zx) || defined(STM32F412Vx) || \
00243     defined(STM32F412Rx) || defined(STM32F412Cx) || defined(STM32F413xx) || defined(STM32F423xx)
00244 
00245 /* Private typedef -----------------------------------------------------------*/
00246 /* Private define ------------------------------------------------------------*/
00247 /** @addtogroup MMC_Private_Defines
00248   * @{
00249   */
00250     
00251 /**
00252   * @}
00253   */
00254   
00255 /* Private macro -------------------------------------------------------------*/
00256 /* Private variables ---------------------------------------------------------*/
00257 /* Private function prototypes -----------------------------------------------*/
00258 /* Private functions ---------------------------------------------------------*/
00259 /** @defgroup MMC_Private_Functions MMC Private Functions
00260   * @{
00261   */
00262 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
00263 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);                      
00264 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
00265 static HAL_StatusTypeDef MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
00266 static HAL_StatusTypeDef MMC_Write_IT(MMC_HandleTypeDef *hmmc);
00267 static HAL_StatusTypeDef MMC_Read_IT(MMC_HandleTypeDef *hmmc);
00268 static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma);
00269 static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
00270 static void MMC_DMAError(DMA_HandleTypeDef *hdma);
00271 static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
00272 static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
00273 /**
00274   * @}
00275   */
00276 
00277 /* Exported functions --------------------------------------------------------*/
00278 /** @addtogroup MMC_Exported_Functions
00279   * @{
00280   */
00281 
00282 /** @addtogroup MMC_Exported_Functions_Group1
00283  *  @brief   Initialization and de-initialization functions 
00284  *
00285 @verbatim    
00286   ==============================================================================
00287           ##### Initialization and de-initialization functions #####
00288   ==============================================================================
00289   [..]  
00290     This section provides functions allowing to initialize/de-initialize the MMC
00291     card device to be ready for use.
00292 
00293 @endverbatim
00294   * @{
00295   */
00296 
00297 /**
00298   * @brief  Initializes the MMC according to the specified parameters in the 
00299             MMC_HandleTypeDef and create the associated handle.
00300   * @param  hmmc Pointer to the MMC handle  
00301   * @retval HAL status
00302   */
00303 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
00304 {
00305   /* Check the MMC handle allocation */
00306   if(hmmc == NULL)
00307   {
00308     return HAL_ERROR;
00309   }
00310 
00311   /* Check the parameters */
00312   assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
00313   assert_param(IS_SDIO_CLOCK_EDGE(hmmc->Init.ClockEdge));
00314   assert_param(IS_SDIO_CLOCK_BYPASS(hmmc->Init.ClockBypass));
00315   assert_param(IS_SDIO_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
00316   assert_param(IS_SDIO_BUS_WIDE(hmmc->Init.BusWide));
00317   assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
00318   assert_param(IS_SDIO_CLKDIV(hmmc->Init.ClockDiv));
00319 
00320   if(hmmc->State == HAL_MMC_STATE_RESET)
00321   {
00322     /* Allocate lock resource and initialize it */
00323     hmmc->Lock = HAL_UNLOCKED;
00324     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
00325     HAL_MMC_MspInit(hmmc);
00326   }
00327 
00328   hmmc->State = HAL_MMC_STATE_BUSY;
00329 
00330   /* Initialize the Card parameters */
00331   HAL_MMC_InitCard(hmmc);
00332 
00333   /* Initialize the error code */
00334   hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
00335   
00336   /* Initialize the MMC operation */
00337   hmmc->Context = MMC_CONTEXT_NONE;
00338                                                                                      
00339   /* Initialize the MMC state */
00340   hmmc->State = HAL_MMC_STATE_READY;
00341 
00342   return HAL_OK;
00343 }
00344 
00345 /**
00346   * @brief  Initializes the MMC Card.
00347   * @param  hmmc Pointer to MMC handle
00348   * @note   This function initializes the MMC card. It could be used when a card 
00349             re-initialization is needed.
00350   * @retval HAL status
00351   */
00352 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
00353 {
00354   uint32_t errorstate = HAL_MMC_ERROR_NONE;
00355   MMC_InitTypeDef Init;
00356   
00357   /* Default SDMMC peripheral configuration for MMC card initialization */
00358   Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
00359   Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
00360   Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
00361   Init.BusWide             = SDIO_BUS_WIDE_1B;
00362   Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
00363   Init.ClockDiv            = SDIO_INIT_CLK_DIV;
00364 
00365   /* Initialize SDMMC peripheral interface with default configuration */
00366   SDIO_Init(hmmc->Instance, Init);
00367 
00368   /* Disable SDMMC Clock */
00369   __HAL_MMC_DISABLE(hmmc); 
00370   
00371   /* Set Power State to ON */
00372   SDIO_PowerState_ON(hmmc->Instance);
00373   
00374   /* Enable SDMMC Clock */
00375   __HAL_MMC_ENABLE(hmmc);
00376   
00377   /* Required power up waiting time before starting the SD initialization 
00378   sequence */
00379   HAL_Delay(2U);
00380   
00381   /* Identify card operating voltage */
00382   errorstate = MMC_PowerON(hmmc);
00383   if(errorstate != HAL_MMC_ERROR_NONE)
00384   {
00385     hmmc->State = HAL_MMC_STATE_READY;
00386     hmmc->ErrorCode |= errorstate;
00387     return HAL_ERROR;
00388   }
00389 
00390   /* Card initialization */
00391   errorstate = MMC_InitCard(hmmc);
00392   if(errorstate != HAL_MMC_ERROR_NONE)
00393   {
00394     hmmc->State = HAL_MMC_STATE_READY;
00395     hmmc->ErrorCode |= errorstate;
00396     return HAL_ERROR;
00397   }
00398 
00399   return HAL_OK;
00400 }
00401 
00402 /**
00403   * @brief  De-Initializes the MMC card.
00404   * @param  hmmc Pointer to MMC handle
00405   * @retval HAL status
00406   */
00407 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
00408 {
00409   /* Check the MMC handle allocation */
00410   if(hmmc == NULL)
00411   {
00412     return HAL_ERROR;
00413   }
00414   
00415   /* Check the parameters */
00416   assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
00417 
00418   hmmc->State = HAL_MMC_STATE_BUSY;
00419   
00420   /* Set SD power state to off */ 
00421   MMC_PowerOFF(hmmc);
00422   
00423   /* De-Initialize the MSP layer */
00424   HAL_MMC_MspDeInit(hmmc);
00425   
00426   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
00427   hmmc->State = HAL_MMC_STATE_RESET;
00428   
00429   return HAL_OK;
00430 }
00431 
00432 
00433 /**
00434   * @brief  Initializes the MMC MSP.
00435   * @param  hmmc Pointer to MMC handle
00436   * @retval None
00437   */
00438 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
00439 {
00440   /* Prevent unused argument(s) compilation warning */
00441   UNUSED(hmmc);
00442  
00443   /* NOTE : This function Should not be modified, when the callback is needed,
00444             the HAL_MMC_MspInit could be implemented in the user file
00445    */
00446 }
00447 
00448 /**
00449   * @brief  De-Initialize MMC MSP.
00450   * @param  hmmc Pointer to MMC handle
00451   * @retval None
00452   */
00453 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
00454 {
00455   /* Prevent unused argument(s) compilation warning */
00456   UNUSED(hmmc);
00457  
00458   /* NOTE : This function Should not be modified, when the callback is needed,
00459             the HAL_MMC_MspDeInit could be implemented in the user file
00460    */
00461 }
00462 
00463 /**
00464   * @}
00465   */
00466 
00467 /** @addtogroup MMC_Exported_Functions_Group2
00468  *  @brief   Data transfer functions 
00469  *
00470 @verbatim   
00471   ==============================================================================
00472                         ##### IO operation functions #####
00473   ==============================================================================  
00474   [..]
00475     This subsection provides a set of functions allowing to manage the data 
00476     transfer from/to MMC card.
00477 
00478 @endverbatim
00479   * @{
00480   */
00481 
00482 /**
00483   * @brief  Reads block(s) from a specified address in a card. The Data transfer 
00484   *         is managed by polling mode.
00485   * @note   This API should be followed by a check on the card state through
00486   *         HAL_MMC_GetCardState().
00487   * @param  hmmc Pointer to MMC handle
00488   * @param  pData pointer to the buffer that will contain the received data
00489   * @param  BlockAdd Block Address from where data is to be read 
00490   * @param  NumberOfBlocks Number of MMC blocks to read
00491   * @param  Timeout Specify timeout value
00492   * @retval HAL status
00493   */
00494 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
00495 {
00496   SDIO_DataInitTypeDef config;
00497   uint32_t errorstate = HAL_MMC_ERROR_NONE;
00498   uint32_t tickstart = HAL_GetTick();
00499   uint32_t count = 0U, *tempbuff = (uint32_t *)pData;
00500   
00501   if(NULL == pData)
00502   {
00503     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00504     return HAL_ERROR;
00505   }
00506  
00507   if(hmmc->State == HAL_MMC_STATE_READY)
00508   {
00509     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
00510     
00511     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00512     {
00513       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00514       return HAL_ERROR;
00515     }
00516     
00517     hmmc->State = HAL_MMC_STATE_BUSY;
00518     
00519     /* Initialize data control register */
00520     hmmc->Instance->DCTRL = 0U;
00521     
00522     /* Check the Card capacity in term of Logical number of blocks */
00523     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
00524     {
00525       BlockAdd *= 512U;
00526     }
00527 
00528     /* Set Block Size for Card */
00529     errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
00530     if(errorstate != HAL_MMC_ERROR_NONE)
00531     {
00532       /* Clear all the static flags */
00533       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);      
00534       hmmc->ErrorCode |= errorstate;
00535       hmmc->State = HAL_MMC_STATE_READY;
00536       return HAL_ERROR;
00537     }
00538     
00539     /* Configure the MMC DPSM (Data Path State Machine) */
00540     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00541     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
00542     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
00543     config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
00544     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
00545     config.DPSM          = SDIO_DPSM_ENABLE;
00546     SDIO_ConfigData(hmmc->Instance, &config);
00547     
00548     /* Read block(s) in polling mode */
00549     if(NumberOfBlocks > 1U)
00550     {
00551       hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
00552       
00553       /* Read Multi Block command */ 
00554       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, BlockAdd);
00555     }
00556     else
00557     {
00558       hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
00559       
00560       /* Read Single Block command */
00561       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, BlockAdd);
00562     }
00563     if(errorstate != HAL_MMC_ERROR_NONE)
00564     {
00565       /* Clear all the static flags */
00566       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00567       hmmc->ErrorCode |= errorstate;
00568       hmmc->State = HAL_MMC_STATE_READY;
00569       return HAL_ERROR;
00570     }
00571       
00572     /* Poll on SDMMC flags */
00573 #ifdef SDIO_STA_STBITERR
00574     while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_STA_STBITERR))
00575 #else /* SDIO_STA_STBITERR not defined */
00576     while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
00577 #endif /* SDIO_STA_STBITERR */
00578     {
00579       if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
00580       {
00581         /* Read data from SDMMC Rx FIFO */
00582         for(count = 0U; count < 8U; count++)
00583         {
00584           *(tempbuff + count) = SDIO_ReadFIFO(hmmc->Instance);
00585         }
00586         tempbuff += 8U;
00587       }
00588       
00589       if((Timeout == 0U)||((HAL_GetTick()-tickstart) >=  Timeout))
00590       {
00591         /* Clear all the static flags */
00592         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00593         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
00594         hmmc->State= HAL_MMC_STATE_READY;
00595         return HAL_TIMEOUT;
00596       }
00597     }
00598     
00599     /* Send stop transmission command in case of multiblock read */
00600     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
00601     {    
00602       /* Send stop transmission command */
00603       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
00604       if(errorstate != HAL_MMC_ERROR_NONE)
00605       {
00606         /* Clear all the static flags */
00607         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00608         hmmc->ErrorCode |= errorstate;
00609         hmmc->State = HAL_MMC_STATE_READY;
00610         return HAL_ERROR;
00611       }
00612     }
00613     
00614     /* Get error state */
00615     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
00616     {
00617       /* Clear all the static flags */
00618       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00619       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
00620       hmmc->State = HAL_MMC_STATE_READY;
00621       return HAL_ERROR;
00622     }
00623     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
00624     {
00625       /* Clear all the static flags */
00626       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00627       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
00628       hmmc->State = HAL_MMC_STATE_READY;
00629       return HAL_ERROR;
00630     }
00631     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
00632     {
00633       /* Clear all the static flags */
00634       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00635       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
00636       hmmc->State = HAL_MMC_STATE_READY;
00637       return HAL_ERROR;
00638     }
00639     
00640     /* Empty FIFO if there is still any data */
00641     while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)))
00642     {
00643       *tempbuff = SDIO_ReadFIFO(hmmc->Instance);
00644       tempbuff++;
00645       
00646       if((Timeout == 0U)||((HAL_GetTick()-tickstart) >=  Timeout))
00647       {
00648         /* Clear all the static flags */
00649         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);        
00650         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
00651         hmmc->State= HAL_MMC_STATE_READY;
00652         return HAL_ERROR;
00653       }
00654     }
00655     
00656     /* Clear all the static flags */
00657     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
00658     
00659     hmmc->State = HAL_MMC_STATE_READY;
00660     
00661     return HAL_OK;
00662   }
00663   else
00664   {
00665     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
00666     return HAL_ERROR;
00667   }
00668 }
00669 
00670 /**
00671   * @brief  Allows to write block(s) to a specified address in a card. The Data
00672   *         transfer is managed by polling mode.
00673   * @note   This API should be followed by a check on the card state through
00674   *         HAL_MMC_GetCardState().
00675   * @param  hmmc Pointer to MMC handle
00676   * @param  pData pointer to the buffer that will contain the data to transmit
00677   * @param  BlockAdd Block Address where data will be written  
00678   * @param  NumberOfBlocks Number of MMC blocks to write
00679   * @param  Timeout Specify timeout value
00680   * @retval HAL status
00681   */
00682 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
00683 {
00684   SDIO_DataInitTypeDef config;
00685   uint32_t errorstate = HAL_MMC_ERROR_NONE;
00686   uint32_t tickstart = HAL_GetTick();
00687   uint32_t count = 0U;
00688   uint32_t *tempbuff = (uint32_t *)pData;
00689   
00690   if(NULL == pData)
00691   {
00692     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00693     return HAL_ERROR;
00694   }
00695 
00696   if(hmmc->State == HAL_MMC_STATE_READY)
00697   {
00698     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
00699     
00700     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00701     {
00702       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00703       return HAL_ERROR;
00704     }
00705     
00706     hmmc->State = HAL_MMC_STATE_BUSY;
00707     
00708     /* Initialize data control register */
00709     hmmc->Instance->DCTRL = 0U;
00710     
00711     /* Check the Card capacity in term of Logical number of blocks */
00712     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
00713     {
00714       BlockAdd *= 512U;
00715     }
00716     
00717     /* Set Block Size for Card */ 
00718     errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
00719     if(errorstate != HAL_MMC_ERROR_NONE)
00720     {
00721       /* Clear all the static flags */
00722       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);  
00723       hmmc->ErrorCode |= errorstate;
00724       hmmc->State = HAL_MMC_STATE_READY;
00725       return HAL_ERROR;
00726     }
00727     
00728     /* Write Blocks in Polling mode */
00729     if(NumberOfBlocks > 1U)
00730     {
00731       hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
00732       
00733       /* Write Multi Block command */ 
00734       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, BlockAdd);
00735     }
00736     else
00737     {
00738       hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
00739       
00740       /* Write Single Block command */
00741       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, BlockAdd);
00742     }
00743     if(errorstate != HAL_MMC_ERROR_NONE)
00744     {
00745       /* Clear all the static flags */
00746       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);  
00747       hmmc->ErrorCode |= errorstate;
00748       hmmc->State = HAL_MMC_STATE_READY;
00749       return HAL_ERROR;
00750     }
00751     
00752     /* Configure the MMC DPSM (Data Path State Machine) */ 
00753     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00754     config.DataLength    = NumberOfBlocks * BLOCKSIZE;
00755     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
00756     config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
00757     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
00758     config.DPSM          = SDIO_DPSM_ENABLE;
00759     SDIO_ConfigData(hmmc->Instance, &config);
00760     
00761     /* Write block(s) in polling mode */
00762 #ifdef SDIO_STA_STBITERR
00763     while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
00764 #else /* SDIO_STA_STBITERR not defined */
00765     while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
00766 #endif /* SDIO_STA_STBITERR */
00767     {
00768       if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE))
00769       {
00770         /* Write data to SDIO Tx FIFO */
00771         for(count = 0U; count < 8U; count++)
00772         {
00773           SDIO_WriteFIFO(hmmc->Instance, (tempbuff + count));
00774         }
00775         tempbuff += 8U;
00776       }
00777       
00778       if((Timeout == 0U)||((HAL_GetTick()-tickstart) >=  Timeout))
00779       {
00780         /* Clear all the static flags */
00781         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);  
00782         hmmc->ErrorCode |= errorstate;
00783         hmmc->State = HAL_MMC_STATE_READY;
00784         return HAL_TIMEOUT;
00785       }
00786     }
00787     
00788     /* Send stop transmission command in case of multiblock write */
00789     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
00790     { 
00791       /* Send stop transmission command */
00792       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
00793       if(errorstate != HAL_MMC_ERROR_NONE)
00794       {
00795         /* Clear all the static flags */
00796         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);  
00797         hmmc->ErrorCode |= errorstate;
00798         hmmc->State = HAL_MMC_STATE_READY;
00799         return HAL_ERROR;
00800       }
00801     }
00802     
00803     /* Get error state */
00804     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
00805     {
00806       /* Clear all the static flags */
00807       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
00808       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
00809       hmmc->State = HAL_MMC_STATE_READY;
00810       return HAL_ERROR;
00811     }
00812     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
00813     {
00814       /* Clear all the static flags */
00815       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
00816       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;      
00817       hmmc->State = HAL_MMC_STATE_READY;
00818       return HAL_ERROR;
00819     }
00820     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR))
00821     {
00822       /* Clear all the static flags */
00823       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
00824       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
00825       hmmc->State = HAL_MMC_STATE_READY;
00826       return HAL_ERROR;
00827     }
00828     
00829     /* Clear all the static flags */
00830     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
00831     
00832     hmmc->State = HAL_MMC_STATE_READY;
00833     
00834     return HAL_OK;
00835   }
00836   else
00837   {
00838     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
00839     return HAL_ERROR;
00840   }
00841 }
00842 
00843 /**
00844   * @brief  Reads block(s) from a specified address in a card. The Data transfer 
00845   *         is managed in interrupt mode. 
00846   * @note   This API should be followed by a check on the card state through
00847   *         HAL_MMC_GetCardState().
00848   * @note   You could also check the IT transfer process through the MMC Rx 
00849   *         interrupt event.
00850   * @param  hmmc Pointer to MMC handle                 
00851   * @param  pData Pointer to the buffer that will contain the received data
00852   * @param  BlockAdd Block Address from where data is to be read 
00853   * @param  NumberOfBlocks Number of blocks to read.
00854   * @retval HAL status
00855   */
00856 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
00857 {
00858   SDIO_DataInitTypeDef config;
00859   uint32_t errorstate = HAL_MMC_ERROR_NONE;
00860   
00861   if(NULL == pData)
00862   {
00863     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00864     return HAL_ERROR;
00865   }
00866   
00867   if(hmmc->State == HAL_MMC_STATE_READY)
00868   {
00869     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
00870     
00871     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00872     {
00873       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00874       return HAL_ERROR;
00875     }
00876     
00877     hmmc->State = HAL_MMC_STATE_BUSY;
00878     
00879     /* Initialize data control register */
00880     hmmc->Instance->DCTRL = 0U;
00881     
00882     hmmc->pRxBuffPtr = (uint32_t *)pData;
00883     hmmc->RxXferSize = BLOCKSIZE * NumberOfBlocks;
00884     
00885     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
00886 
00887     /* Check the Card capacity in term of Logical number of blocks */
00888     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
00889     {
00890       BlockAdd *= 512U;
00891     }
00892     
00893     /* Configure the MMC DPSM (Data Path State Machine) */ 
00894     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00895     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
00896     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
00897     config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
00898     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
00899     config.DPSM          = SDIO_DPSM_ENABLE;
00900     SDIO_ConfigData(hmmc->Instance, &config);
00901     
00902     /* Set Block Size for Card */ 
00903     errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
00904     if(errorstate != HAL_MMC_ERROR_NONE)
00905     {
00906       /* Clear all the static flags */
00907       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
00908       hmmc->ErrorCode |= errorstate;
00909       hmmc->State = HAL_MMC_STATE_READY;
00910       return HAL_ERROR;
00911     }
00912 
00913     /* Read Blocks in IT mode */
00914     if(NumberOfBlocks > 1U)
00915     {
00916       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
00917       
00918       /* Read Multi Block command */
00919       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, BlockAdd);
00920     }
00921     else
00922     {
00923       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
00924       
00925       /* Read Single Block command */
00926       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, BlockAdd);
00927     }
00928     if(errorstate != HAL_MMC_ERROR_NONE)
00929     {
00930       /* Clear all the static flags */
00931       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
00932       hmmc->ErrorCode |= errorstate;
00933       hmmc->State = HAL_MMC_STATE_READY;
00934       return HAL_ERROR;
00935     }
00936     
00937     return HAL_OK;
00938   }
00939   else
00940   {
00941     return HAL_BUSY;
00942   }
00943 }
00944 
00945 /**
00946   * @brief  Writes block(s) to a specified address in a card. The Data transfer 
00947   *         is managed in interrupt mode. 
00948   * @note   This API should be followed by a check on the card state through
00949   *         HAL_MMC_GetCardState().
00950   * @note   You could also check the IT transfer process through the MMC Tx 
00951   *         interrupt event. 
00952   * @param  hmmc Pointer to MMC handle
00953   * @param  pData Pointer to the buffer that will contain the data to transmit
00954   * @param  BlockAdd Block Address where data will be written    
00955   * @param  NumberOfBlocks Number of blocks to write
00956   * @retval HAL status
00957   */
00958 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
00959 {
00960   SDIO_DataInitTypeDef config;
00961   uint32_t errorstate = HAL_MMC_ERROR_NONE;
00962   
00963   if(NULL == pData)
00964   {
00965     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
00966     return HAL_ERROR;
00967   }
00968   
00969   if(hmmc->State == HAL_MMC_STATE_READY)
00970   {
00971     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
00972     
00973     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00974     {
00975       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00976       return HAL_ERROR;
00977     }
00978     
00979     hmmc->State = HAL_MMC_STATE_BUSY;
00980     
00981     /* Initialize data control register */
00982     hmmc->Instance->DCTRL = 0U;
00983   
00984     hmmc->pTxBuffPtr = (uint32_t *)pData;
00985     hmmc->TxXferSize = BLOCKSIZE * NumberOfBlocks;
00986     
00987     /* Enable transfer interrupts */
00988     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE)); 
00989     
00990     /* Check the Card capacity in term of Logical number of blocks */
00991     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
00992     {
00993       BlockAdd *= 512U;
00994     }
00995     
00996     /* Set Block Size for Card */ 
00997     errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
00998     if(errorstate != HAL_MMC_ERROR_NONE)
00999     {
01000       /* Clear all the static flags */
01001       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
01002       hmmc->ErrorCode |= errorstate;
01003       hmmc->State = HAL_MMC_STATE_READY;
01004       return HAL_ERROR;
01005     }
01006     
01007     /* Write Blocks in Polling mode */
01008     if(NumberOfBlocks > 1U)
01009     {
01010       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
01011       
01012       /* Write Multi Block command */ 
01013       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, BlockAdd);
01014     }
01015     else
01016     {
01017       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
01018       
01019       /* Write Single Block command */ 
01020       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, BlockAdd);
01021     }
01022     if(errorstate != HAL_MMC_ERROR_NONE)
01023     {
01024       /* Clear all the static flags */
01025       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
01026       hmmc->ErrorCode |= errorstate;
01027       hmmc->State = HAL_MMC_STATE_READY;
01028       return HAL_ERROR;
01029     }
01030     
01031     /* Configure the MMC DPSM (Data Path State Machine) */ 
01032     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01033     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
01034     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
01035     config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
01036     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
01037     config.DPSM          = SDIO_DPSM_ENABLE;
01038     SDIO_ConfigData(hmmc->Instance, &config);
01039     
01040     return HAL_OK;
01041   }
01042   else
01043   {
01044     return HAL_BUSY;
01045   }
01046 }
01047 
01048 /**
01049   * @brief  Reads block(s) from a specified address in a card. The Data transfer 
01050   *         is managed by DMA mode. 
01051   * @note   This API should be followed by a check on the card state through
01052   *         HAL_MMC_GetCardState().
01053   * @note   You could also check the DMA transfer process through the MMC Rx 
01054   *         interrupt event.
01055   * @param  hmmc Pointer MMC handle                 
01056   * @param  pData Pointer to the buffer that will contain the received data
01057   * @param  BlockAdd Block Address from where data is to be read  
01058   * @param  NumberOfBlocks Number of blocks to read.
01059   * @retval HAL status
01060   */
01061 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
01062 {
01063   SDIO_DataInitTypeDef config;
01064   uint32_t errorstate = HAL_MMC_ERROR_NONE;
01065   
01066   if(NULL == pData)
01067   {
01068     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01069     return HAL_ERROR;
01070   }
01071   
01072   if(hmmc->State == HAL_MMC_STATE_READY)
01073   {
01074     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
01075     
01076     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
01077     {
01078       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01079       return HAL_ERROR;
01080     }
01081     
01082     hmmc->State = HAL_MMC_STATE_BUSY;
01083     
01084     /* Initialize data control register */
01085     hmmc->Instance->DCTRL = 0U;
01086     
01087 #ifdef SDIO_STA_STBITER
01088     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR));
01089 #else /* SDIO_STA_STBITERR not defined */
01090     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
01091 #endif /* SDIO_STA_STBITERR */
01092     
01093     /* Set the DMA transfer complete callback */
01094     hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt;
01095     
01096     /* Set the DMA error callback */
01097     hmmc->hdmarx->XferErrorCallback = MMC_DMAError;
01098     
01099     /* Set the DMA Abort callback */
01100     hmmc->hdmarx->XferAbortCallback = NULL;
01101     
01102     /* Enable the DMA Channel */
01103     HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4);
01104     
01105     /* Enable MMC DMA transfer */
01106     __HAL_MMC_DMA_ENABLE(hmmc);
01107     
01108     /* Check the Card capacity in term of Logical number of blocks */
01109     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
01110     {
01111       BlockAdd *= 512U;
01112     }
01113     
01114     /* Configure the MMC DPSM (Data Path State Machine) */ 
01115     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01116     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
01117     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
01118     config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
01119     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
01120     config.DPSM          = SDIO_DPSM_ENABLE;
01121     SDIO_ConfigData(hmmc->Instance, &config);
01122 
01123     /* Set Block Size for Card */ 
01124     errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
01125     if(errorstate != HAL_MMC_ERROR_NONE)
01126     {
01127       /* Clear all the static flags */
01128       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
01129       hmmc->ErrorCode |= errorstate;
01130       hmmc->State = HAL_MMC_STATE_READY;
01131       return HAL_ERROR;
01132     }
01133         
01134     /* Read Blocks in DMA mode */
01135     if(NumberOfBlocks > 1U)
01136     {
01137       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
01138       
01139       /* Read Multi Block command */ 
01140       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, BlockAdd);
01141     }
01142     else
01143     {
01144       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
01145       
01146       /* Read Single Block command */ 
01147       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, BlockAdd);
01148     }
01149     if(errorstate != HAL_MMC_ERROR_NONE)
01150     {
01151       /* Clear all the static flags */
01152       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
01153       hmmc->ErrorCode |= errorstate;
01154       hmmc->State = HAL_MMC_STATE_READY;
01155       return HAL_ERROR;
01156     }
01157 
01158     return HAL_OK;
01159   }
01160   else
01161   {
01162     return HAL_BUSY;
01163   }
01164 }
01165 
01166 /**
01167   * @brief  Writes block(s) to a specified address in a card. The Data transfer 
01168   *         is managed by DMA mode. 
01169   * @note   This API should be followed by a check on the card state through
01170   *         HAL_MMC_GetCardState().
01171   * @note   You could also check the DMA transfer process through the MMC Tx 
01172   *         interrupt event.
01173   * @param  hmmc Pointer to MMC handle
01174   * @param  pData Pointer to the buffer that will contain the data to transmit
01175   * @param  BlockAdd Block Address where data will be written  
01176   * @param  NumberOfBlocks Number of blocks to write
01177   * @retval HAL status
01178   */
01179 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
01180 {
01181   SDIO_DataInitTypeDef config;
01182   uint32_t errorstate = HAL_MMC_ERROR_NONE;
01183   
01184   if(NULL == pData)
01185   {
01186     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01187     return HAL_ERROR;
01188   }
01189   
01190   if(hmmc->State == HAL_MMC_STATE_READY)
01191   {
01192     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
01193     
01194     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
01195     {
01196       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01197       return HAL_ERROR;
01198     }
01199     
01200     hmmc->State = HAL_MMC_STATE_BUSY;
01201     
01202     /* Initialize data control register */
01203     hmmc->Instance->DCTRL = 0U;
01204     
01205     /* Enable MMC Error interrupts */
01206 #ifdef SDIO_STA_STBITER
01207     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR));    
01208 #else /* SDIO_STA_STBITERR not defined */
01209     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));    
01210 #endif /* SDIO_STA_STBITERR */
01211     
01212     /* Set the DMA transfer complete callback */
01213     hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt;
01214     
01215     /* Set the DMA error callback */
01216     hmmc->hdmatx->XferErrorCallback = MMC_DMAError;
01217     
01218     /* Set the DMA Abort callback */
01219     hmmc->hdmatx->XferAbortCallback = NULL;
01220     
01221     /* Check the Card capacity in term of Logical number of blocks */
01222     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
01223     {
01224       BlockAdd *= 512U;
01225     }
01226     
01227     /* Set Block Size for Card */ 
01228     errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
01229     if(errorstate != HAL_MMC_ERROR_NONE)
01230     {
01231       /* Clear all the static flags */
01232       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
01233       hmmc->ErrorCode |= errorstate;
01234       hmmc->State = HAL_MMC_STATE_READY;
01235       return HAL_ERROR;
01236     }
01237     
01238     /* Write Blocks in Polling mode */
01239     if(NumberOfBlocks > 1U)
01240     {
01241       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
01242       
01243       /* Write Multi Block command */ 
01244       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, BlockAdd);
01245     }
01246     else
01247     {
01248       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
01249       
01250       /* Write Single Block command */
01251       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, BlockAdd);
01252     }
01253     if(errorstate != HAL_MMC_ERROR_NONE)
01254     {
01255       /* Clear all the static flags */
01256       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS); 
01257       hmmc->ErrorCode |= errorstate;
01258       hmmc->State = HAL_MMC_STATE_READY;
01259       return HAL_ERROR;
01260     }
01261     
01262     /* Enable SDIO DMA transfer */
01263     __HAL_MMC_DMA_ENABLE(hmmc);
01264     
01265     /* Enable the DMA Channel */
01266     HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4);
01267     
01268     /* Configure the MMC DPSM (Data Path State Machine) */ 
01269     config.DataTimeOut   = SDMMC_DATATIMEOUT;
01270     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
01271     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
01272     config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
01273     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
01274     config.DPSM          = SDIO_DPSM_ENABLE;
01275     SDIO_ConfigData(hmmc->Instance, &config);
01276     
01277     return HAL_OK;
01278   }
01279   else
01280   {
01281     return HAL_BUSY;
01282   }
01283 }
01284 
01285 /**
01286   * @brief  Erases the specified memory area of the given MMC card.
01287   * @note   This API should be followed by a check on the card state through
01288   *         HAL_MMC_GetCardState().
01289   * @param  hmmc Pointer to MMC handle 
01290   * @param  BlockStartAdd Start Block address
01291   * @param  BlockEndAdd End Block address
01292   * @retval HAL status
01293   */
01294 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
01295 {
01296   uint32_t errorstate = HAL_MMC_ERROR_NONE;
01297   
01298   if(hmmc->State == HAL_MMC_STATE_READY)
01299   {
01300     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
01301     
01302     if(BlockEndAdd < BlockStartAdd)
01303     {
01304       hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01305       return HAL_ERROR;
01306     }
01307     
01308     if(BlockEndAdd > (hmmc->MmcCard.LogBlockNbr))
01309     {
01310       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
01311       return HAL_ERROR;
01312     }
01313     
01314     hmmc->State = HAL_MMC_STATE_BUSY;
01315     
01316     /* Check if the card command class supports erase command */
01317     if(((hmmc->MmcCard.Class) & SDIO_CCCC_ERASE) == 0U)
01318     {
01319       /* Clear all the static flags */
01320       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
01321       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
01322       hmmc->State = HAL_MMC_STATE_READY;
01323       return HAL_ERROR;
01324     }
01325     
01326     if((SDIO_GetResponse(hmmc->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
01327     {
01328       /* Clear all the static flags */
01329       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);  
01330       hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
01331       hmmc->State = HAL_MMC_STATE_READY;
01332       return HAL_ERROR;
01333     }
01334     
01335     /* Check the Card capacity in term of Logical number of blocks */
01336     if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
01337     {
01338       BlockStartAdd *= 512U;
01339       BlockEndAdd   *= 512U;
01340     }
01341 
01342     /* Send CMD35 MMC_ERASE_GRP_START with argument as addr  */
01343     errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, BlockStartAdd);
01344     if(errorstate != HAL_MMC_ERROR_NONE)
01345     {
01346       /* Clear all the static flags */
01347       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 
01348       hmmc->ErrorCode |= errorstate;
01349       hmmc->State = HAL_MMC_STATE_READY;
01350       return HAL_ERROR;
01351     }
01352     
01353     /* Send CMD36 MMC_ERASE_GRP_END with argument as addr  */
01354     errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, BlockEndAdd);
01355     if(errorstate != HAL_MMC_ERROR_NONE)
01356     {
01357       /* Clear all the static flags */
01358       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 
01359       hmmc->ErrorCode |= errorstate;
01360       hmmc->State = HAL_MMC_STATE_READY;
01361       return HAL_ERROR;
01362     }
01363     
01364     /* Send CMD38 ERASE */
01365     errorstate = SDMMC_CmdErase(hmmc->Instance);
01366     if(errorstate != HAL_MMC_ERROR_NONE)
01367     {
01368       /* Clear all the static flags */
01369       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 
01370       hmmc->ErrorCode |= errorstate;
01371       hmmc->State = HAL_MMC_STATE_READY;
01372       return HAL_ERROR;
01373     }
01374     
01375     hmmc->State = HAL_MMC_STATE_READY;
01376     
01377     return HAL_OK;
01378   }
01379   else
01380   {
01381     return HAL_BUSY;
01382   }
01383 }
01384 
01385 /**
01386   * @brief  This function handles MMC card interrupt request.
01387   * @param  hmmc Pointer to MMC handle
01388   * @retval None
01389   */
01390 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
01391 {
01392   uint32_t errorstate = HAL_MMC_ERROR_NONE;
01393   
01394   /* Check for SDIO interrupt flags */
01395   if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DATAEND) != RESET)
01396   {
01397     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_DATAEND); 
01398     
01399 #ifdef SDIO_STA_STBITERR
01400     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
01401                                SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
01402 #else /* SDIO_STA_STBITERR not defined */
01403     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
01404                                SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR);
01405 #endif
01406     
01407     if((hmmc->Context & MMC_CONTEXT_IT) != RESET)
01408     {
01409       if(((hmmc->Context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != RESET) || ((hmmc->Context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != RESET))
01410       {
01411         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
01412         if(errorstate != HAL_MMC_ERROR_NONE)
01413         {
01414           hmmc->ErrorCode |= errorstate;
01415           HAL_MMC_ErrorCallback(hmmc);
01416         }
01417       }
01418       
01419       /* Clear all the static flags */
01420       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
01421       
01422       hmmc->State = HAL_MMC_STATE_READY;
01423       if(((hmmc->Context & MMC_CONTEXT_READ_SINGLE_BLOCK) != RESET) || ((hmmc->Context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != RESET))
01424       {
01425         HAL_MMC_RxCpltCallback(hmmc);
01426       }
01427       else
01428       {
01429         HAL_MMC_TxCpltCallback(hmmc);
01430       }
01431     }
01432     else if((hmmc->Context & MMC_CONTEXT_DMA) != RESET)
01433     {
01434       if((hmmc->Context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != RESET)
01435       {
01436         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
01437         if(errorstate != HAL_MMC_ERROR_NONE)
01438         {
01439           hmmc->ErrorCode |= errorstate;
01440           HAL_MMC_ErrorCallback(hmmc);
01441         }
01442       }
01443       if(((hmmc->Context & MMC_CONTEXT_READ_SINGLE_BLOCK) == RESET) && ((hmmc->Context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == RESET))
01444       {
01445         /* Disable the DMA transfer for transmit request by setting the DMAEN bit
01446         in the MMC DCTRL register */
01447         hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
01448         
01449         hmmc->State = HAL_MMC_STATE_READY;
01450         
01451         HAL_MMC_TxCpltCallback(hmmc);
01452       }
01453     }
01454   }
01455   
01456   else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_TXFIFOHE) != RESET)
01457   {
01458     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_TXFIFOHE);
01459     
01460     MMC_Write_IT(hmmc);
01461   }
01462   
01463   else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_RXFIFOHF) != RESET)
01464   {
01465     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_RXFIFOHF);
01466     
01467     MMC_Read_IT(hmmc);
01468   }
01469   
01470 #ifdef SDIO_STA_STBITERR
01471   else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR) != RESET)
01472   {
01473     /* Set Error code */
01474     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DCRCFAIL) != RESET)
01475     {
01476       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 
01477     }
01478     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DTIMEOUT) != RESET)
01479     {
01480       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 
01481     }
01482     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_RXOVERR) != RESET)
01483     {
01484       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; 
01485     }
01486     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_TXUNDERR) != RESET)
01487     {
01488       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN; 
01489     }
01490     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_STBITERR) != RESET)
01491     {
01492       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
01493     }
01494 
01495     /* Clear All flags */
01496     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS | SDIO_FLAG_STBITERR);
01497     
01498     /* Disable all interrupts */
01499     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
01500                                SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR |SDIO_IT_STBITERR);
01501     
01502     if((hmmc->Context & MMC_CONTEXT_DMA) != RESET)
01503     {
01504       /* Abort the MMC DMA Streams */
01505       if(hmmc->hdmatx != NULL)
01506       {
01507         /* Set the DMA Tx abort callback */
01508         hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
01509         /* Abort DMA in IT mode */
01510         if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
01511         {
01512           MMC_DMATxAbort(hmmc->hdmatx);
01513         }
01514       }
01515       else if(hmmc->hdmarx != NULL)
01516       {
01517         /* Set the DMA Rx abort callback */
01518         hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
01519         /* Abort DMA in IT mode */
01520         if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
01521         {
01522           MMC_DMARxAbort(hmmc->hdmarx);
01523         }
01524       }
01525       else
01526       {
01527         hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
01528         hmmc->State = HAL_MMC_STATE_READY;
01529         HAL_MMC_AbortCallback(hmmc);
01530       }
01531     }
01532     else if((hmmc->Context & MMC_CONTEXT_IT) != RESET)
01533     {
01534       /* Set the MMC state to ready to be able to start again the process */
01535       hmmc->State = HAL_MMC_STATE_READY;
01536       HAL_MMC_ErrorCallback(hmmc);
01537     }
01538   }
01539 #else /* SDIO_STA_STBITERR not defined */
01540   else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_TXUNDERR) != RESET)
01541   {
01542     /* Set Error code */
01543     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DCRCFAIL) != RESET)
01544     {
01545       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 
01546     }
01547     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_DTIMEOUT) != RESET)
01548     {
01549       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 
01550     }
01551     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_RXOVERR) != RESET)
01552     {
01553       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; 
01554     }
01555     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_IT_TXUNDERR) != RESET)
01556     {
01557       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN; 
01558     }
01559 
01560     /* Clear All flags */
01561     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
01562     
01563     /* Disable all interrupts */
01564     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
01565                                SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
01566     
01567     if((hmmc->Context & MMC_CONTEXT_DMA) != RESET)
01568     {
01569       /* Abort the MMC DMA Streams */
01570       if(hmmc->hdmatx != NULL)
01571       {
01572         /* Set the DMA Tx abort callback */
01573         hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
01574         /* Abort DMA in IT mode */
01575         if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
01576         {
01577           MMC_DMATxAbort(hmmc->hdmatx);
01578         }
01579       }
01580       else if(hmmc->hdmarx != NULL)
01581       {
01582         /* Set the DMA Rx abort callback */
01583         hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
01584         /* Abort DMA in IT mode */
01585         if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
01586         {
01587           MMC_DMARxAbort(hmmc->hdmarx);
01588         }
01589       }
01590       else
01591       {
01592         hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
01593         hmmc->State = HAL_MMC_STATE_READY;
01594         HAL_MMC_AbortCallback(hmmc);
01595       }
01596     }
01597     else if((hmmc->Context & MMC_CONTEXT_IT) != RESET)
01598     {
01599       /* Set the MMC state to ready to be able to start again the process */
01600       hmmc->State = HAL_MMC_STATE_READY;
01601       HAL_MMC_ErrorCallback(hmmc);
01602     }
01603   }
01604 #endif /* SDIO_STA_STBITERR */
01605 }
01606 
01607 /**
01608   * @brief return the MMC state
01609   * @param hmmc Pointer to mmc handle
01610   * @retval HAL state
01611   */
01612 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
01613 {
01614   return hmmc->State;
01615 }
01616 
01617 /**
01618 * @brief  Return the MMC error code
01619 * @param  hmmc  Pointer to a MMC_HandleTypeDef structure that contains
01620   *              the configuration information.
01621 * @retval MMC Error Code
01622 */
01623 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
01624 {
01625   return hmmc->ErrorCode;
01626 }
01627 
01628 /**
01629   * @brief Tx Transfer completed callbacks
01630   * @param hmmc Pointer to MMC handle
01631   * @retval None
01632   */
01633  __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
01634 {
01635   /* Prevent unused argument(s) compilation warning */
01636   UNUSED(hmmc);
01637 
01638   /* NOTE : This function should not be modified, when the callback is needed,
01639             the HAL_MMC_TxCpltCallback can be implemented in the user file
01640    */
01641 }
01642 
01643 /**
01644   * @brief Rx Transfer completed callbacks
01645   * @param hmmc Pointer MMC handle
01646   * @retval None
01647   */
01648 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
01649 {
01650   /* Prevent unused argument(s) compilation warning */
01651   UNUSED(hmmc);
01652  
01653   /* NOTE : This function should not be modified, when the callback is needed,
01654             the HAL_MMC_RxCpltCallback can be implemented in the user file
01655    */
01656 }
01657 
01658 /**
01659   * @brief MMC error callbacks
01660   * @param hmmc Pointer MMC handle
01661   * @retval None
01662   */
01663 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
01664 {
01665   /* Prevent unused argument(s) compilation warning */
01666   UNUSED(hmmc);
01667  
01668   /* NOTE : This function should not be modified, when the callback is needed,
01669             the HAL_MMC_ErrorCallback can be implemented in the user file
01670    */ 
01671 }
01672 
01673 /**
01674   * @brief MMC Abort callbacks
01675   * @param hmmc Pointer MMC handle
01676   * @retval None
01677   */
01678 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
01679 {
01680   /* Prevent unused argument(s) compilation warning */
01681   UNUSED(hmmc);
01682  
01683   /* NOTE : This function should not be modified, when the callback is needed,
01684             the HAL_MMC_ErrorCallback can be implemented in the user file
01685    */ 
01686 }
01687 
01688 
01689 /**
01690   * @}
01691   */
01692 
01693 /** @addtogroup MMC_Exported_Functions_Group3
01694  *  @brief   management functions 
01695  *
01696 @verbatim   
01697   ==============================================================================
01698                       ##### Peripheral Control functions #####
01699   ==============================================================================  
01700   [..]
01701     This subsection provides a set of functions allowing to control the MMC card 
01702     operations and get the related information
01703 
01704 @endverbatim
01705   * @{
01706   */
01707 
01708 /**
01709   * @brief  Returns information the information of the card which are stored on
01710   *         the CID register.
01711   * @param  hmmc Pointer to MMC handle
01712   * @param  pCID Pointer to a HAL_MMC_CIDTypedef structure that  
01713   *         contains all CID register parameters 
01714   * @retval HAL status
01715   */
01716 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
01717 {
01718   uint32_t tmp = 0U;
01719   
01720   /* Byte 0 */
01721   tmp = (uint8_t)((hmmc->CID[0U] & 0xFF000000U) >> 24U);
01722   pCID->ManufacturerID = tmp;
01723   
01724   /* Byte 1 */
01725   tmp = (uint8_t)((hmmc->CID[0U] & 0x00FF0000U) >> 16U);
01726   pCID->OEM_AppliID = tmp << 8U;
01727   
01728   /* Byte 2 */
01729   tmp = (uint8_t)((hmmc->CID[0U] & 0x000000FF00U) >> 8U);
01730   pCID->OEM_AppliID |= tmp;
01731   
01732   /* Byte 3 */
01733   tmp = (uint8_t)(hmmc->CID[0U] & 0x000000FFU);
01734   pCID->ProdName1 = tmp << 24U;
01735   
01736   /* Byte 4 */
01737   tmp = (uint8_t)((hmmc->CID[1U] & 0xFF000000U) >> 24U);
01738   pCID->ProdName1 |= tmp << 16U;
01739   
01740   /* Byte 5 */
01741   tmp = (uint8_t)((hmmc->CID[1U] & 0x00FF0000U) >> 16U);
01742   pCID->ProdName1 |= tmp << 8U;
01743   
01744   /* Byte 6 */
01745   tmp = (uint8_t)((hmmc->CID[1U] & 0x0000FF00U) >> 8U);
01746   pCID->ProdName1 |= tmp;
01747   
01748   /* Byte 7 */
01749   tmp = (uint8_t)(hmmc->CID[1U] & 0x000000FFU);
01750   pCID->ProdName2 = tmp;
01751   
01752   /* Byte 8 */
01753   tmp = (uint8_t)((hmmc->CID[2U] & 0xFF000000U) >> 24U);
01754   pCID->ProdRev = tmp;
01755   
01756   /* Byte 9 */
01757   tmp = (uint8_t)((hmmc->CID[2U] & 0x00FF0000U) >> 16U);
01758   pCID->ProdSN = tmp << 24U;
01759   
01760   /* Byte 10 */
01761   tmp = (uint8_t)((hmmc->CID[2U] & 0x0000FF00U) >> 8U);
01762   pCID->ProdSN |= tmp << 16U;
01763   
01764   /* Byte 11 */
01765   tmp = (uint8_t)(hmmc->CID[2U] & 0x000000FFU);
01766   pCID->ProdSN |= tmp << 8U;
01767   
01768   /* Byte 12 */
01769   tmp = (uint8_t)((hmmc->CID[3U] & 0xFF000000U) >> 24U);
01770   pCID->ProdSN |= tmp;
01771   
01772   /* Byte 13 */
01773   tmp = (uint8_t)((hmmc->CID[3U] & 0x00FF0000U) >> 16U);
01774   pCID->Reserved1   |= (tmp & 0xF0U) >> 4U;
01775   pCID->ManufactDate = (tmp & 0x0FU) << 8U;
01776   
01777   /* Byte 14 */
01778   tmp = (uint8_t)((hmmc->CID[3U] & 0x0000FF00U) >> 8U);
01779   pCID->ManufactDate |= tmp;
01780   
01781   /* Byte 15 */
01782   tmp = (uint8_t)(hmmc->CID[3U] & 0x000000FFU);
01783   pCID->CID_CRC   = (tmp & 0xFEU) >> 1U;
01784   pCID->Reserved2 = 1U;
01785 
01786   return HAL_OK;
01787 }
01788 
01789 /**
01790   * @brief  Returns information the information of the card which are stored on
01791   *         the CSD register.
01792   * @param  hmmc Pointer to MMC handle
01793   * @param  pCSD Pointer to a HAL_MMC_CardInfoTypeDef structure that  
01794   *         contains all CSD register parameters  
01795   * @retval HAL status
01796   */
01797 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
01798 {
01799   uint32_t tmp = 0U;
01800   
01801   /* Byte 0 */
01802   tmp = (hmmc->CSD[0U] & 0xFF000000U) >> 24U;
01803   pCSD->CSDStruct      = (uint8_t)((tmp & 0xC0U) >> 6U);
01804   pCSD->SysSpecVersion = (uint8_t)((tmp & 0x3CU) >> 2U);
01805   pCSD->Reserved1      = tmp & 0x03U;
01806   
01807   /* Byte 1 */
01808   tmp = (hmmc->CSD[0U] & 0x00FF0000U) >> 16U;
01809   pCSD->TAAC = (uint8_t)tmp;
01810   
01811   /* Byte 2 */
01812   tmp = (hmmc->CSD[0U] & 0x0000FF00U) >> 8U;
01813   pCSD->NSAC = (uint8_t)tmp;
01814   
01815   /* Byte 3 */
01816   tmp = hmmc->CSD[0U] & 0x000000FFU;
01817   pCSD->MaxBusClkFrec = (uint8_t)tmp;
01818   
01819   /* Byte 4 */
01820   tmp = (hmmc->CSD[1U] & 0xFF000000U) >> 24U;
01821   pCSD->CardComdClasses = (uint16_t)(tmp << 4U);
01822   
01823   /* Byte 5 */
01824   tmp = (hmmc->CSD[1U] & 0x00FF0000U) >> 16U;
01825   pCSD->CardComdClasses |= (uint16_t)((tmp & 0xF0U) >> 4U);
01826   pCSD->RdBlockLen       = (uint8_t)(tmp & 0x0FU);
01827   
01828   /* Byte 6 */
01829   tmp = (hmmc->CSD[1U] & 0x0000FF00U) >> 8U;
01830   pCSD->PartBlockRead   = (uint8_t)((tmp & 0x80U) >> 7U);
01831   pCSD->WrBlockMisalign = (uint8_t)((tmp & 0x40U) >> 6U);
01832   pCSD->RdBlockMisalign = (uint8_t)((tmp & 0x20U) >> 5U);
01833   pCSD->DSRImpl         = (uint8_t)((tmp & 0x10U) >> 4U);
01834   pCSD->Reserved2       = 0; /*!< Reserved */
01835        
01836   pCSD->DeviceSize = (tmp & 0x03U) << 10U;
01837   
01838   /* Byte 7 */
01839   tmp = (uint8_t)(hmmc->CSD[1U] & 0x000000FFU);
01840   pCSD->DeviceSize |= (tmp) << 2U;
01841   
01842   /* Byte 8 */
01843   tmp = (uint8_t)((hmmc->CSD[2U] & 0xFF000000U) >> 24U);
01844   pCSD->DeviceSize |= (tmp & 0xC0U) >> 6U;
01845   
01846   pCSD->MaxRdCurrentVDDMin = (tmp & 0x38U) >> 3U;
01847   pCSD->MaxRdCurrentVDDMax = (tmp & 0x07U);
01848   
01849   /* Byte 9 */
01850   tmp = (uint8_t)((hmmc->CSD[2U] & 0x00FF0000U) >> 16U);
01851   pCSD->MaxWrCurrentVDDMin = (tmp & 0xE0U) >> 5U;
01852   pCSD->MaxWrCurrentVDDMax = (tmp & 0x1CU) >> 2U;
01853   pCSD->DeviceSizeMul      = (tmp & 0x03U) << 1U;
01854   /* Byte 10 */
01855   tmp = (uint8_t)((hmmc->CSD[2] & 0x0000FF00U) >> 8U);
01856   pCSD->DeviceSizeMul |= (tmp & 0x80U) >> 7U;
01857   
01858   hmmc->MmcCard.BlockNbr  = (pCSD->DeviceSize + 1U) ;
01859   hmmc->MmcCard.BlockNbr *= (1U << (pCSD->DeviceSizeMul + 2U));
01860   hmmc->MmcCard.BlockSize = 1U << (pCSD->RdBlockLen);
01861   
01862   hmmc->MmcCard.LogBlockNbr =  (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U); 
01863   hmmc->MmcCard.LogBlockSize = 512U;
01864   
01865   pCSD->EraseGrSize = (tmp & 0x40U) >> 6U;
01866   pCSD->EraseGrMul  = (tmp & 0x3FU) << 1U;
01867   
01868   /* Byte 11 */
01869   tmp = (uint8_t)(hmmc->CSD[2U] & 0x000000FFU);
01870   pCSD->EraseGrMul     |= (tmp & 0x80U) >> 7U;
01871   pCSD->WrProtectGrSize = (tmp & 0x7FU);
01872   
01873   /* Byte 12 */
01874   tmp = (uint8_t)((hmmc->CSD[3U] & 0xFF000000U) >> 24U);
01875   pCSD->WrProtectGrEnable = (tmp & 0x80U) >> 7U;
01876   pCSD->ManDeflECC        = (tmp & 0x60U) >> 5U;
01877   pCSD->WrSpeedFact       = (tmp & 0x1CU) >> 2U;
01878   pCSD->MaxWrBlockLen     = (tmp & 0x03U) << 2U;
01879   
01880   /* Byte 13 */
01881   tmp = (uint8_t)((hmmc->CSD[3U] & 0x00FF0000U) >> 16U);
01882   pCSD->MaxWrBlockLen      |= (tmp & 0xC0U) >> 6U;
01883   pCSD->WriteBlockPaPartial = (tmp & 0x20U) >> 5U;
01884   pCSD->Reserved3           = 0U;
01885   pCSD->ContentProtectAppli = (tmp & 0x01U);
01886   
01887   /* Byte 14 */
01888   tmp = (uint8_t)((hmmc->CSD[3U] & 0x0000FF00U) >> 8U);
01889   pCSD->FileFormatGrouop = (tmp & 0x80U) >> 7U;
01890   pCSD->CopyFlag         = (tmp & 0x40U) >> 6U;
01891   pCSD->PermWrProtect    = (tmp & 0x20U) >> 5U;
01892   pCSD->TempWrProtect    = (tmp & 0x10U) >> 4U;
01893   pCSD->FileFormat       = (tmp & 0x0CU) >> 2U;
01894   pCSD->ECC              = (tmp & 0x03U);
01895   
01896   /* Byte 15 */
01897   tmp = (uint8_t)(hmmc->CSD[3U] & 0x000000FFU);
01898   pCSD->CSD_CRC   = (tmp & 0xFEU) >> 1U;
01899   pCSD->Reserved4 = 1U;
01900   
01901   return HAL_OK;
01902 }
01903 
01904 /**
01905   * @brief  Gets the MMC card info.
01906   * @param  hmmc Pointer to MMC handle      
01907   * @param  pCardInfo Pointer to the HAL_MMC_CardInfoTypeDef structure that 
01908   *         will contain the MMC card status information 
01909   * @retval HAL status
01910   */
01911 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
01912 {
01913   pCardInfo->CardType     = (uint32_t)(hmmc->MmcCard.CardType);
01914   pCardInfo->Class        = (uint32_t)(hmmc->MmcCard.Class);
01915   pCardInfo->RelCardAdd   = (uint32_t)(hmmc->MmcCard.RelCardAdd);
01916   pCardInfo->BlockNbr     = (uint32_t)(hmmc->MmcCard.BlockNbr);
01917   pCardInfo->BlockSize    = (uint32_t)(hmmc->MmcCard.BlockSize);
01918   pCardInfo->LogBlockNbr  = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
01919   pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
01920   
01921   return HAL_OK;
01922 }
01923 
01924 /**
01925   * @brief  Enables wide bus operation for the requested card if supported by 
01926   *         card.
01927   * @param  hmmc Pointer to MMC handle       
01928   * @param  WideMode Specifies the MMC card wide bus mode 
01929   *          This parameter can be one of the following values:
01930   *            @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
01931   *            @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
01932   *            @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
01933   * @retval HAL status
01934   */
01935 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
01936 {
01937   __IO uint32_t count = 0U;
01938   SDIO_InitTypeDef Init;
01939   uint32_t errorstate = HAL_MMC_ERROR_NONE;
01940   uint32_t response = 0U, busy = 0U;
01941   
01942   /* Check the parameters */
01943   assert_param(IS_SDIO_BUS_WIDE(WideMode));
01944   
01945   /* Chnage Satte */
01946   hmmc->State = HAL_MMC_STATE_BUSY;
01947   
01948   /* Update Clock for Bus mode update */
01949   Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
01950   Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
01951   Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
01952   Init.BusWide             = WideMode;
01953   Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
01954   Init.ClockDiv            = SDIO_INIT_CLK_DIV;
01955   /* Initialize SDIO*/
01956   SDIO_Init(hmmc->Instance, Init); 
01957     
01958   if(WideMode == SDIO_BUS_WIDE_8B)
01959   {
01960     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
01961     if(errorstate != HAL_MMC_ERROR_NONE)
01962     {
01963       hmmc->ErrorCode |= errorstate;
01964     }
01965   }
01966   else if(WideMode == SDIO_BUS_WIDE_4B)
01967   {
01968     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
01969     if(errorstate != HAL_MMC_ERROR_NONE)
01970     {
01971       hmmc->ErrorCode |= errorstate;
01972     }
01973   }
01974   else if(WideMode == SDIO_BUS_WIDE_1B)
01975   {
01976     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
01977     if(errorstate != HAL_MMC_ERROR_NONE)
01978     {
01979       hmmc->ErrorCode |= errorstate;
01980     }
01981   }
01982   else
01983   {
01984     /* WideMode is not a valid argument*/
01985     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
01986   }
01987   
01988   /* Check for switch error and violation of the trial number of sending CMD 13 */
01989   while(busy == 0U)
01990   {
01991     if(count++ == SDMMC_MAX_TRIAL)
01992     {
01993       hmmc->State = HAL_MMC_STATE_READY;
01994       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
01995       return HAL_ERROR;
01996     }
01997     
01998     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
01999     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
02000     if(errorstate != HAL_MMC_ERROR_NONE)
02001     {
02002       hmmc->ErrorCode |= errorstate;
02003     }
02004     
02005     /* Get command response */
02006     response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
02007     
02008     /* Get operating voltage*/
02009     busy = (((response >> 7U) == 1U) ? 0U : 1U);
02010   }
02011       
02012   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
02013   count = SDMMC_DATATIMEOUT;
02014   while((response & 0x00000100U) == 0U)
02015   {
02016     if(count-- == 0U)
02017     {
02018       hmmc->State = HAL_MMC_STATE_READY;
02019       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
02020       return HAL_ERROR;
02021     }
02022     
02023     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
02024     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
02025     if(errorstate != HAL_MMC_ERROR_NONE)
02026     {
02027       hmmc->ErrorCode |= errorstate;
02028     }
02029     
02030     /* Get command response */
02031     response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
02032   }
02033   
02034   if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02035   {
02036     /* Clear all the static flags */
02037     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
02038     hmmc->State = HAL_MMC_STATE_READY;
02039     return HAL_ERROR;
02040   }
02041   else
02042   {
02043     /* Configure the SDIO peripheral */
02044     Init.ClockEdge           = hmmc->Init.ClockEdge;
02045     Init.ClockBypass         = hmmc->Init.ClockBypass;
02046     Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
02047     Init.BusWide             = WideMode;
02048     Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
02049     Init.ClockDiv            = hmmc->Init.ClockDiv;
02050     SDIO_Init(hmmc->Instance, Init);
02051   }
02052 
02053   /* Change State */
02054   hmmc->State = HAL_MMC_STATE_READY;
02055   
02056   return HAL_OK;
02057 }
02058 
02059 
02060 /**
02061   * @brief  Gets the current mmc card data state.
02062   * @param  hmmc pointer to MMC handle
02063   * @retval Card state
02064   */
02065 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
02066 {
02067   HAL_MMC_CardStateTypeDef cardstate =  HAL_MMC_CARD_TRANSFER;
02068   uint32_t errorstate = HAL_MMC_ERROR_NONE;
02069   uint32_t resp1 = 0U;
02070   
02071   errorstate = MMC_SendStatus(hmmc, &resp1);
02072   if(errorstate != HAL_OK)
02073   {
02074     hmmc->ErrorCode |= errorstate;
02075   }
02076 
02077   cardstate = (HAL_MMC_CardStateTypeDef)((resp1 >> 9U) & 0x0FU);
02078   
02079   return cardstate;
02080 }
02081 
02082 /**
02083   * @brief  Abort the current transfer and disable the MMC.
02084   * @param  hmmc pointer to a MMC_HandleTypeDef structure that contains
02085   *                the configuration information for MMC module.
02086   * @retval HAL status
02087   */
02088 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
02089 {
02090   HAL_MMC_CardStateTypeDef CardState;
02091   
02092   /* DIsable All interrupts */
02093   __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
02094                            SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
02095   
02096   /* Clear All flags */
02097   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
02098   
02099   if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
02100   {
02101     /* Disable the MMC DMA request */
02102     hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
02103     
02104     /* Abort the MMC DMA Tx Stream */
02105     if(hmmc->hdmatx != NULL)
02106     {
02107       HAL_DMA_Abort(hmmc->hdmatx);
02108     }
02109     /* Abort the MMC DMA Rx Stream */
02110     if(hmmc->hdmarx != NULL)
02111     {
02112       HAL_DMA_Abort(hmmc->hdmarx);
02113     }
02114   }
02115   
02116   hmmc->State = HAL_MMC_STATE_READY;
02117   CardState = HAL_MMC_GetCardState(hmmc);
02118   if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02119   {
02120     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
02121   }
02122   if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02123   {
02124     return HAL_ERROR;
02125   }
02126   return HAL_OK;
02127 }
02128 
02129 /**
02130   * @brief  Abort the current transfer and disable the MMC (IT mode).
02131   * @param  hmmc pointer to a MMC_HandleTypeDef structure that contains
02132   *                the configuration information for MMC module.
02133   * @retval HAL status
02134   */
02135 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
02136 {
02137   HAL_MMC_CardStateTypeDef CardState;
02138     
02139   /* DIsable All interrupts */
02140   __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
02141                            SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
02142   
02143   /* Clear All flags */
02144   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
02145   
02146   if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
02147   {
02148     /* Disable the MMC DMA request */
02149     hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
02150     
02151     /* Abort the MMC DMA Tx Stream */
02152     if(hmmc->hdmatx != NULL)
02153     {
02154       hmmc->hdmatx->XferAbortCallback =  MMC_DMATxAbort;
02155       if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
02156       {
02157         hmmc->hdmatx = NULL;
02158       }
02159     }
02160     /* Abort the MMC DMA Rx Stream */
02161     if(hmmc->hdmarx != NULL)
02162     {
02163       hmmc->hdmarx->XferAbortCallback =  MMC_DMARxAbort;
02164       if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
02165       {
02166         hmmc->hdmarx = NULL;
02167       }
02168     }
02169   }
02170   
02171   /* No transfer ongoing on both DMA channels*/
02172   if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
02173   {
02174     CardState = HAL_MMC_GetCardState(hmmc);
02175     hmmc->State = HAL_MMC_STATE_READY;
02176     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02177     {
02178       hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
02179     }
02180     if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02181     {
02182       return HAL_ERROR;
02183     }
02184     else
02185     {
02186       HAL_MMC_AbortCallback(hmmc);
02187     }
02188   }
02189   
02190   return HAL_OK;
02191 }
02192 
02193 /**
02194   * @}
02195   */
02196   
02197 /**
02198   * @}
02199   */
02200   
02201 /* Private function ----------------------------------------------------------*/  
02202 /** @addtogroup MMC_Private_Functions
02203   * @{
02204   */
02205 
02206 /**
02207   * @brief  DMA MMC transmit process complete callback 
02208   * @param  hdma DMA handle
02209   * @retval None
02210   */
02211 static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)     
02212 {
02213   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
02214   
02215   /* Enable DATAEND Interrupt */
02216   __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DATAEND));
02217 }
02218 
02219 /**
02220   * @brief  DMA MMC receive process complete callback 
02221   * @param  hdma DMA handle
02222   * @retval None
02223   */
02224 static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)  
02225 {
02226   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
02227   uint32_t errorstate = HAL_MMC_ERROR_NONE;
02228   
02229   /* Send stop command in multiblock write */
02230   if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
02231   {
02232     errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
02233     if(errorstate != HAL_MMC_ERROR_NONE)
02234     {
02235       hmmc->ErrorCode |= errorstate;
02236       HAL_MMC_ErrorCallback(hmmc);
02237     }
02238   }
02239   
02240   /* Disable the DMA transfer for transmit request by setting the DMAEN bit
02241   in the MMC DCTRL register */
02242   hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
02243   
02244   /* Clear all the static flags */
02245   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
02246   
02247   hmmc->State = HAL_MMC_STATE_READY;
02248 
02249   HAL_MMC_RxCpltCallback(hmmc);
02250 }
02251 
02252 /**
02253   * @brief  DMA MMC communication error callback 
02254   * @param  hdma DMA handle
02255   * @retval None
02256   */
02257 static void MMC_DMAError(DMA_HandleTypeDef *hdma)   
02258 {
02259   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
02260   HAL_MMC_CardStateTypeDef CardState;
02261   
02262   if((hmmc->hdmarx->ErrorCode == HAL_DMA_ERROR_TE) || (hmmc->hdmatx->ErrorCode == HAL_DMA_ERROR_TE))
02263   {
02264     /* Clear All flags */
02265     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
02266     
02267     /* Disable All interrupts */
02268     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
02269       SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
02270     
02271     hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
02272     CardState = HAL_MMC_GetCardState(hmmc);
02273     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02274     {
02275       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
02276     }
02277     
02278     hmmc->State= HAL_MMC_STATE_READY;
02279   }
02280 
02281   HAL_MMC_ErrorCallback(hmmc);
02282 }
02283 
02284 /**
02285   * @brief  DMA MMC Tx Abort callback 
02286   * @param  hdma DMA handle
02287   * @retval None
02288   */
02289 static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)   
02290 {
02291   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
02292   HAL_MMC_CardStateTypeDef CardState;
02293   
02294   if(hmmc->hdmatx != NULL)
02295   {
02296     hmmc->hdmatx = NULL;
02297   }
02298   
02299   /* All DMA channels are aborted */
02300   if(hmmc->hdmarx == NULL)
02301   {
02302     CardState = HAL_MMC_GetCardState(hmmc);
02303     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
02304     hmmc->State = HAL_MMC_STATE_READY;
02305     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02306     {
02307       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
02308       
02309       if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02310       {
02311         HAL_MMC_AbortCallback(hmmc);
02312       }
02313       else
02314       {
02315         HAL_MMC_ErrorCallback(hmmc);
02316       }
02317     }
02318   }
02319 }
02320 
02321 /**
02322   * @brief  DMA MMC Rx Abort callback 
02323   * @param  hdma DMA handle
02324   * @retval None
02325   */
02326 static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)   
02327 {
02328   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
02329   HAL_MMC_CardStateTypeDef CardState;
02330   
02331   if(hmmc->hdmarx != NULL)
02332   {
02333     hmmc->hdmarx = NULL;
02334   }
02335   
02336   /* All DMA channels are aborted */
02337   if(hmmc->hdmatx == NULL)
02338   {
02339     CardState = HAL_MMC_GetCardState(hmmc);
02340     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
02341     hmmc->State = HAL_MMC_STATE_READY;
02342     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
02343     {
02344       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
02345       
02346       if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
02347       {
02348         HAL_MMC_AbortCallback(hmmc);
02349       }
02350       else
02351       {
02352         HAL_MMC_ErrorCallback(hmmc);
02353       }
02354     }
02355   }
02356 }
02357 
02358 
02359 /**
02360   * @brief  Initializes the mmc card.
02361   * @param  hmmc Pointer to MMC handle
02362   * @retval MMC Card error state
02363   */
02364 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
02365 {
02366   HAL_MMC_CardCSDTypeDef CSD;
02367   uint32_t errorstate = HAL_MMC_ERROR_NONE;
02368   uint16_t mmc_rca = 1;
02369   
02370   /* Check the power State */
02371   if(SDIO_GetPowerState(hmmc->Instance) == 0U) 
02372   {
02373     /* Power off */
02374     return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
02375   }
02376   
02377   /* Send CMD2 ALL_SEND_CID */
02378   errorstate = SDMMC_CmdSendCID(hmmc->Instance);
02379   if(errorstate != HAL_MMC_ERROR_NONE)
02380   {
02381     return errorstate;
02382   }
02383   else
02384   {
02385     /* Get Card identification number data */
02386     hmmc->CID[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
02387     hmmc->CID[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
02388     hmmc->CID[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
02389     hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
02390   }
02391   
02392   /* Send CMD3 SET_REL_ADDR with argument 0 */
02393   /* MMC Card publishes its RCA. */
02394   errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
02395   if(errorstate != HAL_MMC_ERROR_NONE)
02396   {
02397     return errorstate;
02398   }
02399   
02400   /* Get the MMC card RCA */
02401   hmmc->MmcCard.RelCardAdd = mmc_rca;
02402   
02403   /* Send CMD9 SEND_CSD with argument as card's RCA */
02404   errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
02405   if(errorstate != HAL_MMC_ERROR_NONE)
02406   {
02407     return errorstate;
02408   }
02409   else
02410   {
02411     /* Get Card Specific Data */
02412     hmmc->CSD[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
02413     hmmc->CSD[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
02414     hmmc->CSD[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
02415     hmmc->CSD[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
02416   }
02417   
02418   /* Get the Card Class */
02419   hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U);
02420   
02421   /* Get CSD parameters */
02422   HAL_MMC_GetCardCSD(hmmc, &CSD);
02423 
02424   /* Select the Card */
02425  errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
02426  if(errorstate != HAL_MMC_ERROR_NONE)
02427  {
02428    return errorstate;
02429  }
02430 
02431   /* Configure SDIO peripheral interface */
02432   SDIO_Init(hmmc->Instance, hmmc->Init);
02433 
02434   /* All cards are initialized */
02435   return HAL_MMC_ERROR_NONE;
02436 }
02437 
02438 /**
02439   * @brief  Enquires cards about their operating voltage and configures clock
02440   *         controls and stores MMC information that will be needed in future
02441   *         in the MMC handle.
02442   * @param  hmmc Pointer to MMC handle
02443   * @retval error state
02444   */
02445 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
02446 {
02447   __IO uint32_t count = 0U;
02448   uint32_t response = 0U, validvoltage = 0U;
02449   uint32_t errorstate = HAL_MMC_ERROR_NONE;
02450   
02451   /* CMD0: GO_IDLE_STATE */
02452   errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
02453   if(errorstate != HAL_MMC_ERROR_NONE)
02454   {
02455     return errorstate;
02456   }
02457 
02458   while(validvoltage == 0U)
02459   {
02460     if(count++ == SDMMC_MAX_VOLT_TRIAL)
02461     {
02462       return HAL_MMC_ERROR_INVALID_VOLTRANGE;
02463     }
02464     
02465     /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
02466     errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
02467     if(errorstate != HAL_MMC_ERROR_NONE)
02468     {
02469       return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
02470     }
02471     
02472     /* Get command response */
02473     response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
02474     
02475     /* Get operating voltage*/
02476     validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
02477   }
02478   
02479   /* When power routine is finished and command returns valid voltage */
02480   if ((response & eMMC_HIGH_VOLTAGE_RANGE) == MMC_HIGH_VOLTAGE_RANGE)
02481   {
02482     /* When voltage range of the card is within 2.7V and 3.6V */
02483     hmmc->MmcCard.CardType = MMC_HIGH_VOLTAGE_CARD;
02484   }
02485   else
02486   {
02487     /* When voltage range of the card is within 1.65V and 1.95V or 2.7V and 3.6V */
02488     hmmc->MmcCard.CardType = MMC_DUAL_VOLTAGE_CARD;
02489   }
02490   
02491   return HAL_MMC_ERROR_NONE;
02492 }
02493 
02494 /**
02495   * @brief  Turns the SDIO output signals off.
02496   * @param  hmmc Pointer to MMC handle
02497   * @retval HAL status
02498   */
02499 static HAL_StatusTypeDef MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
02500 {
02501   /* Set Power State to OFF */
02502   SDIO_PowerState_OFF(hmmc->Instance);
02503   
02504   return HAL_OK;
02505 }
02506 
02507 /**
02508   * @brief  Returns the current card's status.
02509   * @param  hmmc Pointer to MMC handle
02510   * @param  pCardStatus pointer to the buffer that will contain the MMC card 
02511   *         status (Card Status register)  
02512   * @retval error state
02513   */
02514 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
02515 {
02516   uint32_t errorstate = HAL_MMC_ERROR_NONE;
02517   
02518   if(pCardStatus == NULL)
02519   {
02520     return HAL_MMC_ERROR_PARAM;
02521   }
02522   
02523   /* Send Status command */
02524   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
02525   if(errorstate != HAL_OK)
02526   {
02527     return errorstate;
02528   }
02529   
02530   /* Get MMC card status */
02531   *pCardStatus = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
02532   
02533   return HAL_MMC_ERROR_NONE;
02534 }
02535 
02536 /**
02537   * @brief  Wrap up reading in non-blocking mode.
02538   * @param  hmmc pointer to a MMC_HandleTypeDef structure that contains
02539   *              the configuration information.
02540   * @retval HAL status
02541   */
02542 static HAL_StatusTypeDef MMC_Read_IT(MMC_HandleTypeDef *hmmc)
02543 {
02544   uint32_t count = 0U;
02545   uint32_t* tmp;
02546 
02547   tmp = (uint32_t*)hmmc->pRxBuffPtr;
02548   
02549   /* Read data from SDMMC Rx FIFO */
02550   for(count = 0U; count < 8U; count++)
02551   {
02552     *(tmp + count) = SDIO_ReadFIFO(hmmc->Instance);
02553   }
02554   
02555   hmmc->pRxBuffPtr += 8U;
02556   
02557   return HAL_OK;
02558 }
02559 
02560 /**
02561   * @brief  Wrap up writing in non-blocking mode.
02562   * @param  hmmc pointer to a MMC_HandleTypeDef structure that contains
02563   *              the configuration information.
02564   * @retval HAL status
02565   */
02566 static HAL_StatusTypeDef MMC_Write_IT(MMC_HandleTypeDef *hmmc)
02567 {
02568   uint32_t count = 0U;
02569   uint32_t* tmp;
02570   
02571   tmp = (uint32_t*)hmmc->pTxBuffPtr;
02572   
02573   /* Write data to SDMMC Tx FIFO */
02574   for(count = 0U; count < 8U; count++)
02575   {
02576     SDIO_WriteFIFO(hmmc->Instance, (tmp + count));
02577   }
02578   
02579   hmmc->pTxBuffPtr += 8U;
02580   
02581   return HAL_OK;
02582 }
02583 
02584 /**
02585   * @}
02586   */
02587 
02588 #endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F427xx || STM32F437xx || STM32F429xx || STM32F439xx ||
02589           STM32F401xC || STM32F401xE || STM32F411xE || STM32F446xx || STM32F469xx || STM32F479xx || STM32F412Zx || STM32F412Vx || 
02590           STM32F412Rx || STM32F412Cx || STM32F413xx || STM32F423xx */
02591 
02592 #endif /* HAL_MMC_MODULE_ENABLED */
02593 
02594 /**
02595   * @}
02596   */
02597 
02598 /**
02599   * @}
02600   */
02601 
02602 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/