1 /**
2   ******************************************************************************
3   * @file    stm32f2xx_hal_mmc.c
4   * @author  MCD Application Team
5   * @brief   MMC card HAL module driver.
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the Secure Digital (MMC) peripheral:
8   *           + Initialization and de-initialization functions
9   *           + IO operation functions
10   *           + Peripheral Control functions
11   *           + MMC card Control functions
12   *
13   @verbatim
14   ==============================================================================
15                         ##### How to use this driver #####
16   ==============================================================================
17   [..]
18     This driver implements a high level communication layer for read and write from/to
19     this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
20     the user in HAL_MMC_MspInit() function (MSP layer).
21     Basically, the MSP layer configuration should be the same as we provide in the
22     examples.
23     You can easily tailor this configuration according to hardware resources.
24 
25   [..]
26     This driver is a generic layered driver for SDMMC memories which uses the HAL
27     SDMMC driver functions to interface with MMC and eMMC cards devices.
28     It is used as follows:
29 
30     (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
31         (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
32         (##) SDMMC pins configuration for MMC card
33             (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
34             (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
35                   and according to your pin assignment;
36         (##) DMA Configuration if you need to use DMA process (HAL_MMC_ReadBlocks_DMA()
37              and HAL_MMC_WriteBlocks_DMA() APIs).
38             (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
39             (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
40         (##) NVIC configuration if you need to use interrupt process when using DMA transfer.
41             (+++) Configure the SDMMC and DMA interrupt priorities using function HAL_NVIC_SetPriority();
42                   DMA priority is superior to SDMMC's priority
43             (+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ()
44             (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
45                   and __HAL_MMC_DISABLE_IT() inside the communication process.
46             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
47                   and __HAL_MMC_CLEAR_IT()
48         (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
49              and HAL_MMC_WriteBlocks_IT() APIs).
50             (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
51             (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
52             (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
53                   and __HAL_MMC_DISABLE_IT() inside the communication process.
54             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
55                   and __HAL_MMC_CLEAR_IT()
56     (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
57 
58 
59   *** MMC Card Initialization and configuration ***
60   ================================================
61   [..]
62     To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
63     SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
64     This function provide the following operations:
65 
66     (#) Initialize the SDMMC peripheral interface with defaullt configuration.
67         The initialization process is done at 400KHz. You can change or adapt
68         this frequency by adjusting the "ClockDiv" field.
69         The MMC Card frequency (SDMMC_CK) is computed as follows:
70 
71            SDMMC_CK = SDMMCCLK / (ClockDiv + 2)
72 
73         In initialization mode and according to the MMC Card standard,
74         make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
75 
76         This phase of initialization is done through SDMMC_Init() and
77         SDMMC_PowerState_ON() SDMMC low level APIs.
78 
79     (#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
80         This phase allows the card initialization and identification
81         and check the MMC Card type (Standard Capacity or High Capacity)
82         The initialization flow is compatible with MMC standard.
83 
84         This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
85         of plug-off plug-in.
86 
87     (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
88         frequency is set to 24MHz. You can change or adapt this frequency by adjusting
89         the "ClockDiv" field.
90         In transfer mode and according to the MMC Card standard, make sure that the
91         SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
92         To be able to use a frequency higher than 24MHz, you should use the SDMMC
93         peripheral in bypass mode. Refer to the corresponding reference manual
94         for more details.
95 
96     (#) Select the corresponding MMC Card according to the address read with the step 2.
97 
98     (#) Configure the MMC Card in wide bus mode: 4-bits data.
99 
100   *** MMC Card Read operation ***
101   ==============================
102   [..]
103     (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
104         This function support only 512-bytes block length (the block size should be
105         chosen as 512 bytes).
106         You can choose either one block read operation or multiple block read operation
107         by adjusting the "NumberOfBlocks" parameter.
108         After this, you have to ensure that the transfer is done correctly. The check is done
109         through HAL_MMC_GetCardState() function for MMC card state.
110 
111     (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
112         This function support only 512-bytes block length (the block size should be
113         chosen as 512 bytes).
114         You can choose either one block read operation or multiple block read operation
115         by adjusting the "NumberOfBlocks" parameter.
116         After this, you have to ensure that the transfer is done correctly. The check is done
117         through HAL_MMC_GetCardState() function for MMC card state.
118         You could also check the DMA transfer process through the MMC Rx interrupt event.
119 
120     (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
121         This function allows the read of 512 bytes blocks.
122         You can choose either one block read operation or multiple block read operation
123         by adjusting the "NumberOfBlocks" parameter.
124         After this, you have to ensure that the transfer is done correctly. The check is done
125         through HAL_MMC_GetCardState() function for MMC card state.
126         You could also check the IT transfer process through the MMC Rx interrupt event.
127 
128   *** MMC Card Write operation ***
129   ===============================
130   [..]
131     (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
132         This function support only 512-bytes block length (the block size should be
133         chosen as 512 bytes).
134         You can choose either one block read operation or multiple block read operation
135         by adjusting the "NumberOfBlocks" parameter.
136         After this, you have to ensure that the transfer is done correctly. The check is done
137         through HAL_MMC_GetCardState() function for MMC card state.
138 
139     (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
140         This function support only 512-bytes block length (the block size should be
141         chosen as 512 byte).
142         You can choose either one block read operation or multiple block read operation
143         by adjusting the "NumberOfBlocks" parameter.
144         After this, you have to ensure that the transfer is done correctly. The check is done
145         through HAL_MMC_GetCardState() function for MMC card state.
146         You could also check the DMA transfer process through the MMC Tx interrupt event.
147 
148     (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
149         This function allows the read of 512 bytes blocks.
150         You can choose either one block read operation or multiple block read operation
151         by adjusting the "NumberOfBlocks" parameter.
152         After this, you have to ensure that the transfer is done correctly. The check is done
153         through HAL_MMC_GetCardState() function for MMC card state.
154         You could also check the IT transfer process through the MMC Tx interrupt event.
155 
156   *** MMC card information ***
157   ===========================
158   [..]
159     (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
160         It returns useful information about the MMC card such as block size, card type,
161         block number ...
162 
163   *** MMC card CSD register ***
164   ============================
165   [..]
166     (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
167         Some of the CSD parameters are useful for card initialization and identification.
168 
169   *** MMC card CID register ***
170   ============================
171   [..]
172     (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
173         Some of the CID parameters are useful for card initialization and identification.
174 
175   *** MMC HAL driver macros list ***
176   ==================================
177   [..]
178     Below the list of most used macros in MMC HAL driver.
179 
180     (+) __HAL_MMC_ENABLE : Enable the MMC device
181     (+) __HAL_MMC_DISABLE : Disable the MMC device
182     (+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer
183     (+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer
184     (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
185     (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
186     (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
187     (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
188 
189   [..]
190     (@) You can refer to the MMC HAL driver header file for more useful macros
191 
192   *** Callback registration ***
193   =============================================
194   [..]
195     The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
196     allows the user to configure dynamically the driver callbacks.
197 
198     Use Functions @ref HAL_MMC_RegisterCallback() to register a user callback,
199     it allows to register following callbacks:
200       (+) TxCpltCallback : callback when a transmission transfer is completed.
201       (+) RxCpltCallback : callback when a reception transfer is completed.
202       (+) ErrorCallback : callback when error occurs.
203       (+) AbortCpltCallback : callback when abort is completed.
204       (+) MspInitCallback    : MMC MspInit.
205       (+) MspDeInitCallback  : MMC MspDeInit.
206     This function takes as parameters the HAL peripheral handle, the Callback ID
207     and a pointer to the user callback function.
208 
209     Use function @ref HAL_MMC_UnRegisterCallback() to reset a callback to the default
210     weak (surcharged) function. It allows to reset following callbacks:
211       (+) TxCpltCallback : callback when a transmission transfer is completed.
212       (+) RxCpltCallback : callback when a reception transfer is completed.
213       (+) ErrorCallback : callback when error occurs.
214       (+) AbortCpltCallback : callback when abort is completed.
215       (+) MspInitCallback    : MMC MspInit.
216       (+) MspDeInitCallback  : MMC MspDeInit.
217     This function) takes as parameters the HAL peripheral handle and the Callback ID.
218 
219     By default, after the @ref HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
220     all callbacks are reset to the corresponding legacy weak (surcharged) functions.
221     Exception done for MspInit and MspDeInit callbacks that are respectively
222     reset to the legacy weak (surcharged) functions in the @ref HAL_MMC_Init
223     and @ref  HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
224     If not, MspInit or MspDeInit are not null, the @ref HAL_MMC_Init and @ref HAL_MMC_DeInit
225     keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
226 
227     Callbacks can be registered/unregistered in READY state only.
228     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
229     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
230     during the Init/DeInit.
231     In that case first register the MspInit/MspDeInit user callbacks
232     using @ref HAL_MMC_RegisterCallback before calling @ref HAL_MMC_DeInit
233     or @ref HAL_MMC_Init function.
234 
235     When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
236     not defined, the callback registering feature is not available
237     and weak (surcharged) callbacks are used.
238 
239   @endverbatim
240   ******************************************************************************
241   * @attention
242   *
243   * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
244   * All rights reserved.</center></h2>
245   *
246   * This software component is licensed by ST under BSD 3-Clause license,
247   * the "License"; You may not use this file except in compliance with the
248   * License. You may obtain a copy of the License at:
249   *                       opensource.org/licenses/BSD-3-Clause
250   *
251   ******************************************************************************
252   */
253 
254 /* Includes ------------------------------------------------------------------*/
255 #include "stm32f2xx_hal.h"
256 
257 /** @addtogroup STM32F2xx_HAL_Driver
258   * @{
259   */
260 
261 /** @defgroup MMC MMC
262   * @brief MMC HAL module driver
263   * @{
264   */
265 
266 #ifdef HAL_MMC_MODULE_ENABLED
267 
268 #if defined(SDIO)
269 
270 /* Private typedef -----------------------------------------------------------*/
271 /* Private define ------------------------------------------------------------*/
272 /** @addtogroup MMC_Private_Defines
273   * @{
274   */
275 
276 /**
277   * @}
278   */
279 
280 /* Private macro -------------------------------------------------------------*/
281 /* Private variables ---------------------------------------------------------*/
282 /* Private function prototypes -----------------------------------------------*/
283 /* Private functions ---------------------------------------------------------*/
284 /** @defgroup MMC_Private_Functions MMC Private Functions
285   * @{
286   */
287 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
288 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
289 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
290 static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout);
291 static void     MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
292 static void     MMC_Write_IT(MMC_HandleTypeDef *hmmc);
293 static void     MMC_Read_IT(MMC_HandleTypeDef *hmmc);
294 static void     MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma);
295 static void     MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
296 static void     MMC_DMAError(DMA_HandleTypeDef *hdma);
297 static void     MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
298 static void     MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
299 /**
300   * @}
301   */
302 /* Exported functions --------------------------------------------------------*/
303 /** @addtogroup MMC_Exported_Functions
304   * @{
305   */
306 
307 /** @addtogroup MMC_Exported_Functions_Group1
308  *  @brief   Initialization and de-initialization functions
309  *
310 @verbatim
311   ==============================================================================
312           ##### Initialization and de-initialization functions #####
313   ==============================================================================
314   [..]
315     This section provides functions allowing to initialize/de-initialize the MMC
316     card device to be ready for use.
317 
318 @endverbatim
319   * @{
320   */
321 
322 /**
323   * @brief  Initializes the MMC according to the specified parameters in the
324             MMC_HandleTypeDef and create the associated handle.
325   * @param  hmmc: Pointer to the MMC handle
326   * @retval HAL status
327   */
HAL_MMC_Init(MMC_HandleTypeDef * hmmc)328 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
329 {
330   /* Check the MMC handle allocation */
331   if(hmmc == NULL)
332   {
333     return HAL_ERROR;
334   }
335 
336   /* Check the parameters */
337   assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
338   assert_param(IS_SDIO_CLOCK_EDGE(hmmc->Init.ClockEdge));
339   assert_param(IS_SDIO_CLOCK_BYPASS(hmmc->Init.ClockBypass));
340   assert_param(IS_SDIO_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
341   assert_param(IS_SDIO_BUS_WIDE(hmmc->Init.BusWide));
342   assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
343   assert_param(IS_SDIO_CLKDIV(hmmc->Init.ClockDiv));
344 
345   if(hmmc->State == HAL_MMC_STATE_RESET)
346   {
347     /* Allocate lock resource and initialize it */
348     hmmc->Lock = HAL_UNLOCKED;
349 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
350     /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
351     hmmc->TxCpltCallback    = HAL_MMC_TxCpltCallback;
352     hmmc->RxCpltCallback    = HAL_MMC_RxCpltCallback;
353     hmmc->ErrorCallback     = HAL_MMC_ErrorCallback;
354     hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
355 
356     if(hmmc->MspInitCallback == NULL)
357     {
358       hmmc->MspInitCallback = HAL_MMC_MspInit;
359     }
360 
361     /* Init the low level hardware */
362     hmmc->MspInitCallback(hmmc);
363 #else
364     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
365     HAL_MMC_MspInit(hmmc);
366 #endif
367   }
368 
369   hmmc->State = HAL_MMC_STATE_BUSY;
370 
371   /* Initialize the Card parameters */
372   if(HAL_MMC_InitCard(hmmc) == HAL_ERROR)
373   {
374     return HAL_ERROR;
375   }
376 
377   /* Initialize the error code */
378   hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
379 
380   /* Initialize the MMC operation */
381   hmmc->Context = MMC_CONTEXT_NONE;
382 
383   /* Initialize the MMC state */
384   hmmc->State = HAL_MMC_STATE_READY;
385 
386   return HAL_OK;
387 }
388 
389 /**
390   * @brief  Initializes the MMC Card.
391   * @param  hmmc: Pointer to MMC handle
392   * @note   This function initializes the MMC card. It could be used when a card
393             re-initialization is needed.
394   * @retval HAL status
395   */
HAL_MMC_InitCard(MMC_HandleTypeDef * hmmc)396 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
397 {
398   uint32_t errorstate;
399   MMC_InitTypeDef Init;
400   HAL_StatusTypeDef status;
401 
402   /* Default SDIO peripheral configuration for MMC card initialization */
403   Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
404   Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
405   Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
406   Init.BusWide             = SDIO_BUS_WIDE_1B;
407   Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
408   Init.ClockDiv            = SDIO_INIT_CLK_DIV;
409 
410   /* Initialize SDIO peripheral interface with default configuration */
411   status = SDIO_Init(hmmc->Instance, Init);
412   if(status == HAL_ERROR)
413   {
414     return HAL_ERROR;
415   }
416 
417   /* Disable SDIO Clock */
418   __HAL_MMC_DISABLE(hmmc);
419 
420   /* Set Power State to ON */
421   status = SDIO_PowerState_ON(hmmc->Instance);
422   if(status == HAL_ERROR)
423   {
424     return HAL_ERROR;
425   }
426 
427   /* Enable MMC Clock */
428   __HAL_MMC_ENABLE(hmmc);
429 
430   /* Identify card operating voltage */
431   errorstate = MMC_PowerON(hmmc);
432   if(errorstate != HAL_MMC_ERROR_NONE)
433   {
434     hmmc->State = HAL_MMC_STATE_READY;
435     hmmc->ErrorCode |= errorstate;
436     return HAL_ERROR;
437   }
438 
439   /* Card initialization */
440   errorstate = MMC_InitCard(hmmc);
441   if(errorstate != HAL_MMC_ERROR_NONE)
442   {
443     hmmc->State = HAL_MMC_STATE_READY;
444     hmmc->ErrorCode |= errorstate;
445     return HAL_ERROR;
446   }
447 
448   /* Set Block Size for Card */
449   errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
450   if(errorstate != HAL_MMC_ERROR_NONE)
451   {
452     /* Clear all the static flags */
453     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
454     hmmc->ErrorCode |= errorstate;
455     hmmc->State = HAL_MMC_STATE_READY;
456     return HAL_ERROR;
457   }
458 
459   return HAL_OK;
460 }
461 
462 /**
463   * @brief  De-Initializes the MMC card.
464   * @param  hmmc: Pointer to MMC handle
465   * @retval HAL status
466   */
HAL_MMC_DeInit(MMC_HandleTypeDef * hmmc)467 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
468 {
469   /* Check the MMC handle allocation */
470   if(hmmc == NULL)
471   {
472     return HAL_ERROR;
473   }
474 
475   /* Check the parameters */
476   assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
477 
478   hmmc->State = HAL_MMC_STATE_BUSY;
479 
480   /* Set MMC power state to off */
481   MMC_PowerOFF(hmmc);
482 
483 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
484   if(hmmc->MspDeInitCallback == NULL)
485   {
486     hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
487   }
488 
489   /* DeInit the low level hardware */
490   hmmc->MspDeInitCallback(hmmc);
491 #else
492   /* De-Initialize the MSP layer */
493   HAL_MMC_MspDeInit(hmmc);
494 #endif
495 
496   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
497   hmmc->State = HAL_MMC_STATE_RESET;
498 
499   return HAL_OK;
500 }
501 
502 
503 /**
504   * @brief  Initializes the MMC MSP.
505   * @param  hmmc: Pointer to MMC handle
506   * @retval None
507   */
HAL_MMC_MspInit(MMC_HandleTypeDef * hmmc)508 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
509 {
510   /* Prevent unused argument(s) compilation warning */
511   UNUSED(hmmc);
512 
513   /* NOTE : This function Should not be modified, when the callback is needed,
514             the HAL_MMC_MspInit could be implemented in the user file
515    */
516 }
517 
518 /**
519   * @brief  De-Initialize MMC MSP.
520   * @param  hmmc: Pointer to MMC handle
521   * @retval None
522   */
HAL_MMC_MspDeInit(MMC_HandleTypeDef * hmmc)523 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
524 {
525   /* Prevent unused argument(s) compilation warning */
526   UNUSED(hmmc);
527 
528   /* NOTE : This function Should not be modified, when the callback is needed,
529             the HAL_MMC_MspDeInit could be implemented in the user file
530    */
531 }
532 
533 /**
534   * @}
535   */
536 
537 /** @addtogroup MMC_Exported_Functions_Group2
538  *  @brief   Data transfer functions
539  *
540 @verbatim
541   ==============================================================================
542                         ##### IO operation functions #####
543   ==============================================================================
544   [..]
545     This subsection provides a set of functions allowing to manage the data
546     transfer from/to MMC card.
547 
548 @endverbatim
549   * @{
550   */
551 
552 /**
553   * @brief  Reads block(s) from a specified address in a card. The Data transfer
554   *         is managed by polling mode.
555   * @note   This API should be followed by a check on the card state through
556   *         HAL_MMC_GetCardState().
557   * @param  hmmc: Pointer to MMC handle
558   * @param  pData: pointer to the buffer that will contain the received data
559   * @param  BlockAdd: Block Address from where data is to be read
560   * @param  NumberOfBlocks: Number of MMC blocks to read
561   * @param  Timeout: Specify timeout value
562   * @retval HAL status
563   */
HAL_MMC_ReadBlocks(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks,uint32_t Timeout)564 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
565 {
566   SDIO_DataInitTypeDef config;
567   uint32_t errorstate;
568   uint32_t tickstart = HAL_GetTick();
569   uint32_t count, data, dataremaining;
570   uint32_t add = BlockAdd;
571   uint8_t *tempbuff = pData;
572 
573   if(NULL == pData)
574   {
575     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
576     return HAL_ERROR;
577   }
578 
579   if(hmmc->State == HAL_MMC_STATE_READY)
580   {
581     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
582 
583     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
584     {
585       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
586       return HAL_ERROR;
587     }
588 
589     hmmc->State = HAL_MMC_STATE_BUSY;
590 
591     /* Initialize data control register */
592     hmmc->Instance->DCTRL = 0U;
593 
594     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
595     {
596       add *= 512U;
597     }
598 
599     /* Configure the MMC DPSM (Data Path State Machine) */
600     config.DataTimeOut   = SDMMC_DATATIMEOUT;
601     config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
602     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
603     config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
604     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
605     config.DPSM          = SDIO_DPSM_ENABLE;
606     (void)SDIO_ConfigData(hmmc->Instance, &config);
607 
608     /* Read block(s) in polling mode */
609     if(NumberOfBlocks > 1U)
610     {
611       hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
612 
613       /* Read Multi Block command */
614       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
615     }
616     else
617     {
618       hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
619 
620       /* Read Single Block command */
621       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
622     }
623     if(errorstate != HAL_MMC_ERROR_NONE)
624     {
625       /* Clear all the static flags */
626       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
627       hmmc->ErrorCode |= errorstate;
628       hmmc->State = HAL_MMC_STATE_READY;
629       return HAL_ERROR;
630     }
631 
632     /* Poll on SDIO flags */
633     dataremaining = config.DataLength;
634     while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
635     {
636       if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U))
637       {
638         /* Read data from SDIO Rx FIFO */
639         for(count = 0U; count < 8U; count++)
640         {
641           data = SDIO_ReadFIFO(hmmc->Instance);
642           *tempbuff = (uint8_t)(data & 0xFFU);
643           tempbuff++;
644           dataremaining--;
645           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
646           tempbuff++;
647           dataremaining--;
648           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
649           tempbuff++;
650           dataremaining--;
651           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
652           tempbuff++;
653           dataremaining--;
654         }
655       }
656 
657       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
658       {
659         /* Clear all the static flags */
660         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
661         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
662         hmmc->State= HAL_MMC_STATE_READY;
663         return HAL_TIMEOUT;
664       }
665     }
666 
667     /* Send stop transmission command in case of multiblock read */
668     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
669     {
670       /* Send stop transmission command */
671       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
672       if(errorstate != HAL_MMC_ERROR_NONE)
673       {
674         /* Clear all the static flags */
675         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
676         hmmc->ErrorCode |= errorstate;
677         hmmc->State = HAL_MMC_STATE_READY;
678         return HAL_ERROR;
679       }
680     }
681 
682     /* Get error state */
683     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
684     {
685       /* Clear all the static flags */
686       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
687       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
688       hmmc->State = HAL_MMC_STATE_READY;
689       return HAL_ERROR;
690     }
691     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
692     {
693       /* Clear all the static flags */
694       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
695       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
696       hmmc->State = HAL_MMC_STATE_READY;
697       return HAL_ERROR;
698     }
699     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
700     {
701       /* Clear all the static flags */
702       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
703       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
704       hmmc->State = HAL_MMC_STATE_READY;
705       return HAL_ERROR;
706     }
707     else
708     {
709       /* Nothing to do */
710     }
711 
712     /* Empty FIFO if there is still any data */
713     while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U))
714     {
715       data = SDIO_ReadFIFO(hmmc->Instance);
716       *tempbuff = (uint8_t)(data & 0xFFU);
717       tempbuff++;
718       dataremaining--;
719       *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
720       tempbuff++;
721       dataremaining--;
722       *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
723       tempbuff++;
724       dataremaining--;
725       *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
726       tempbuff++;
727       dataremaining--;
728 
729       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
730       {
731         /* Clear all the static flags */
732         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
733         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
734         hmmc->State= HAL_MMC_STATE_READY;
735         return HAL_ERROR;
736       }
737     }
738 
739     /* Clear all the static flags */
740     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
741 
742     hmmc->State = HAL_MMC_STATE_READY;
743 
744     return HAL_OK;
745   }
746   else
747   {
748     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
749     return HAL_ERROR;
750   }
751 }
752 
753 /**
754   * @brief  Allows to write block(s) to a specified address in a card. The Data
755   *         transfer is managed by polling mode.
756   * @note   This API should be followed by a check on the card state through
757   *         HAL_MMC_GetCardState().
758   * @param  hmmc: Pointer to MMC handle
759   * @param  pData: pointer to the buffer that will contain the data to transmit
760   * @param  BlockAdd: Block Address where data will be written
761   * @param  NumberOfBlocks: Number of MMC blocks to write
762   * @param  Timeout: Specify timeout value
763   * @retval HAL status
764   */
HAL_MMC_WriteBlocks(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks,uint32_t Timeout)765 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
766 {
767   SDIO_DataInitTypeDef config;
768   uint32_t errorstate;
769   uint32_t tickstart = HAL_GetTick();
770   uint32_t count, data, dataremaining;
771   uint32_t add = BlockAdd;
772   uint8_t *tempbuff = pData;
773 
774   if(NULL == pData)
775   {
776     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
777     return HAL_ERROR;
778   }
779 
780   if(hmmc->State == HAL_MMC_STATE_READY)
781   {
782     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
783 
784     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
785     {
786       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
787       return HAL_ERROR;
788     }
789 
790     hmmc->State = HAL_MMC_STATE_BUSY;
791 
792     /* Initialize data control register */
793     hmmc->Instance->DCTRL = 0U;
794 
795     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
796     {
797       add *= 512U;
798     }
799 
800     /* Write Blocks in Polling mode */
801     if(NumberOfBlocks > 1U)
802     {
803       hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
804 
805       /* Write Multi Block command */
806       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
807     }
808     else
809     {
810       hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
811 
812       /* Write Single Block command */
813       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
814     }
815     if(errorstate != HAL_MMC_ERROR_NONE)
816     {
817       /* Clear all the static flags */
818       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
819       hmmc->ErrorCode |= errorstate;
820       hmmc->State = HAL_MMC_STATE_READY;
821       return HAL_ERROR;
822     }
823 
824     /* Configure the MMC DPSM (Data Path State Machine) */
825     config.DataTimeOut   = SDMMC_DATATIMEOUT;
826     config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
827     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
828     config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
829     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
830     config.DPSM          = SDIO_DPSM_ENABLE;
831     (void)SDIO_ConfigData(hmmc->Instance, &config);
832 
833     /* Write block(s) in polling mode */
834     dataremaining = config.DataLength;
835     while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
836     {
837       if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U))
838       {
839         /* Write data to SDIO Tx FIFO */
840         for(count = 0U; count < 8U; count++)
841         {
842           data = (uint32_t)(*tempbuff);
843           tempbuff++;
844           dataremaining--;
845           data |= ((uint32_t)(*tempbuff) << 8U);
846           tempbuff++;
847           dataremaining--;
848           data |= ((uint32_t)(*tempbuff) << 16U);
849           tempbuff++;
850           dataremaining--;
851           data |= ((uint32_t)(*tempbuff) << 24U);
852           tempbuff++;
853           dataremaining--;
854           (void)SDIO_WriteFIFO(hmmc->Instance, &data);
855         }
856       }
857 
858       if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
859       {
860         /* Clear all the static flags */
861         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
862         hmmc->ErrorCode |= errorstate;
863         hmmc->State = HAL_MMC_STATE_READY;
864         return HAL_TIMEOUT;
865       }
866     }
867 
868     /* Send stop transmission command in case of multiblock write */
869     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
870     {
871       /* Send stop transmission command */
872       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
873       if(errorstate != HAL_MMC_ERROR_NONE)
874       {
875         /* Clear all the static flags */
876         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
877         hmmc->ErrorCode |= errorstate;
878         hmmc->State = HAL_MMC_STATE_READY;
879         return HAL_ERROR;
880       }
881     }
882 
883     /* Get error state */
884     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
885     {
886       /* Clear all the static flags */
887       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
888       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
889       hmmc->State = HAL_MMC_STATE_READY;
890       return HAL_ERROR;
891     }
892     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
893     {
894       /* Clear all the static flags */
895       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
896       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
897       hmmc->State = HAL_MMC_STATE_READY;
898       return HAL_ERROR;
899     }
900     else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR))
901     {
902       /* Clear all the static flags */
903       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
904       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
905       hmmc->State = HAL_MMC_STATE_READY;
906       return HAL_ERROR;
907     }
908     else
909     {
910       /* Nothing to do */
911     }
912 
913     /* Clear all the static flags */
914     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
915 
916     hmmc->State = HAL_MMC_STATE_READY;
917 
918     return HAL_OK;
919   }
920   else
921   {
922     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
923     return HAL_ERROR;
924   }
925 }
926 
927 /**
928   * @brief  Reads block(s) from a specified address in a card. The Data transfer
929   *         is managed in interrupt mode.
930   * @note   This API should be followed by a check on the card state through
931   *         HAL_MMC_GetCardState().
932   * @note   You could also check the IT transfer process through the MMC Rx
933   *         interrupt event.
934   * @param  hmmc: Pointer to MMC handle
935   * @param  pData: Pointer to the buffer that will contain the received data
936   * @param  BlockAdd: Block Address from where data is to be read
937   * @param  NumberOfBlocks: Number of blocks to read.
938   * @retval HAL status
939   */
HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)940 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
941 {
942   SDIO_DataInitTypeDef config;
943   uint32_t errorstate;
944   uint32_t add = BlockAdd;
945 
946   if(NULL == pData)
947   {
948     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
949     return HAL_ERROR;
950   }
951 
952   if(hmmc->State == HAL_MMC_STATE_READY)
953   {
954     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
955 
956     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
957     {
958       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
959       return HAL_ERROR;
960     }
961 
962     hmmc->State = HAL_MMC_STATE_BUSY;
963 
964     /* Initialize data control register */
965     hmmc->Instance->DCTRL = 0U;
966 
967     hmmc->pRxBuffPtr = pData;
968     hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
969 
970     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
971 
972     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
973     {
974       add *= 512U;
975     }
976 
977     /* Configure the MMC DPSM (Data Path State Machine) */
978     config.DataTimeOut   = SDMMC_DATATIMEOUT;
979     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
980     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
981     config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
982     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
983     config.DPSM          = SDIO_DPSM_ENABLE;
984     (void)SDIO_ConfigData(hmmc->Instance, &config);
985 
986     /* Read Blocks in IT mode */
987     if(NumberOfBlocks > 1U)
988     {
989       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
990 
991       /* Read Multi Block command */
992       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
993     }
994     else
995     {
996       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
997 
998       /* Read Single Block command */
999       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
1000     }
1001 
1002     if(errorstate != HAL_MMC_ERROR_NONE)
1003     {
1004       /* Clear all the static flags */
1005       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1006       hmmc->ErrorCode |= errorstate;
1007       hmmc->State = HAL_MMC_STATE_READY;
1008       return HAL_ERROR;
1009     }
1010 
1011     return HAL_OK;
1012   }
1013   else
1014   {
1015     return HAL_BUSY;
1016   }
1017 }
1018 
1019 /**
1020   * @brief  Writes block(s) to a specified address in a card. The Data transfer
1021   *         is managed in interrupt mode.
1022   * @note   This API should be followed by a check on the card state through
1023   *         HAL_MMC_GetCardState().
1024   * @note   You could also check the IT transfer process through the MMC Tx
1025   *         interrupt event.
1026   * @param  hmmc: Pointer to MMC handle
1027   * @param  pData: Pointer to the buffer that will contain the data to transmit
1028   * @param  BlockAdd: Block Address where data will be written
1029   * @param  NumberOfBlocks: Number of blocks to write
1030   * @retval HAL status
1031   */
HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1032 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1033 {
1034   SDIO_DataInitTypeDef config;
1035   uint32_t errorstate;
1036   uint32_t add = BlockAdd;
1037 
1038   if(NULL == pData)
1039   {
1040     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1041     return HAL_ERROR;
1042   }
1043 
1044   if(hmmc->State == HAL_MMC_STATE_READY)
1045   {
1046     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1047 
1048     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1049     {
1050       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1051       return HAL_ERROR;
1052     }
1053 
1054     hmmc->State = HAL_MMC_STATE_BUSY;
1055 
1056     /* Initialize data control register */
1057     hmmc->Instance->DCTRL = 0U;
1058 
1059     hmmc->pTxBuffPtr = pData;
1060     hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1061 
1062     /* Enable transfer interrupts */
1063     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE));
1064 
1065     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1066     {
1067       add *= 512U;
1068     }
1069 
1070     /* Write Blocks in Polling mode */
1071     if(NumberOfBlocks > 1U)
1072     {
1073       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
1074 
1075       /* Write Multi Block command */
1076       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
1077     }
1078     else
1079     {
1080       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
1081 
1082       /* Write Single Block command */
1083       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
1084     }
1085     if(errorstate != HAL_MMC_ERROR_NONE)
1086     {
1087       /* Clear all the static flags */
1088       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1089       hmmc->ErrorCode |= errorstate;
1090       hmmc->State = HAL_MMC_STATE_READY;
1091       return HAL_ERROR;
1092     }
1093 
1094     /* Configure the MMC DPSM (Data Path State Machine) */
1095     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1096     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1097     config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1098     config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
1099     config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1100     config.DPSM          = SDIO_DPSM_ENABLE;
1101     (void)SDIO_ConfigData(hmmc->Instance, &config);
1102 
1103     return HAL_OK;
1104   }
1105   else
1106   {
1107     return HAL_BUSY;
1108   }
1109 }
1110 
1111 /**
1112   * @brief  Reads block(s) from a specified address in a card. The Data transfer
1113   *         is managed by DMA mode.
1114   * @note   This API should be followed by a check on the card state through
1115   *         HAL_MMC_GetCardState().
1116   * @note   You could also check the DMA transfer process through the MMC Rx
1117   *         interrupt event.
1118   * @param  hmmc: Pointer MMC handle
1119   * @param  pData: Pointer to the buffer that will contain the received data
1120   * @param  BlockAdd: Block Address from where data is to be read
1121   * @param  NumberOfBlocks: Number of blocks to read.
1122   * @retval HAL status
1123   */
HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1124 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1125 {
1126   SDIO_DataInitTypeDef config;
1127   uint32_t errorstate;
1128   uint32_t add = BlockAdd;
1129 
1130   if(NULL == pData)
1131   {
1132     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1133     return HAL_ERROR;
1134   }
1135 
1136   if(hmmc->State == HAL_MMC_STATE_READY)
1137   {
1138     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1139 
1140     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1141     {
1142       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1143       return HAL_ERROR;
1144     }
1145 
1146     hmmc->State = HAL_MMC_STATE_BUSY;
1147 
1148     /* Initialize data control register */
1149     hmmc->Instance->DCTRL = 0U;
1150 
1151     __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
1152 
1153     /* Set the DMA transfer complete callback */
1154     hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt;
1155 
1156     /* Set the DMA error callback */
1157     hmmc->hdmarx->XferErrorCallback = MMC_DMAError;
1158 
1159     /* Set the DMA Abort callback */
1160     hmmc->hdmarx->XferAbortCallback = NULL;
1161 
1162     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1163     {
1164       add *= 512U;
1165     }
1166 
1167     /* Force DMA Direction */
1168     hmmc->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
1169     MODIFY_REG(hmmc->hdmarx->Instance->CR, DMA_SxCR_DIR, hmmc->hdmarx->Init.Direction);
1170 
1171     /* Enable the DMA Channel */
1172     if(HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
1173     {
1174       __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
1175       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1176       hmmc->ErrorCode = HAL_MMC_ERROR_DMA;
1177       hmmc->State = HAL_MMC_STATE_READY;
1178       return HAL_ERROR;
1179     }
1180     else
1181     {
1182       /* Enable MMC DMA transfer */
1183       __HAL_MMC_DMA_ENABLE(hmmc);
1184 
1185       /* Configure the MMC DPSM (Data Path State Machine) */
1186       config.DataTimeOut   = SDMMC_DATATIMEOUT;
1187       config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1188       config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1189       config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
1190       config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1191       config.DPSM          = SDIO_DPSM_ENABLE;
1192       (void)SDIO_ConfigData(hmmc->Instance, &config);
1193 
1194       /* Read Blocks in DMA mode */
1195       if(NumberOfBlocks > 1U)
1196       {
1197         hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1198 
1199         /* Read Multi Block command */
1200         errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
1201       }
1202       else
1203       {
1204         hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1205 
1206         /* Read Single Block command */
1207         errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
1208       }
1209       if(errorstate != HAL_MMC_ERROR_NONE)
1210       {
1211         /* Clear all the static flags */
1212         __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1213         __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
1214         hmmc->ErrorCode = errorstate;
1215         hmmc->State = HAL_MMC_STATE_READY;
1216         return HAL_ERROR;
1217       }
1218 
1219       return HAL_OK;
1220     }
1221   }
1222   else
1223   {
1224     return HAL_BUSY;
1225   }
1226 }
1227 
1228 /**
1229   * @brief  Writes block(s) to a specified address in a card. The Data transfer
1230   *         is managed by DMA mode.
1231   * @note   This API should be followed by a check on the card state through
1232   *         HAL_MMC_GetCardState().
1233   * @note   You could also check the DMA transfer process through the MMC Tx
1234   *         interrupt event.
1235   * @param  hmmc: Pointer to MMC handle
1236   * @param  pData: Pointer to the buffer that will contain the data to transmit
1237   * @param  BlockAdd: Block Address where data will be written
1238   * @param  NumberOfBlocks: Number of blocks to write
1239   * @retval HAL status
1240   */
HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1241 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1242 {
1243   SDIO_DataInitTypeDef config;
1244   uint32_t errorstate;
1245   uint32_t add = BlockAdd;
1246 
1247   if(NULL == pData)
1248   {
1249     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1250     return HAL_ERROR;
1251   }
1252 
1253   if(hmmc->State == HAL_MMC_STATE_READY)
1254   {
1255     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1256 
1257     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1258     {
1259       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1260       return HAL_ERROR;
1261     }
1262 
1263     hmmc->State = HAL_MMC_STATE_BUSY;
1264 
1265     /* Initialize data control register */
1266     hmmc->Instance->DCTRL = 0U;
1267 
1268     /* Enable MMC Error interrupts */
1269 	__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
1270 
1271     /* Set the DMA transfer complete callback */
1272     hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt;
1273 
1274     /* Set the DMA error callback */
1275     hmmc->hdmatx->XferErrorCallback = MMC_DMAError;
1276 
1277     /* Set the DMA Abort callback */
1278     hmmc->hdmatx->XferAbortCallback = NULL;
1279 
1280     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1281     {
1282       add *= 512U;
1283     }
1284 
1285 
1286     /* Write Blocks in Polling mode */
1287     if(NumberOfBlocks > 1U)
1288     {
1289       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1290 
1291       /* Write Multi Block command */
1292       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
1293     }
1294     else
1295     {
1296       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1297 
1298       /* Write Single Block command */
1299       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
1300     }
1301     if(errorstate != HAL_MMC_ERROR_NONE)
1302     {
1303       /* Clear all the static flags */
1304       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1305       __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
1306       hmmc->ErrorCode |= errorstate;
1307       hmmc->State = HAL_MMC_STATE_READY;
1308       return HAL_ERROR;
1309     }
1310 
1311     /* Enable SDIO DMA transfer */
1312     __HAL_MMC_DMA_ENABLE(hmmc);
1313 
1314     /* Force DMA Direction */
1315     hmmc->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
1316     MODIFY_REG(hmmc->hdmatx->Instance->CR, DMA_SxCR_DIR, hmmc->hdmatx->Init.Direction);
1317 
1318     /* Enable the DMA Channel */
1319     if(HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
1320     {
1321       __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
1322       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1323       hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
1324       hmmc->State = HAL_MMC_STATE_READY;
1325       return HAL_ERROR;
1326     }
1327     else
1328     {
1329       /* Configure the MMC DPSM (Data Path State Machine) */
1330       config.DataTimeOut   = SDMMC_DATATIMEOUT;
1331       config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1332       config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1333       config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
1334       config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1335       config.DPSM          = SDIO_DPSM_ENABLE;
1336       (void)SDIO_ConfigData(hmmc->Instance, &config);
1337 
1338       return HAL_OK;
1339     }
1340   }
1341   else
1342   {
1343     return HAL_BUSY;
1344   }
1345 }
1346 
1347 /**
1348   * @brief  Erases the specified memory area of the given MMC card.
1349   * @note   This API should be followed by a check on the card state through
1350   *         HAL_MMC_GetCardState().
1351   * @param  hmmc: Pointer to MMC handle
1352   * @param  BlockStartAdd: Start Block address
1353   * @param  BlockEndAdd: End Block address
1354   * @retval HAL status
1355   */
HAL_MMC_Erase(MMC_HandleTypeDef * hmmc,uint32_t BlockStartAdd,uint32_t BlockEndAdd)1356 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
1357 {
1358   uint32_t errorstate;
1359   uint32_t start_add = BlockStartAdd;
1360   uint32_t end_add = BlockEndAdd;
1361 
1362   if(hmmc->State == HAL_MMC_STATE_READY)
1363   {
1364     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1365 
1366     if(end_add < start_add)
1367     {
1368       hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1369       return HAL_ERROR;
1370     }
1371 
1372     if(end_add > (hmmc->MmcCard.LogBlockNbr))
1373     {
1374       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1375       return HAL_ERROR;
1376     }
1377 
1378     hmmc->State = HAL_MMC_STATE_BUSY;
1379 
1380     /* Check if the card command class supports erase command */
1381     if(((hmmc->MmcCard.Class) & SDIO_CCCC_ERASE) == 0U)
1382     {
1383       /* Clear all the static flags */
1384       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1385       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
1386       hmmc->State = HAL_MMC_STATE_READY;
1387       return HAL_ERROR;
1388     }
1389 
1390     if((SDIO_GetResponse(hmmc->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
1391     {
1392       /* Clear all the static flags */
1393       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1394       hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
1395       hmmc->State = HAL_MMC_STATE_READY;
1396       return HAL_ERROR;
1397     }
1398 
1399     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1400     {
1401       start_add *= 512U;
1402       end_add   *= 512U;
1403     }
1404 
1405     /* Send CMD35 MMC_ERASE_GRP_START with argument as addr  */
1406     errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
1407     if(errorstate != HAL_MMC_ERROR_NONE)
1408     {
1409       /* Clear all the static flags */
1410       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1411       hmmc->ErrorCode |= errorstate;
1412       hmmc->State = HAL_MMC_STATE_READY;
1413       return HAL_ERROR;
1414     }
1415 
1416     /* Send CMD36 MMC_ERASE_GRP_END with argument as addr  */
1417     errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
1418     if(errorstate != HAL_MMC_ERROR_NONE)
1419     {
1420       /* Clear all the static flags */
1421       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1422       hmmc->ErrorCode |= errorstate;
1423       hmmc->State = HAL_MMC_STATE_READY;
1424       return HAL_ERROR;
1425     }
1426 
1427     /* Send CMD38 ERASE */
1428     errorstate = SDMMC_CmdErase(hmmc->Instance);
1429     if(errorstate != HAL_MMC_ERROR_NONE)
1430     {
1431       /* Clear all the static flags */
1432       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1433       hmmc->ErrorCode |= errorstate;
1434       hmmc->State = HAL_MMC_STATE_READY;
1435       return HAL_ERROR;
1436     }
1437 
1438     hmmc->State = HAL_MMC_STATE_READY;
1439 
1440     return HAL_OK;
1441   }
1442   else
1443   {
1444     return HAL_BUSY;
1445   }
1446 }
1447 
1448 /**
1449   * @brief  This function handles MMC card interrupt request.
1450   * @param  hmmc: Pointer to MMC handle
1451   * @retval None
1452   */
HAL_MMC_IRQHandler(MMC_HandleTypeDef * hmmc)1453 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
1454 {
1455   uint32_t errorstate;
1456   uint32_t context = hmmc->Context;
1457 
1458   /* Check for SDIO interrupt flags */
1459   if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1460   {
1461     MMC_Read_IT(hmmc);
1462   }
1463 
1464   else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) != RESET)
1465   {
1466     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_DATAEND);
1467 
1468     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
1469                              SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
1470 
1471     hmmc->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN);
1472 
1473     if((context & MMC_CONTEXT_DMA) != 0U)
1474     {
1475       if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
1476       {
1477         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1478         if(errorstate != HAL_MMC_ERROR_NONE)
1479         {
1480           hmmc->ErrorCode |= errorstate;
1481 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1482           hmmc->ErrorCallback(hmmc);
1483 #else
1484           HAL_MMC_ErrorCallback(hmmc);
1485 #endif
1486         }
1487       }
1488       if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
1489       {
1490         /* Disable the DMA transfer for transmit request by setting the DMAEN bit
1491         in the MMC DCTRL register */
1492         hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
1493 
1494         hmmc->State = HAL_MMC_STATE_READY;
1495 
1496 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1497         hmmc->TxCpltCallback(hmmc);
1498 #else
1499         HAL_MMC_TxCpltCallback(hmmc);
1500 #endif
1501       }
1502     }
1503     else if((context & MMC_CONTEXT_IT) != 0U)
1504     {
1505       /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1506       if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1507       {
1508         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1509         if(errorstate != HAL_MMC_ERROR_NONE)
1510         {
1511           hmmc->ErrorCode |= errorstate;
1512 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1513           hmmc->ErrorCallback(hmmc);
1514 #else
1515           HAL_MMC_ErrorCallback(hmmc);
1516 #endif
1517         }
1518       }
1519 
1520       /* Clear all the static flags */
1521       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
1522 
1523       hmmc->State = HAL_MMC_STATE_READY;
1524       if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1525       {
1526 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1527         hmmc->RxCpltCallback(hmmc);
1528 #else
1529         HAL_MMC_RxCpltCallback(hmmc);
1530 #endif
1531       }
1532       else
1533       {
1534 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1535         hmmc->TxCpltCallback(hmmc);
1536 #else
1537         HAL_MMC_TxCpltCallback(hmmc);
1538 #endif
1539       }
1540     }
1541     else
1542     {
1543       /* Nothing to do */
1544     }
1545   }
1546 
1547   else if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1548   {
1549     MMC_Write_IT(hmmc);
1550   }
1551 
1552   else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET)
1553   {
1554     /* Set Error code */
1555     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL) != RESET)
1556     {
1557       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
1558     }
1559     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT) != RESET)
1560     {
1561       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
1562     }
1563     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR) != RESET)
1564     {
1565       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
1566     }
1567     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR) != RESET)
1568     {
1569       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
1570     }
1571 
1572     /* Clear All flags */
1573     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR);
1574 
1575     /* Disable all interrupts */
1576     __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
1577                                SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
1578 
1579     hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
1580 
1581     if((context & MMC_CONTEXT_IT) != 0U)
1582     {
1583       /* Set the MMC state to ready to be able to start again the process */
1584       hmmc->State = HAL_MMC_STATE_READY;
1585 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1586       hmmc->ErrorCallback(hmmc);
1587 #else
1588       HAL_MMC_ErrorCallback(hmmc);
1589 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1590     }
1591     else if((context & MMC_CONTEXT_DMA) != 0U)
1592     {
1593       /* Abort the MMC DMA Streams */
1594       if(hmmc->hdmatx != NULL)
1595       {
1596         /* Set the DMA Tx abort callback */
1597         hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
1598         /* Abort DMA in IT mode */
1599         if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
1600         {
1601           MMC_DMATxAbort(hmmc->hdmatx);
1602         }
1603       }
1604       else if(hmmc->hdmarx != NULL)
1605       {
1606         /* Set the DMA Rx abort callback */
1607         hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
1608         /* Abort DMA in IT mode */
1609         if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
1610         {
1611           MMC_DMARxAbort(hmmc->hdmarx);
1612         }
1613       }
1614       else
1615       {
1616         hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1617         hmmc->State = HAL_MMC_STATE_READY;
1618 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1619         hmmc->AbortCpltCallback(hmmc);
1620 #else
1621         HAL_MMC_AbortCallback(hmmc);
1622 #endif
1623       }
1624     }
1625     else
1626     {
1627       /* Nothing to do */
1628     }
1629   }
1630 
1631   else
1632   {
1633     /* Nothing to do */
1634   }
1635 }
1636 
1637 /**
1638   * @brief return the MMC state
1639   * @param hmmc: Pointer to mmc handle
1640   * @retval HAL state
1641   */
HAL_MMC_GetState(MMC_HandleTypeDef * hmmc)1642 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
1643 {
1644   return hmmc->State;
1645 }
1646 
1647 /**
1648 * @brief  Return the MMC error code
1649 * @param  hmmc : Pointer to a MMC_HandleTypeDef structure that contains
1650   *              the configuration information.
1651 * @retval MMC Error Code
1652 */
HAL_MMC_GetError(MMC_HandleTypeDef * hmmc)1653 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
1654 {
1655   return hmmc->ErrorCode;
1656 }
1657 
1658 /**
1659   * @brief Tx Transfer completed callbacks
1660   * @param hmmc: Pointer to MMC handle
1661   * @retval None
1662   */
HAL_MMC_TxCpltCallback(MMC_HandleTypeDef * hmmc)1663 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
1664 {
1665   /* Prevent unused argument(s) compilation warning */
1666   UNUSED(hmmc);
1667 
1668   /* NOTE : This function should not be modified, when the callback is needed,
1669             the HAL_MMC_TxCpltCallback can be implemented in the user file
1670    */
1671 }
1672 
1673 /**
1674   * @brief Rx Transfer completed callbacks
1675   * @param hmmc: Pointer MMC handle
1676   * @retval None
1677   */
HAL_MMC_RxCpltCallback(MMC_HandleTypeDef * hmmc)1678 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
1679 {
1680   /* Prevent unused argument(s) compilation warning */
1681   UNUSED(hmmc);
1682 
1683   /* NOTE : This function should not be modified, when the callback is needed,
1684             the HAL_MMC_RxCpltCallback can be implemented in the user file
1685    */
1686 }
1687 
1688 /**
1689   * @brief MMC error callbacks
1690   * @param hmmc: Pointer MMC handle
1691   * @retval None
1692   */
HAL_MMC_ErrorCallback(MMC_HandleTypeDef * hmmc)1693 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
1694 {
1695   /* Prevent unused argument(s) compilation warning */
1696   UNUSED(hmmc);
1697 
1698   /* NOTE : This function should not be modified, when the callback is needed,
1699             the HAL_MMC_ErrorCallback can be implemented in the user file
1700    */
1701 }
1702 
1703 /**
1704   * @brief MMC Abort callbacks
1705   * @param hmmc: Pointer MMC handle
1706   * @retval None
1707   */
HAL_MMC_AbortCallback(MMC_HandleTypeDef * hmmc)1708 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
1709 {
1710   /* Prevent unused argument(s) compilation warning */
1711   UNUSED(hmmc);
1712 
1713   /* NOTE : This function should not be modified, when the callback is needed,
1714             the HAL_MMC_AbortCallback can be implemented in the user file
1715    */
1716 }
1717 
1718 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1719 /**
1720   * @brief  Register a User MMC Callback
1721   *         To be used instead of the weak (surcharged) predefined callback
1722   * @param hmmc : MMC handle
1723   * @param CallbackId : ID of the callback to be registered
1724   *        This parameter can be one of the following values:
1725   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID    MMC Tx Complete Callback ID
1726   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID    MMC Rx Complete Callback ID
1727   *          @arg @ref HAL_MMC_ERROR_CB_ID      MMC Error Callback ID
1728   *          @arg @ref HAL_MMC_ABORT_CB_ID      MMC Abort Callback ID
1729   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID   MMC MspInit Callback ID
1730   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1731   * @param pCallback : pointer to the Callback function
1732   * @retval status
1733   */
HAL_MMC_RegisterCallback(MMC_HandleTypeDef * hmmc,HAL_MMC_CallbackIDTypeDef CallbackId,pMMC_CallbackTypeDef pCallback)1734 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
1735 {
1736   HAL_StatusTypeDef status = HAL_OK;
1737 
1738   if(pCallback == NULL)
1739   {
1740     /* Update the error code */
1741     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1742     return HAL_ERROR;
1743   }
1744 
1745   /* Process locked */
1746   __HAL_LOCK(hmmc);
1747 
1748   if(hmmc->State == HAL_MMC_STATE_READY)
1749   {
1750     switch (CallbackId)
1751     {
1752     case HAL_MMC_TX_CPLT_CB_ID :
1753       hmmc->TxCpltCallback = pCallback;
1754       break;
1755     case HAL_MMC_RX_CPLT_CB_ID :
1756       hmmc->RxCpltCallback = pCallback;
1757       break;
1758     case HAL_MMC_ERROR_CB_ID :
1759       hmmc->ErrorCallback = pCallback;
1760       break;
1761     case HAL_MMC_ABORT_CB_ID :
1762       hmmc->AbortCpltCallback = pCallback;
1763       break;
1764     case HAL_MMC_MSP_INIT_CB_ID :
1765       hmmc->MspInitCallback = pCallback;
1766       break;
1767     case HAL_MMC_MSP_DEINIT_CB_ID :
1768       hmmc->MspDeInitCallback = pCallback;
1769       break;
1770     default :
1771       /* Update the error code */
1772       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1773       /* update return status */
1774       status =  HAL_ERROR;
1775       break;
1776     }
1777   }
1778   else if (hmmc->State == HAL_MMC_STATE_RESET)
1779   {
1780     switch (CallbackId)
1781     {
1782     case HAL_MMC_MSP_INIT_CB_ID :
1783       hmmc->MspInitCallback = pCallback;
1784       break;
1785     case HAL_MMC_MSP_DEINIT_CB_ID :
1786       hmmc->MspDeInitCallback = pCallback;
1787       break;
1788     default :
1789       /* Update the error code */
1790       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1791       /* update return status */
1792       status =  HAL_ERROR;
1793       break;
1794     }
1795   }
1796   else
1797   {
1798     /* Update the error code */
1799     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1800     /* update return status */
1801     status =  HAL_ERROR;
1802   }
1803 
1804   /* Release Lock */
1805   __HAL_UNLOCK(hmmc);
1806   return status;
1807 }
1808 
1809 /**
1810   * @brief  Unregister a User MMC Callback
1811   *         MMC Callback is redirected to the weak (surcharged) predefined callback
1812   * @param hmmc : MMC handle
1813   * @param CallbackId : ID of the callback to be unregistered
1814   *        This parameter can be one of the following values:
1815   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID    MMC Tx Complete Callback ID
1816   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID    MMC Rx Complete Callback ID
1817   *          @arg @ref HAL_MMC_ERROR_CB_ID      MMC Error Callback ID
1818   *          @arg @ref HAL_MMC_ABORT_CB_ID      MMC Abort Callback ID
1819   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID   MMC MspInit Callback ID
1820   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1821   * @retval status
1822   */
HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef * hmmc,HAL_MMC_CallbackIDTypeDef CallbackId)1823 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
1824 {
1825   HAL_StatusTypeDef status = HAL_OK;
1826 
1827   /* Process locked */
1828   __HAL_LOCK(hmmc);
1829 
1830   if(hmmc->State == HAL_MMC_STATE_READY)
1831   {
1832     switch (CallbackId)
1833     {
1834     case HAL_MMC_TX_CPLT_CB_ID :
1835       hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
1836       break;
1837     case HAL_MMC_RX_CPLT_CB_ID :
1838       hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
1839       break;
1840     case HAL_MMC_ERROR_CB_ID :
1841       hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
1842       break;
1843     case HAL_MMC_ABORT_CB_ID :
1844       hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
1845       break;
1846     case HAL_MMC_MSP_INIT_CB_ID :
1847       hmmc->MspInitCallback = HAL_MMC_MspInit;
1848       break;
1849     case HAL_MMC_MSP_DEINIT_CB_ID :
1850       hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1851       break;
1852     default :
1853       /* Update the error code */
1854       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1855       /* update return status */
1856       status =  HAL_ERROR;
1857       break;
1858     }
1859   }
1860   else if (hmmc->State == HAL_MMC_STATE_RESET)
1861   {
1862     switch (CallbackId)
1863     {
1864     case HAL_MMC_MSP_INIT_CB_ID :
1865       hmmc->MspInitCallback = HAL_MMC_MspInit;
1866       break;
1867     case HAL_MMC_MSP_DEINIT_CB_ID :
1868       hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1869       break;
1870     default :
1871       /* Update the error code */
1872       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1873       /* update return status */
1874       status =  HAL_ERROR;
1875       break;
1876     }
1877   }
1878   else
1879   {
1880     /* Update the error code */
1881     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1882     /* update return status */
1883     status =  HAL_ERROR;
1884   }
1885 
1886   /* Release Lock */
1887   __HAL_UNLOCK(hmmc);
1888   return status;
1889 }
1890 #endif
1891 
1892 /**
1893   * @}
1894   */
1895 
1896 /** @addtogroup MMC_Exported_Functions_Group3
1897  *  @brief   management functions
1898  *
1899 @verbatim
1900   ==============================================================================
1901                       ##### Peripheral Control functions #####
1902   ==============================================================================
1903   [..]
1904     This subsection provides a set of functions allowing to control the MMC card
1905     operations and get the related information
1906 
1907 @endverbatim
1908   * @{
1909   */
1910 
1911 /**
1912   * @brief  Returns information the information of the card which are stored on
1913   *         the CID register.
1914   * @param  hmmc: Pointer to MMC handle
1915   * @param  pCID: Pointer to a HAL_MMC_CIDTypedef structure that
1916   *         contains all CID register parameters
1917   * @retval HAL status
1918   */
HAL_MMC_GetCardCID(MMC_HandleTypeDef * hmmc,HAL_MMC_CardCIDTypeDef * pCID)1919 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
1920 {
1921   pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
1922 
1923   pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
1924 
1925   pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
1926 
1927   pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
1928 
1929   pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
1930 
1931   pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
1932 
1933   pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
1934 
1935   pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
1936 
1937   pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
1938 
1939   pCID->Reserved2 = 1U;
1940 
1941   return HAL_OK;
1942 }
1943 
1944 /**
1945   * @brief  Returns information the information of the card which are stored on
1946   *         the CSD register.
1947   * @param  hmmc: Pointer to MMC handle
1948   * @param  pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
1949   *         contains all CSD register parameters
1950   * @retval HAL status
1951   */
HAL_MMC_GetCardCSD(MMC_HandleTypeDef * hmmc,HAL_MMC_CardCSDTypeDef * pCSD)1952 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
1953 {
1954   uint32_t block_nbr = 0;
1955 
1956   pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
1957 
1958   pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
1959 
1960   pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
1961 
1962   pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
1963 
1964   pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
1965 
1966   pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
1967 
1968   pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
1969 
1970   pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
1971 
1972   pCSD->PartBlockRead   = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
1973 
1974   pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
1975 
1976   pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
1977 
1978   pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
1979 
1980   pCSD->Reserved2 = 0U; /*!< Reserved */
1981 
1982   pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
1983 
1984   pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
1985 
1986   pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
1987 
1988   pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
1989 
1990   pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
1991 
1992   pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
1993 
1994   if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
1995   {
1996     return HAL_ERROR;
1997   }
1998 
1999   if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
2000   {
2001     hmmc->MmcCard.BlockNbr  = (pCSD->DeviceSize + 1U) ;
2002     hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
2003     hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
2004     hmmc->MmcCard.LogBlockNbr =  (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
2005     hmmc->MmcCard.LogBlockSize = 512U;
2006   }
2007   else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
2008   {
2009     hmmc->MmcCard.BlockNbr = block_nbr;
2010     hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
2011     hmmc->MmcCard.BlockSize = 512U;
2012     hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
2013   }
2014   else
2015   {
2016     /* Clear all the static flags */
2017     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2018     hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2019     hmmc->State = HAL_MMC_STATE_READY;
2020     return HAL_ERROR;
2021   }
2022 
2023   pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
2024 
2025   pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
2026 
2027   pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
2028 
2029   pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
2030 
2031   pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
2032 
2033   pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
2034 
2035   pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
2036 
2037   pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
2038 
2039   pCSD->Reserved3 = 0;
2040 
2041   pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
2042 
2043   pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
2044 
2045   pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
2046 
2047   pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
2048 
2049   pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
2050 
2051   pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
2052 
2053   pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
2054 
2055   pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
2056 
2057   pCSD->Reserved4 = 1;
2058 
2059   return HAL_OK;
2060 }
2061 
2062 /**
2063   * @brief  Gets the MMC card info.
2064   * @param  hmmc: Pointer to MMC handle
2065   * @param  pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
2066   *         will contain the MMC card status information
2067   * @retval HAL status
2068   */
HAL_MMC_GetCardInfo(MMC_HandleTypeDef * hmmc,HAL_MMC_CardInfoTypeDef * pCardInfo)2069 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
2070 {
2071   pCardInfo->CardType     = (uint32_t)(hmmc->MmcCard.CardType);
2072   pCardInfo->Class        = (uint32_t)(hmmc->MmcCard.Class);
2073   pCardInfo->RelCardAdd   = (uint32_t)(hmmc->MmcCard.RelCardAdd);
2074   pCardInfo->BlockNbr     = (uint32_t)(hmmc->MmcCard.BlockNbr);
2075   pCardInfo->BlockSize    = (uint32_t)(hmmc->MmcCard.BlockSize);
2076   pCardInfo->LogBlockNbr  = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
2077   pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
2078 
2079   return HAL_OK;
2080 }
2081 
2082 /**
2083   * @brief  Enables wide bus operation for the requested card if supported by
2084   *         card.
2085   * @param  hmmc: Pointer to MMC handle
2086   * @param  WideMode: Specifies the MMC card wide bus mode
2087   *          This parameter can be one of the following values:
2088   *            @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
2089   *            @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
2090   *            @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
2091   * @retval HAL status
2092   */
HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef * hmmc,uint32_t WideMode)2093 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
2094 {
2095   __IO uint32_t count = 0U;
2096   SDIO_InitTypeDef Init;
2097   uint32_t errorstate;
2098   uint32_t response = 0U, busy = 0U;
2099 
2100   /* Check the parameters */
2101   assert_param(IS_SDIO_BUS_WIDE(WideMode));
2102 
2103   /* Change State */
2104   hmmc->State = HAL_MMC_STATE_BUSY;
2105 
2106   /* Update Clock for Bus mode update */
2107   Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
2108   Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
2109   Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
2110   Init.BusWide             = WideMode;
2111   Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
2112   Init.ClockDiv            = SDIO_INIT_CLK_DIV;
2113   /* Initialize SDIO*/
2114   (void)SDIO_Init(hmmc->Instance, Init);
2115 
2116   if(WideMode == SDIO_BUS_WIDE_8B)
2117   {
2118     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
2119     if(errorstate != HAL_MMC_ERROR_NONE)
2120     {
2121       hmmc->ErrorCode |= errorstate;
2122     }
2123   }
2124   else if(WideMode == SDIO_BUS_WIDE_4B)
2125   {
2126     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
2127     if(errorstate != HAL_MMC_ERROR_NONE)
2128     {
2129       hmmc->ErrorCode |= errorstate;
2130     }
2131   }
2132   else if(WideMode == SDIO_BUS_WIDE_1B)
2133   {
2134     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
2135     if(errorstate != HAL_MMC_ERROR_NONE)
2136     {
2137       hmmc->ErrorCode |= errorstate;
2138     }
2139   }
2140   else
2141   {
2142     /* WideMode is not a valid argument*/
2143     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2144   }
2145 
2146   /* Check for switch error and violation of the trial number of sending CMD 13 */
2147   while(busy == 0U)
2148   {
2149     if(count == SDMMC_MAX_TRIAL)
2150     {
2151       hmmc->State = HAL_MMC_STATE_READY;
2152       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2153       return HAL_ERROR;
2154     }
2155     count++;
2156 
2157     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2158     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2159     if(errorstate != HAL_MMC_ERROR_NONE)
2160     {
2161       hmmc->ErrorCode |= errorstate;
2162     }
2163 
2164     /* Get command response */
2165     response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2166 
2167     /* Get operating voltage*/
2168     busy = (((response >> 7U) == 1U) ? 0U : 1U);
2169   }
2170 
2171   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2172   count = SDMMC_DATATIMEOUT;
2173   while((response & 0x00000100U) == 0U)
2174   {
2175     if(count == 0U)
2176     {
2177       hmmc->State = HAL_MMC_STATE_READY;
2178       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2179       return HAL_ERROR;
2180     }
2181     count--;
2182 
2183     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2184     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2185     if(errorstate != HAL_MMC_ERROR_NONE)
2186     {
2187       hmmc->ErrorCode |= errorstate;
2188     }
2189 
2190     /* Get command response */
2191     response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2192   }
2193 
2194   if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2195   {
2196     /* Clear all the static flags */
2197     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2198     hmmc->State = HAL_MMC_STATE_READY;
2199     return HAL_ERROR;
2200   }
2201   else
2202   {
2203     /* Configure the SDIO peripheral */
2204     Init.ClockEdge           = hmmc->Init.ClockEdge;
2205     Init.ClockBypass         = hmmc->Init.ClockBypass;
2206     Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
2207     Init.BusWide             = WideMode;
2208     Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
2209     Init.ClockDiv            = hmmc->Init.ClockDiv;
2210     (void)SDIO_Init(hmmc->Instance, Init);
2211   }
2212 
2213   /* Change State */
2214   hmmc->State = HAL_MMC_STATE_READY;
2215 
2216   return HAL_OK;
2217 }
2218 
2219 /**
2220   * @brief  Gets the current mmc card data state.
2221   * @param  hmmc: pointer to MMC handle
2222   * @retval Card state
2223   */
HAL_MMC_GetCardState(MMC_HandleTypeDef * hmmc)2224 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
2225 {
2226   uint32_t cardstate;
2227   uint32_t errorstate;
2228   uint32_t resp1 = 0U;
2229 
2230   errorstate = MMC_SendStatus(hmmc, &resp1);
2231   if(errorstate != HAL_MMC_ERROR_NONE)
2232   {
2233     hmmc->ErrorCode |= errorstate;
2234   }
2235 
2236   cardstate = ((resp1 >> 9U) & 0x0FU);
2237 
2238   return (HAL_MMC_CardStateTypeDef)cardstate;
2239 }
2240 
2241 /**
2242   * @brief  Abort the current transfer and disable the MMC.
2243   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2244   *                the configuration information for MMC module.
2245   * @retval HAL status
2246   */
HAL_MMC_Abort(MMC_HandleTypeDef * hmmc)2247 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
2248 {
2249   HAL_MMC_CardStateTypeDef CardState;
2250 
2251   /* DIsable All interrupts */
2252   __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
2253                              SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
2254 
2255   /* Clear All flags */
2256   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2257 
2258   if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2259   {
2260     /* Disable the MMC DMA request */
2261     hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
2262 
2263     /* Abort the MMC DMA Tx Stream */
2264     if(hmmc->hdmatx != NULL)
2265     {
2266       if(HAL_DMA_Abort(hmmc->hdmatx) != HAL_OK)
2267       {
2268         hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2269       }
2270     }
2271     /* Abort the MMC DMA Rx Stream */
2272     if(hmmc->hdmarx != NULL)
2273     {
2274       if(HAL_DMA_Abort(hmmc->hdmarx) != HAL_OK)
2275       {
2276         hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2277       }
2278     }
2279   }
2280 
2281   hmmc->State = HAL_MMC_STATE_READY;
2282 
2283   /* Initialize the MMC operation */
2284   hmmc->Context = MMC_CONTEXT_NONE;
2285 
2286   CardState = HAL_MMC_GetCardState(hmmc);
2287   if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2288   {
2289     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2290   }
2291   if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2292   {
2293     return HAL_ERROR;
2294   }
2295   return HAL_OK;
2296 }
2297 
2298 /**
2299   * @brief  Abort the current transfer and disable the MMC (IT mode).
2300   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2301   *                the configuration information for MMC module.
2302   * @retval HAL status
2303   */
HAL_MMC_Abort_IT(MMC_HandleTypeDef * hmmc)2304 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
2305 {
2306   HAL_MMC_CardStateTypeDef CardState;
2307 
2308   /* DIsable All interrupts */
2309   __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
2310                            SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
2311 
2312   /* Clear All flags */
2313   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2314 
2315   if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2316   {
2317     /* Disable the MMC DMA request */
2318     hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
2319 
2320     /* Abort the MMC DMA Tx Stream */
2321     if(hmmc->hdmatx != NULL)
2322     {
2323       hmmc->hdmatx->XferAbortCallback =  MMC_DMATxAbort;
2324       if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
2325       {
2326         hmmc->hdmatx = NULL;
2327       }
2328     }
2329     /* Abort the MMC DMA Rx Stream */
2330     if(hmmc->hdmarx != NULL)
2331     {
2332       hmmc->hdmarx->XferAbortCallback =  MMC_DMARxAbort;
2333       if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
2334       {
2335         hmmc->hdmarx = NULL;
2336       }
2337     }
2338   }
2339 
2340   /* No transfer ongoing on both DMA channels*/
2341   if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
2342   {
2343     CardState = HAL_MMC_GetCardState(hmmc);
2344     hmmc->State = HAL_MMC_STATE_READY;
2345 
2346     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2347     {
2348       hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2349     }
2350     if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2351     {
2352       return HAL_ERROR;
2353     }
2354     else
2355     {
2356 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2357       hmmc->AbortCpltCallback(hmmc);
2358 #else
2359       HAL_MMC_AbortCallback(hmmc);
2360 #endif
2361     }
2362   }
2363 
2364   return HAL_OK;
2365 }
2366 
2367 /**
2368   * @}
2369   */
2370 
2371 /**
2372   * @}
2373   */
2374 
2375 /* Private function ----------------------------------------------------------*/
2376 /** @addtogroup MMC_Private_Functions
2377   * @{
2378   */
2379 
2380 /**
2381   * @brief  DMA MMC transmit process complete callback
2382   * @param  hdma: DMA handle
2383   * @retval None
2384   */
MMC_DMATransmitCplt(DMA_HandleTypeDef * hdma)2385 static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)
2386 {
2387   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2388 
2389   /* Enable DATAEND Interrupt */
2390   __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DATAEND));
2391 }
2392 
2393 /**
2394   * @brief  DMA MMC receive process complete callback
2395   * @param  hdma: DMA handle
2396   * @retval None
2397   */
MMC_DMAReceiveCplt(DMA_HandleTypeDef * hdma)2398 static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
2399 {
2400   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2401   uint32_t errorstate;
2402 
2403   /* Send stop command in multiblock write */
2404   if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
2405   {
2406     errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
2407     if(errorstate != HAL_MMC_ERROR_NONE)
2408     {
2409       hmmc->ErrorCode |= errorstate;
2410 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2411       hmmc->ErrorCallback(hmmc);
2412 #else
2413       HAL_MMC_ErrorCallback(hmmc);
2414 #endif
2415     }
2416   }
2417 
2418   /* Disable the DMA transfer for transmit request by setting the DMAEN bit
2419   in the MMC DCTRL register */
2420   hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
2421 
2422   /* Clear all the static flags */
2423   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2424 
2425   hmmc->State = HAL_MMC_STATE_READY;
2426 
2427 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2428   hmmc->RxCpltCallback(hmmc);
2429 #else
2430   HAL_MMC_RxCpltCallback(hmmc);
2431 #endif
2432 }
2433 
2434 /**
2435   * @brief  DMA MMC communication error callback
2436   * @param  hdma: DMA handle
2437   * @retval None
2438   */
MMC_DMAError(DMA_HandleTypeDef * hdma)2439 static void MMC_DMAError(DMA_HandleTypeDef *hdma)
2440 {
2441   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2442   HAL_MMC_CardStateTypeDef CardState;
2443   uint32_t RxErrorCode, TxErrorCode;
2444 
2445   /* if DMA error is FIFO error ignore it */
2446   if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
2447   {
2448     RxErrorCode = hmmc->hdmarx->ErrorCode;
2449     TxErrorCode = hmmc->hdmatx->ErrorCode;
2450     if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
2451     {
2452       /* Clear All flags */
2453       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2454 
2455       /* Disable All interrupts */
2456       __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
2457         SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
2458 
2459       hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2460       CardState = HAL_MMC_GetCardState(hmmc);
2461       if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2462       {
2463         hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2464       }
2465 
2466       hmmc->State= HAL_MMC_STATE_READY;
2467     }
2468 
2469 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2470     hmmc->ErrorCallback(hmmc);
2471 #else
2472     HAL_MMC_ErrorCallback(hmmc);
2473 #endif
2474   }
2475 }
2476 
2477 /**
2478   * @brief  DMA MMC Tx Abort callback
2479   * @param  hdma: DMA handle
2480   * @retval None
2481   */
MMC_DMATxAbort(DMA_HandleTypeDef * hdma)2482 static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)
2483 {
2484   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2485   HAL_MMC_CardStateTypeDef CardState;
2486 
2487   if(hmmc->hdmatx != NULL)
2488   {
2489     hmmc->hdmatx = NULL;
2490   }
2491 
2492   /* All DMA channels are aborted */
2493   if(hmmc->hdmarx == NULL)
2494   {
2495     CardState = HAL_MMC_GetCardState(hmmc);
2496     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2497     hmmc->State = HAL_MMC_STATE_READY;
2498     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2499     {
2500       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2501 
2502       if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2503       {
2504 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2505         hmmc->AbortCpltCallback(hmmc);
2506 #else
2507         HAL_MMC_AbortCallback(hmmc);
2508 #endif
2509       }
2510       else
2511       {
2512 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2513         hmmc->ErrorCallback(hmmc);
2514 #else
2515         HAL_MMC_ErrorCallback(hmmc);
2516 #endif
2517       }
2518     }
2519   }
2520 }
2521 
2522 /**
2523   * @brief  DMA MMC Rx Abort callback
2524   * @param  hdma: DMA handle
2525   * @retval None
2526   */
MMC_DMARxAbort(DMA_HandleTypeDef * hdma)2527 static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)
2528 {
2529   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2530   HAL_MMC_CardStateTypeDef CardState;
2531 
2532   if(hmmc->hdmarx != NULL)
2533   {
2534     hmmc->hdmarx = NULL;
2535   }
2536 
2537   /* All DMA channels are aborted */
2538   if(hmmc->hdmatx == NULL)
2539   {
2540     CardState = HAL_MMC_GetCardState(hmmc);
2541     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2542     hmmc->State = HAL_MMC_STATE_READY;
2543     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2544     {
2545       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2546 
2547       if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2548       {
2549 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2550         hmmc->AbortCpltCallback(hmmc);
2551 #else
2552         HAL_MMC_AbortCallback(hmmc);
2553 #endif
2554       }
2555       else
2556       {
2557 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2558         hmmc->ErrorCallback(hmmc);
2559 #else
2560         HAL_MMC_ErrorCallback(hmmc);
2561 #endif
2562       }
2563     }
2564   }
2565 }
2566 
2567 /**
2568   * @brief  Initializes the mmc card.
2569   * @param  hmmc: Pointer to MMC handle
2570   * @retval MMC Card error state
2571   */
MMC_InitCard(MMC_HandleTypeDef * hmmc)2572 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
2573 {
2574   HAL_MMC_CardCSDTypeDef CSD;
2575   uint32_t errorstate;
2576   uint16_t mmc_rca = 1U;
2577 
2578   /* Check the power State */
2579   if(SDIO_GetPowerState(hmmc->Instance) == 0U)
2580   {
2581     /* Power off */
2582     return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2583   }
2584 
2585   /* Send CMD2 ALL_SEND_CID */
2586   errorstate = SDMMC_CmdSendCID(hmmc->Instance);
2587   if(errorstate != HAL_MMC_ERROR_NONE)
2588   {
2589     return errorstate;
2590   }
2591   else
2592   {
2593     /* Get Card identification number data */
2594     hmmc->CID[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2595     hmmc->CID[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
2596     hmmc->CID[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
2597     hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
2598   }
2599 
2600   /* Send CMD3 SET_REL_ADDR with argument 0 */
2601   /* MMC Card publishes its RCA. */
2602   errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
2603   if(errorstate != HAL_MMC_ERROR_NONE)
2604   {
2605     return errorstate;
2606   }
2607 
2608   /* Get the MMC card RCA */
2609   hmmc->MmcCard.RelCardAdd = mmc_rca;
2610 
2611   /* Send CMD9 SEND_CSD with argument as card's RCA */
2612   errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2613   if(errorstate != HAL_MMC_ERROR_NONE)
2614   {
2615     return errorstate;
2616   }
2617   else
2618   {
2619     /* Get Card Specific Data */
2620     hmmc->CSD[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2621     hmmc->CSD[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
2622     hmmc->CSD[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
2623     hmmc->CSD[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
2624   }
2625 
2626   /* Get the Card Class */
2627   hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U);
2628 
2629   /* Get CSD parameters */
2630   if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
2631   {
2632     return hmmc->ErrorCode;
2633   }
2634 
2635   /* Select the Card */
2636   errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2637   if(errorstate != HAL_MMC_ERROR_NONE)
2638   {
2639     return errorstate;
2640   }
2641 
2642   /* Configure SDIO peripheral interface */
2643   (void)SDIO_Init(hmmc->Instance, hmmc->Init);
2644 
2645   /* All cards are initialized */
2646   return HAL_MMC_ERROR_NONE;
2647 }
2648 
2649 /**
2650   * @brief  Enquires cards about their operating voltage and configures clock
2651   *         controls and stores MMC information that will be needed in future
2652   *         in the MMC handle.
2653   * @param  hmmc: Pointer to MMC handle
2654   * @retval error state
2655   */
MMC_PowerON(MMC_HandleTypeDef * hmmc)2656 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
2657 {
2658   __IO uint32_t count = 0U;
2659   uint32_t response = 0U, validvoltage = 0U;
2660   uint32_t errorstate;
2661 
2662   /* CMD0: GO_IDLE_STATE */
2663   errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
2664   if(errorstate != HAL_MMC_ERROR_NONE)
2665   {
2666     return errorstate;
2667   }
2668 
2669   while(validvoltage == 0U)
2670   {
2671     if(count++ == SDMMC_MAX_VOLT_TRIAL)
2672     {
2673       return HAL_MMC_ERROR_INVALID_VOLTRANGE;
2674     }
2675 
2676     /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
2677     errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
2678     if(errorstate != HAL_MMC_ERROR_NONE)
2679     {
2680       return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2681     }
2682 
2683     /* Get command response */
2684     response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2685 
2686     /* Get operating voltage*/
2687     validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
2688   }
2689 
2690   /* When power routine is finished and command returns valid voltage */
2691   if (((response & (0xFF000000U)) >> 24U) == 0xC0U)
2692   {
2693     hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
2694   }
2695   else
2696   {
2697     hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
2698   }
2699 
2700   return HAL_MMC_ERROR_NONE;
2701 }
2702 
2703 /**
2704   * @brief  Turns the SDIO output signals off.
2705   * @param  hmmc: Pointer to MMC handle
2706   * @retval None
2707   */
MMC_PowerOFF(MMC_HandleTypeDef * hmmc)2708 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
2709 {
2710   /* Set Power State to OFF */
2711   (void)SDIO_PowerState_OFF(hmmc->Instance);
2712 }
2713 
2714 /**
2715   * @brief  Returns the current card's status.
2716   * @param  hmmc: Pointer to MMC handle
2717   * @param  pCardStatus: pointer to the buffer that will contain the MMC card
2718   *         status (Card Status register)
2719   * @retval error state
2720   */
MMC_SendStatus(MMC_HandleTypeDef * hmmc,uint32_t * pCardStatus)2721 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
2722 {
2723   uint32_t errorstate;
2724 
2725   if(pCardStatus == NULL)
2726   {
2727     return HAL_MMC_ERROR_PARAM;
2728   }
2729 
2730   /* Send Status command */
2731   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2732   if(errorstate != HAL_MMC_ERROR_NONE)
2733   {
2734     return errorstate;
2735   }
2736 
2737   /* Get MMC card status */
2738   *pCardStatus = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2739 
2740   return HAL_MMC_ERROR_NONE;
2741 }
2742 
2743 /**
2744   * @brief  Reads extended CSD register to get the sectors number of the device
2745   * @param  hmmc: Pointer to MMC handle
2746   * @param  pFieldData: Pointer to the read buffer
2747   * @param  FieldIndex: Index of the field to be read
2748   * @param  Timeout: Specify timeout value
2749   * @retval HAL status
2750   */
MMC_ReadExtCSD(MMC_HandleTypeDef * hmmc,uint32_t * pFieldData,uint16_t FieldIndex,uint32_t Timeout)2751 static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout)
2752 {
2753   SDIO_DataInitTypeDef config;
2754   uint32_t errorstate;
2755   uint32_t tickstart = HAL_GetTick();
2756   uint32_t count;
2757   uint32_t i = 0;
2758   uint32_t tmp_data;
2759 
2760   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2761 
2762   /* Initialize data control register */
2763   hmmc->Instance->DCTRL = 0;
2764 
2765   /* Configure the MMC DPSM (Data Path State Machine) */
2766   config.DataTimeOut   = SDMMC_DATATIMEOUT;
2767   config.DataLength    = 512;
2768   config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
2769   config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
2770   config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
2771   config.DPSM          = SDIO_DPSM_ENABLE;
2772   (void)SDIO_ConfigData(hmmc->Instance, &config);
2773 
2774   /* Set Block Size for Card */
2775   errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
2776   if(errorstate != HAL_MMC_ERROR_NONE)
2777   {
2778     /* Clear all the static flags */
2779     __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2780     hmmc->ErrorCode |= errorstate;
2781     hmmc->State = HAL_MMC_STATE_READY;
2782     return HAL_ERROR;
2783   }
2784 
2785   /* Poll on SDMMC flags */
2786   while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
2787   {
2788     if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
2789     {
2790       /* Read data from SDMMC Rx FIFO */
2791       for(count = 0U; count < 8U; count++)
2792       {
2793         tmp_data = SDIO_ReadFIFO(hmmc->Instance);
2794         /* eg : SEC_COUNT   : FieldIndex = 212 => i+count = 53 */
2795         /*      DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
2796         if ((i + count) == ((uint32_t)FieldIndex/4U))
2797         {
2798           *pFieldData = tmp_data;
2799         }
2800       }
2801       i += 8U;
2802     }
2803 
2804     if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
2805     {
2806       /* Clear all the static flags */
2807       __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2808       hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
2809       hmmc->State= HAL_MMC_STATE_READY;
2810       return HAL_TIMEOUT;
2811     }
2812   }
2813 
2814   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2815   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
2816   if(errorstate != HAL_MMC_ERROR_NONE)
2817   {
2818     hmmc->ErrorCode |= errorstate;
2819   }
2820 
2821   /* Clear all the static flags */
2822   __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2823 
2824   hmmc->State = HAL_MMC_STATE_READY;
2825 
2826   return HAL_OK;
2827 }
2828 
2829 
2830 /**
2831   * @brief  Wrap up reading in non-blocking mode.
2832   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2833   *              the configuration information.
2834   * @retval None
2835   */
MMC_Read_IT(MMC_HandleTypeDef * hmmc)2836 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
2837 {
2838   uint32_t count, data, dataremaining;
2839   uint8_t* tmp;
2840 
2841   tmp = hmmc->pRxBuffPtr;
2842   dataremaining = hmmc->RxXferSize;
2843 
2844   if (dataremaining > 0U)
2845   {
2846     /* Read data from SDIO Rx FIFO */
2847     for(count = 0U; count < 8U; count++)
2848     {
2849       data = SDIO_ReadFIFO(hmmc->Instance);
2850       *tmp = (uint8_t)(data & 0xFFU);
2851       tmp++;
2852       dataremaining--;
2853       *tmp = (uint8_t)((data >> 8U) & 0xFFU);
2854       tmp++;
2855       dataremaining--;
2856       *tmp = (uint8_t)((data >> 16U) & 0xFFU);
2857       tmp++;
2858       dataremaining--;
2859       *tmp = (uint8_t)((data >> 24U) & 0xFFU);
2860       tmp++;
2861       dataremaining--;
2862     }
2863 
2864     hmmc->pRxBuffPtr = tmp;
2865     hmmc->RxXferSize = dataremaining;
2866   }
2867 }
2868 
2869 /**
2870   * @brief  Wrap up writing in non-blocking mode.
2871   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2872   *              the configuration information.
2873   * @retval None
2874   */
MMC_Write_IT(MMC_HandleTypeDef * hmmc)2875 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
2876 {
2877   uint32_t count, data, dataremaining;
2878   uint8_t* tmp;
2879 
2880   tmp = hmmc->pTxBuffPtr;
2881   dataremaining = hmmc->TxXferSize;
2882 
2883   if (dataremaining > 0U)
2884   {
2885     /* Write data to SDIO Tx FIFO */
2886     for(count = 0U; count < 8U; count++)
2887     {
2888       data = (uint32_t)(*tmp);
2889       tmp++;
2890       dataremaining--;
2891       data |= ((uint32_t)(*tmp) << 8U);
2892       tmp++;
2893       dataremaining--;
2894       data |= ((uint32_t)(*tmp) << 16U);
2895       tmp++;
2896       dataremaining--;
2897       data |= ((uint32_t)(*tmp) << 24U);
2898       tmp++;
2899       dataremaining--;
2900       (void)SDIO_WriteFIFO(hmmc->Instance, &data);
2901     }
2902 
2903     hmmc->pTxBuffPtr = tmp;
2904     hmmc->TxXferSize = dataremaining;
2905   }
2906 }
2907 
2908 /**
2909   * @}
2910   */
2911 
2912 #endif /* SDIO */
2913 
2914 #endif /* HAL_MMC_MODULE_ENABLED */
2915 
2916 /**
2917   * @}
2918   */
2919 
2920 /**
2921   * @}
2922   */
2923 
2924 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2925