1 /**
2   ******************************************************************************
3   * @file    stm32f7xx_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) 2017 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 "stm32f7xx_hal.h"
256 
257 /** @addtogroup STM32F7xx_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(SDMMC1)
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_SDMMC_ALL_INSTANCE(hmmc->Instance));
338   assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge));
339   assert_param(IS_SDMMC_CLOCK_BYPASS(hmmc->Init.ClockBypass));
340   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
341   assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide));
342   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
343   assert_param(IS_SDMMC_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 SDMMC peripheral configuration for MMC card initialization */
403   Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
404   Init.ClockBypass         = SDMMC_CLOCK_BYPASS_DISABLE;
405   Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
406   Init.BusWide             = SDMMC_BUS_WIDE_1B;
407   Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
408   Init.ClockDiv            = SDMMC_INIT_CLK_DIV;
409 
410   /* Initialize SDMMC peripheral interface with default configuration */
411   status = SDMMC_Init(hmmc->Instance, Init);
412   if(status == HAL_ERROR)
413   {
414     return HAL_ERROR;
415   }
416 
417   /* Disable SDMMC Clock */
418   __HAL_MMC_DISABLE(hmmc);
419 
420   /* Set Power State to ON */
421   status = SDMMC_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, SDMMC_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_SDMMC_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   SDMMC_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 = SDMMC_DATABLOCK_SIZE_512B;
603     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
604     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
605     config.DPSM          = SDMMC_DPSM_ENABLE;
606     (void)SDMMC_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, SDMMC_STATIC_FLAGS);
627       hmmc->ErrorCode |= errorstate;
628       hmmc->State = HAL_MMC_STATE_READY;
629       return HAL_ERROR;
630     }
631 
632     /* Poll on SDMMC flags */
633     dataremaining = config.DataLength;
634     while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
635     {
636       if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) && (dataremaining > 0U))
637       {
638         /* Read data from SDMMC Rx FIFO */
639         for(count = 0U; count < 8U; count++)
640         {
641           data = SDMMC_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, SDMMC_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, SDMMC_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, SDMMC_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, SDMMC_FLAG_DTIMEOUT))
684     {
685       /* Clear all the static flags */
686       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_FLAG_DCRCFAIL))
692     {
693       /* Clear all the static flags */
694       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_FLAG_RXOVERR))
700     {
701       /* Clear all the static flags */
702       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_FLAG_RXDAVL)) && (dataremaining > 0U))
714     {
715       data = SDMMC_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, SDMMC_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, SDMMC_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   SDMMC_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, SDMMC_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 = SDMMC_DATABLOCK_SIZE_512B;
828     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
829     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
830     config.DPSM          = SDMMC_DPSM_ENABLE;
831     (void)SDMMC_ConfigData(hmmc->Instance, &config);
832 
833     /* Write block(s) in polling mode */
834     dataremaining = config.DataLength;
835     while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
836     {
837       if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) && (dataremaining > 0U))
838       {
839         /* Write data to SDMMC 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)SDMMC_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, SDMMC_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, SDMMC_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, SDMMC_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, SDMMC_FLAG_DTIMEOUT))
885     {
886       /* Clear all the static flags */
887       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_FLAG_DCRCFAIL))
893     {
894       /* Clear all the static flags */
895       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_FLAG_TXUNDERR))
901     {
902       /* Clear all the static flags */
903       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_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   SDMMC_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, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_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 = SDMMC_DATABLOCK_SIZE_512B;
981     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
982     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
983     config.DPSM          = SDMMC_DPSM_ENABLE;
984     (void)SDMMC_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, SDMMC_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   SDMMC_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, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_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, SDMMC_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 = SDMMC_DATABLOCK_SIZE_512B;
1098     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
1099     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1100     config.DPSM          = SDMMC_DPSM_ENABLE;
1101     (void)SDMMC_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   SDMMC_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, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_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, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
1175       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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 = SDMMC_DATABLOCK_SIZE_512B;
1189       config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
1190       config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1191       config.DPSM          = SDMMC_DPSM_ENABLE;
1192       (void)SDMMC_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, SDMMC_STATIC_FLAGS);
1213         __HAL_MMC_DISABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_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   SDMMC_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, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_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, SDMMC_STATIC_FLAGS);
1305       __HAL_MMC_DISABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
1306       hmmc->ErrorCode |= errorstate;
1307       hmmc->State = HAL_MMC_STATE_READY;
1308       return HAL_ERROR;
1309     }
1310 
1311     /* Enable SDMMC 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, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
1322       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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 = SDMMC_DATABLOCK_SIZE_512B;
1333       config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
1334       config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1335       config.DPSM          = SDMMC_DPSM_ENABLE;
1336       (void)SDMMC_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) & SDMMC_CCCC_ERASE) == 0U)
1382     {
1383       /* Clear all the static flags */
1384       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
1391     {
1392       /* Clear all the static flags */
1393       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_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, SDMMC_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, SDMMC_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, SDMMC_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 SDMMC interrupt flags */
1459   if((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1460   {
1461     MMC_Read_IT(hmmc);
1462   }
1463 
1464   else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) != RESET)
1465   {
1466     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND);
1467 
1468     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND  | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT |\
1469                                SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR  | SDMMC_IT_TXFIFOHE |\
1470                                SDMMC_IT_RXFIFOHF);
1471 
1472     hmmc->Instance->DCTRL &= ~(SDMMC_DCTRL_DTEN);
1473 
1474     if((context & MMC_CONTEXT_DMA) != 0U)
1475     {
1476       if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
1477       {
1478         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1479         if(errorstate != HAL_MMC_ERROR_NONE)
1480         {
1481           hmmc->ErrorCode |= errorstate;
1482 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1483           hmmc->ErrorCallback(hmmc);
1484 #else
1485           HAL_MMC_ErrorCallback(hmmc);
1486 #endif
1487         }
1488       }
1489       if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
1490       {
1491         /* Disable the DMA transfer for transmit request by setting the DMAEN bit
1492         in the MMC DCTRL register */
1493         hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
1494 
1495         hmmc->State = HAL_MMC_STATE_READY;
1496 
1497 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1498         hmmc->TxCpltCallback(hmmc);
1499 #else
1500         HAL_MMC_TxCpltCallback(hmmc);
1501 #endif
1502       }
1503     }
1504     else if((context & MMC_CONTEXT_IT) != 0U)
1505     {
1506       /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1507       if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1508       {
1509         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1510         if(errorstate != HAL_MMC_ERROR_NONE)
1511         {
1512           hmmc->ErrorCode |= errorstate;
1513 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1514           hmmc->ErrorCallback(hmmc);
1515 #else
1516           HAL_MMC_ErrorCallback(hmmc);
1517 #endif
1518         }
1519       }
1520 
1521       /* Clear all the static flags */
1522       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1523 
1524       hmmc->State = HAL_MMC_STATE_READY;
1525       if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1526       {
1527 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1528         hmmc->RxCpltCallback(hmmc);
1529 #else
1530         HAL_MMC_RxCpltCallback(hmmc);
1531 #endif
1532       }
1533       else
1534       {
1535 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1536         hmmc->TxCpltCallback(hmmc);
1537 #else
1538         HAL_MMC_TxCpltCallback(hmmc);
1539 #endif
1540       }
1541     }
1542     else
1543     {
1544       /* Nothing to do */
1545     }
1546   }
1547 
1548   else if((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1549   {
1550     MMC_Write_IT(hmmc);
1551   }
1552 
1553   else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
1554   {
1555     /* Set Error code */
1556     if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL) != RESET)
1557     {
1558       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
1559     }
1560     if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT) != RESET)
1561     {
1562       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
1563     }
1564     if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR) != RESET)
1565     {
1566       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
1567     }
1568     if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR) != RESET)
1569     {
1570       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
1571     }
1572 
1573     /* Clear All flags */
1574     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1575 
1576     /* Disable all interrupts */
1577     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
1578                              SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
1579 
1580     hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
1581 
1582     if((context & MMC_CONTEXT_IT) != 0U)
1583     {
1584       /* Set the MMC state to ready to be able to start again the process */
1585       hmmc->State = HAL_MMC_STATE_READY;
1586 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1587       hmmc->ErrorCallback(hmmc);
1588 #else
1589       HAL_MMC_ErrorCallback(hmmc);
1590 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1591     }
1592     else if((context & MMC_CONTEXT_DMA) != 0U)
1593     {
1594       /* Abort the MMC DMA Streams */
1595       if(hmmc->hdmatx != NULL)
1596       {
1597         /* Set the DMA Tx abort callback */
1598         hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
1599         /* Abort DMA in IT mode */
1600         if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
1601         {
1602           MMC_DMATxAbort(hmmc->hdmatx);
1603         }
1604       }
1605       else if(hmmc->hdmarx != NULL)
1606       {
1607         /* Set the DMA Rx abort callback */
1608         hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
1609         /* Abort DMA in IT mode */
1610         if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
1611         {
1612           MMC_DMARxAbort(hmmc->hdmarx);
1613         }
1614       }
1615       else
1616       {
1617         hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1618         hmmc->State = HAL_MMC_STATE_READY;
1619 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1620         hmmc->AbortCpltCallback(hmmc);
1621 #else
1622         HAL_MMC_AbortCallback(hmmc);
1623 #endif
1624       }
1625     }
1626     else
1627     {
1628       /* Nothing to do */
1629     }
1630   }
1631 
1632   else
1633   {
1634     /* Nothing to do */
1635   }
1636 }
1637 
1638 /**
1639   * @brief return the MMC state
1640   * @param hmmc: Pointer to mmc handle
1641   * @retval HAL state
1642   */
HAL_MMC_GetState(MMC_HandleTypeDef * hmmc)1643 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
1644 {
1645   return hmmc->State;
1646 }
1647 
1648 /**
1649 * @brief  Return the MMC error code
1650 * @param  hmmc : Pointer to a MMC_HandleTypeDef structure that contains
1651   *              the configuration information.
1652 * @retval MMC Error Code
1653 */
HAL_MMC_GetError(MMC_HandleTypeDef * hmmc)1654 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
1655 {
1656   return hmmc->ErrorCode;
1657 }
1658 
1659 /**
1660   * @brief Tx Transfer completed callbacks
1661   * @param hmmc: Pointer to MMC handle
1662   * @retval None
1663   */
HAL_MMC_TxCpltCallback(MMC_HandleTypeDef * hmmc)1664 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
1665 {
1666   /* Prevent unused argument(s) compilation warning */
1667   UNUSED(hmmc);
1668 
1669   /* NOTE : This function should not be modified, when the callback is needed,
1670             the HAL_MMC_TxCpltCallback can be implemented in the user file
1671    */
1672 }
1673 
1674 /**
1675   * @brief Rx Transfer completed callbacks
1676   * @param hmmc: Pointer MMC handle
1677   * @retval None
1678   */
HAL_MMC_RxCpltCallback(MMC_HandleTypeDef * hmmc)1679 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
1680 {
1681   /* Prevent unused argument(s) compilation warning */
1682   UNUSED(hmmc);
1683 
1684   /* NOTE : This function should not be modified, when the callback is needed,
1685             the HAL_MMC_RxCpltCallback can be implemented in the user file
1686    */
1687 }
1688 
1689 /**
1690   * @brief MMC error callbacks
1691   * @param hmmc: Pointer MMC handle
1692   * @retval None
1693   */
HAL_MMC_ErrorCallback(MMC_HandleTypeDef * hmmc)1694 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
1695 {
1696   /* Prevent unused argument(s) compilation warning */
1697   UNUSED(hmmc);
1698 
1699   /* NOTE : This function should not be modified, when the callback is needed,
1700             the HAL_MMC_ErrorCallback can be implemented in the user file
1701    */
1702 }
1703 
1704 /**
1705   * @brief MMC Abort callbacks
1706   * @param hmmc: Pointer MMC handle
1707   * @retval None
1708   */
HAL_MMC_AbortCallback(MMC_HandleTypeDef * hmmc)1709 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
1710 {
1711   /* Prevent unused argument(s) compilation warning */
1712   UNUSED(hmmc);
1713 
1714   /* NOTE : This function should not be modified, when the callback is needed,
1715             the HAL_MMC_AbortCallback can be implemented in the user file
1716    */
1717 }
1718 
1719 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1720 /**
1721   * @brief  Register a User MMC Callback
1722   *         To be used instead of the weak (surcharged) predefined callback
1723   * @param hmmc : MMC handle
1724   * @param CallbackId : ID of the callback to be registered
1725   *        This parameter can be one of the following values:
1726   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID    MMC Tx Complete Callback ID
1727   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID    MMC Rx Complete Callback ID
1728   *          @arg @ref HAL_MMC_ERROR_CB_ID      MMC Error Callback ID
1729   *          @arg @ref HAL_MMC_ABORT_CB_ID      MMC Abort Callback ID
1730   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID   MMC MspInit Callback ID
1731   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1732   * @param pCallback : pointer to the Callback function
1733   * @retval status
1734   */
HAL_MMC_RegisterCallback(MMC_HandleTypeDef * hmmc,HAL_MMC_CallbackIDTypeDef CallbackId,pMMC_CallbackTypeDef pCallback)1735 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
1736 {
1737   HAL_StatusTypeDef status = HAL_OK;
1738 
1739   if(pCallback == NULL)
1740   {
1741     /* Update the error code */
1742     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1743     return HAL_ERROR;
1744   }
1745 
1746   /* Process locked */
1747   __HAL_LOCK(hmmc);
1748 
1749   if(hmmc->State == HAL_MMC_STATE_READY)
1750   {
1751     switch (CallbackId)
1752     {
1753     case HAL_MMC_TX_CPLT_CB_ID :
1754       hmmc->TxCpltCallback = pCallback;
1755       break;
1756     case HAL_MMC_RX_CPLT_CB_ID :
1757       hmmc->RxCpltCallback = pCallback;
1758       break;
1759     case HAL_MMC_ERROR_CB_ID :
1760       hmmc->ErrorCallback = pCallback;
1761       break;
1762     case HAL_MMC_ABORT_CB_ID :
1763       hmmc->AbortCpltCallback = pCallback;
1764       break;
1765     case HAL_MMC_MSP_INIT_CB_ID :
1766       hmmc->MspInitCallback = pCallback;
1767       break;
1768     case HAL_MMC_MSP_DEINIT_CB_ID :
1769       hmmc->MspDeInitCallback = pCallback;
1770       break;
1771     default :
1772       /* Update the error code */
1773       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1774       /* update return status */
1775       status =  HAL_ERROR;
1776       break;
1777     }
1778   }
1779   else if (hmmc->State == HAL_MMC_STATE_RESET)
1780   {
1781     switch (CallbackId)
1782     {
1783     case HAL_MMC_MSP_INIT_CB_ID :
1784       hmmc->MspInitCallback = pCallback;
1785       break;
1786     case HAL_MMC_MSP_DEINIT_CB_ID :
1787       hmmc->MspDeInitCallback = pCallback;
1788       break;
1789     default :
1790       /* Update the error code */
1791       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1792       /* update return status */
1793       status =  HAL_ERROR;
1794       break;
1795     }
1796   }
1797   else
1798   {
1799     /* Update the error code */
1800     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1801     /* update return status */
1802     status =  HAL_ERROR;
1803   }
1804 
1805   /* Release Lock */
1806   __HAL_UNLOCK(hmmc);
1807   return status;
1808 }
1809 
1810 /**
1811   * @brief  Unregister a User MMC Callback
1812   *         MMC Callback is redirected to the weak (surcharged) predefined callback
1813   * @param hmmc : MMC handle
1814   * @param CallbackId : ID of the callback to be unregistered
1815   *        This parameter can be one of the following values:
1816   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID    MMC Tx Complete Callback ID
1817   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID    MMC Rx Complete Callback ID
1818   *          @arg @ref HAL_MMC_ERROR_CB_ID      MMC Error Callback ID
1819   *          @arg @ref HAL_MMC_ABORT_CB_ID      MMC Abort Callback ID
1820   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID   MMC MspInit Callback ID
1821   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1822   * @retval status
1823   */
HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef * hmmc,HAL_MMC_CallbackIDTypeDef CallbackId)1824 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
1825 {
1826   HAL_StatusTypeDef status = HAL_OK;
1827 
1828   /* Process locked */
1829   __HAL_LOCK(hmmc);
1830 
1831   if(hmmc->State == HAL_MMC_STATE_READY)
1832   {
1833     switch (CallbackId)
1834     {
1835     case HAL_MMC_TX_CPLT_CB_ID :
1836       hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
1837       break;
1838     case HAL_MMC_RX_CPLT_CB_ID :
1839       hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
1840       break;
1841     case HAL_MMC_ERROR_CB_ID :
1842       hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
1843       break;
1844     case HAL_MMC_ABORT_CB_ID :
1845       hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
1846       break;
1847     case HAL_MMC_MSP_INIT_CB_ID :
1848       hmmc->MspInitCallback = HAL_MMC_MspInit;
1849       break;
1850     case HAL_MMC_MSP_DEINIT_CB_ID :
1851       hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1852       break;
1853     default :
1854       /* Update the error code */
1855       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1856       /* update return status */
1857       status =  HAL_ERROR;
1858       break;
1859     }
1860   }
1861   else if (hmmc->State == HAL_MMC_STATE_RESET)
1862   {
1863     switch (CallbackId)
1864     {
1865     case HAL_MMC_MSP_INIT_CB_ID :
1866       hmmc->MspInitCallback = HAL_MMC_MspInit;
1867       break;
1868     case HAL_MMC_MSP_DEINIT_CB_ID :
1869       hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1870       break;
1871     default :
1872       /* Update the error code */
1873       hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1874       /* update return status */
1875       status =  HAL_ERROR;
1876       break;
1877     }
1878   }
1879   else
1880   {
1881     /* Update the error code */
1882     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1883     /* update return status */
1884     status =  HAL_ERROR;
1885   }
1886 
1887   /* Release Lock */
1888   __HAL_UNLOCK(hmmc);
1889   return status;
1890 }
1891 #endif
1892 
1893 /**
1894   * @}
1895   */
1896 
1897 /** @addtogroup MMC_Exported_Functions_Group3
1898  *  @brief   management functions
1899  *
1900 @verbatim
1901   ==============================================================================
1902                       ##### Peripheral Control functions #####
1903   ==============================================================================
1904   [..]
1905     This subsection provides a set of functions allowing to control the MMC card
1906     operations and get the related information
1907 
1908 @endverbatim
1909   * @{
1910   */
1911 
1912 /**
1913   * @brief  Returns information the information of the card which are stored on
1914   *         the CID register.
1915   * @param  hmmc: Pointer to MMC handle
1916   * @param  pCID: Pointer to a HAL_MMC_CIDTypedef structure that
1917   *         contains all CID register parameters
1918   * @retval HAL status
1919   */
HAL_MMC_GetCardCID(MMC_HandleTypeDef * hmmc,HAL_MMC_CardCIDTypeDef * pCID)1920 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
1921 {
1922   pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
1923 
1924   pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
1925 
1926   pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
1927 
1928   pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
1929 
1930   pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
1931 
1932   pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
1933 
1934   pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
1935 
1936   pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
1937 
1938   pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
1939 
1940   pCID->Reserved2 = 1U;
1941 
1942   return HAL_OK;
1943 }
1944 
1945 /**
1946   * @brief  Returns information the information of the card which are stored on
1947   *         the CSD register.
1948   * @param  hmmc: Pointer to MMC handle
1949   * @param  pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
1950   *         contains all CSD register parameters
1951   * @retval HAL status
1952   */
HAL_MMC_GetCardCSD(MMC_HandleTypeDef * hmmc,HAL_MMC_CardCSDTypeDef * pCSD)1953 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
1954 {
1955   uint32_t block_nbr = 0;
1956 
1957   pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
1958 
1959   pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
1960 
1961   pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
1962 
1963   pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
1964 
1965   pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
1966 
1967   pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
1968 
1969   pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
1970 
1971   pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
1972 
1973   pCSD->PartBlockRead   = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
1974 
1975   pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
1976 
1977   pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
1978 
1979   pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
1980 
1981   pCSD->Reserved2 = 0U; /*!< Reserved */
1982 
1983   pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
1984 
1985   pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
1986 
1987   pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
1988 
1989   pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
1990 
1991   pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
1992 
1993   pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
1994 
1995   if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
1996   {
1997     return HAL_ERROR;
1998   }
1999 
2000   if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
2001   {
2002     hmmc->MmcCard.BlockNbr  = (pCSD->DeviceSize + 1U) ;
2003     hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
2004     hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
2005     hmmc->MmcCard.LogBlockNbr =  (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
2006     hmmc->MmcCard.LogBlockSize = 512U;
2007   }
2008   else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
2009   {
2010     hmmc->MmcCard.BlockNbr = block_nbr;
2011     hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
2012     hmmc->MmcCard.BlockSize = 512U;
2013     hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
2014   }
2015   else
2016   {
2017     /* Clear all the static flags */
2018     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2019     hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2020     hmmc->State = HAL_MMC_STATE_READY;
2021     return HAL_ERROR;
2022   }
2023 
2024   pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
2025 
2026   pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
2027 
2028   pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
2029 
2030   pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
2031 
2032   pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
2033 
2034   pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
2035 
2036   pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
2037 
2038   pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
2039 
2040   pCSD->Reserved3 = 0;
2041 
2042   pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
2043 
2044   pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
2045 
2046   pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
2047 
2048   pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
2049 
2050   pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
2051 
2052   pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
2053 
2054   pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
2055 
2056   pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
2057 
2058   pCSD->Reserved4 = 1;
2059 
2060   return HAL_OK;
2061 }
2062 
2063 /**
2064   * @brief  Gets the MMC card info.
2065   * @param  hmmc: Pointer to MMC handle
2066   * @param  pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
2067   *         will contain the MMC card status information
2068   * @retval HAL status
2069   */
HAL_MMC_GetCardInfo(MMC_HandleTypeDef * hmmc,HAL_MMC_CardInfoTypeDef * pCardInfo)2070 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
2071 {
2072   pCardInfo->CardType     = (uint32_t)(hmmc->MmcCard.CardType);
2073   pCardInfo->Class        = (uint32_t)(hmmc->MmcCard.Class);
2074   pCardInfo->RelCardAdd   = (uint32_t)(hmmc->MmcCard.RelCardAdd);
2075   pCardInfo->BlockNbr     = (uint32_t)(hmmc->MmcCard.BlockNbr);
2076   pCardInfo->BlockSize    = (uint32_t)(hmmc->MmcCard.BlockSize);
2077   pCardInfo->LogBlockNbr  = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
2078   pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
2079 
2080   return HAL_OK;
2081 }
2082 
2083 /**
2084   * @brief  Enables wide bus operation for the requested card if supported by
2085   *         card.
2086   * @param  hmmc: Pointer to MMC handle
2087   * @param  WideMode: Specifies the MMC card wide bus mode
2088   *          This parameter can be one of the following values:
2089   *            @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
2090   *            @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
2091   *            @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
2092   * @retval HAL status
2093   */
HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef * hmmc,uint32_t WideMode)2094 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
2095 {
2096   __IO uint32_t count = 0U;
2097   SDMMC_InitTypeDef Init;
2098   uint32_t errorstate;
2099   uint32_t response = 0U, busy = 0U;
2100 
2101   /* Check the parameters */
2102   assert_param(IS_SDMMC_BUS_WIDE(WideMode));
2103 
2104   /* Change State */
2105   hmmc->State = HAL_MMC_STATE_BUSY;
2106 
2107   /* Update Clock for Bus mode update */
2108   Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
2109   Init.ClockBypass         = SDMMC_CLOCK_BYPASS_DISABLE;
2110   Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
2111   Init.BusWide             = WideMode;
2112   Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
2113   Init.ClockDiv            = SDMMC_INIT_CLK_DIV;
2114   /* Initialize SDMMC*/
2115   (void)SDMMC_Init(hmmc->Instance, Init);
2116 
2117   if(WideMode == SDMMC_BUS_WIDE_8B)
2118   {
2119     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
2120     if(errorstate != HAL_MMC_ERROR_NONE)
2121     {
2122       hmmc->ErrorCode |= errorstate;
2123     }
2124   }
2125   else if(WideMode == SDMMC_BUS_WIDE_4B)
2126   {
2127     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
2128     if(errorstate != HAL_MMC_ERROR_NONE)
2129     {
2130       hmmc->ErrorCode |= errorstate;
2131     }
2132   }
2133   else if(WideMode == SDMMC_BUS_WIDE_1B)
2134   {
2135     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
2136     if(errorstate != HAL_MMC_ERROR_NONE)
2137     {
2138       hmmc->ErrorCode |= errorstate;
2139     }
2140   }
2141   else
2142   {
2143     /* WideMode is not a valid argument*/
2144     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2145   }
2146 
2147   /* Check for switch error and violation of the trial number of sending CMD 13 */
2148   while(busy == 0U)
2149   {
2150     if(count == SDMMC_MAX_TRIAL)
2151     {
2152       hmmc->State = HAL_MMC_STATE_READY;
2153       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2154       return HAL_ERROR;
2155     }
2156     count++;
2157 
2158     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2159     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2160     if(errorstate != HAL_MMC_ERROR_NONE)
2161     {
2162       hmmc->ErrorCode |= errorstate;
2163     }
2164 
2165     /* Get command response */
2166     response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2167 
2168     /* Get operating voltage*/
2169     busy = (((response >> 7U) == 1U) ? 0U : 1U);
2170   }
2171 
2172   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2173   count = SDMMC_DATATIMEOUT;
2174   while((response & 0x00000100U) == 0U)
2175   {
2176     if(count == 0U)
2177     {
2178       hmmc->State = HAL_MMC_STATE_READY;
2179       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2180       return HAL_ERROR;
2181     }
2182     count--;
2183 
2184     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2185     errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2186     if(errorstate != HAL_MMC_ERROR_NONE)
2187     {
2188       hmmc->ErrorCode |= errorstate;
2189     }
2190 
2191     /* Get command response */
2192     response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2193   }
2194 
2195   if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2196   {
2197     /* Clear all the static flags */
2198     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2199     hmmc->State = HAL_MMC_STATE_READY;
2200     return HAL_ERROR;
2201   }
2202   else
2203   {
2204     /* Configure the SDMMC peripheral */
2205     Init.ClockEdge           = hmmc->Init.ClockEdge;
2206     Init.ClockBypass         = hmmc->Init.ClockBypass;
2207     Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
2208     Init.BusWide             = WideMode;
2209     Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
2210     Init.ClockDiv            = hmmc->Init.ClockDiv;
2211     (void)SDMMC_Init(hmmc->Instance, Init);
2212   }
2213 
2214   /* Change State */
2215   hmmc->State = HAL_MMC_STATE_READY;
2216 
2217   return HAL_OK;
2218 }
2219 
2220 /**
2221   * @brief  Gets the current mmc card data state.
2222   * @param  hmmc: pointer to MMC handle
2223   * @retval Card state
2224   */
HAL_MMC_GetCardState(MMC_HandleTypeDef * hmmc)2225 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
2226 {
2227   uint32_t cardstate;
2228   uint32_t errorstate;
2229   uint32_t resp1 = 0U;
2230 
2231   errorstate = MMC_SendStatus(hmmc, &resp1);
2232   if(errorstate != HAL_MMC_ERROR_NONE)
2233   {
2234     hmmc->ErrorCode |= errorstate;
2235   }
2236 
2237   cardstate = ((resp1 >> 9U) & 0x0FU);
2238 
2239   return (HAL_MMC_CardStateTypeDef)cardstate;
2240 }
2241 
2242 /**
2243   * @brief  Abort the current transfer and disable the MMC.
2244   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2245   *                the configuration information for MMC module.
2246   * @retval HAL status
2247   */
HAL_MMC_Abort(MMC_HandleTypeDef * hmmc)2248 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
2249 {
2250   HAL_MMC_CardStateTypeDef CardState;
2251 
2252   /* DIsable All interrupts */
2253   __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2254                              SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2255 
2256   /* Clear All flags */
2257   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2258 
2259   if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2260   {
2261     /* Disable the MMC DMA request */
2262     hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
2263 
2264     /* Abort the MMC DMA Tx Stream */
2265     if(hmmc->hdmatx != NULL)
2266     {
2267       if(HAL_DMA_Abort(hmmc->hdmatx) != HAL_OK)
2268       {
2269         hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2270       }
2271     }
2272     /* Abort the MMC DMA Rx Stream */
2273     if(hmmc->hdmarx != NULL)
2274     {
2275       if(HAL_DMA_Abort(hmmc->hdmarx) != HAL_OK)
2276       {
2277         hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2278       }
2279     }
2280   }
2281 
2282   hmmc->State = HAL_MMC_STATE_READY;
2283 
2284   /* Initialize the MMC operation */
2285   hmmc->Context = MMC_CONTEXT_NONE;
2286 
2287   CardState = HAL_MMC_GetCardState(hmmc);
2288   if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2289   {
2290     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2291   }
2292   if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2293   {
2294     return HAL_ERROR;
2295   }
2296   return HAL_OK;
2297 }
2298 
2299 /**
2300   * @brief  Abort the current transfer and disable the MMC (IT mode).
2301   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2302   *                the configuration information for MMC module.
2303   * @retval HAL status
2304   */
HAL_MMC_Abort_IT(MMC_HandleTypeDef * hmmc)2305 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
2306 {
2307   HAL_MMC_CardStateTypeDef CardState;
2308 
2309   /* DIsable All interrupts */
2310   __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2311                            SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2312 
2313   /* Clear All flags */
2314   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2315 
2316   if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2317   {
2318     /* Disable the MMC DMA request */
2319     hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
2320 
2321     /* Abort the MMC DMA Tx Stream */
2322     if(hmmc->hdmatx != NULL)
2323     {
2324       hmmc->hdmatx->XferAbortCallback =  MMC_DMATxAbort;
2325       if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
2326       {
2327         hmmc->hdmatx = NULL;
2328       }
2329     }
2330     /* Abort the MMC DMA Rx Stream */
2331     if(hmmc->hdmarx != NULL)
2332     {
2333       hmmc->hdmarx->XferAbortCallback =  MMC_DMARxAbort;
2334       if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
2335       {
2336         hmmc->hdmarx = NULL;
2337       }
2338     }
2339   }
2340 
2341   /* No transfer ongoing on both DMA channels*/
2342   if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
2343   {
2344     CardState = HAL_MMC_GetCardState(hmmc);
2345     hmmc->State = HAL_MMC_STATE_READY;
2346 
2347     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2348     {
2349       hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2350     }
2351     if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2352     {
2353       return HAL_ERROR;
2354     }
2355     else
2356     {
2357 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2358       hmmc->AbortCpltCallback(hmmc);
2359 #else
2360       HAL_MMC_AbortCallback(hmmc);
2361 #endif
2362     }
2363   }
2364 
2365   return HAL_OK;
2366 }
2367 
2368 /**
2369   * @}
2370   */
2371 
2372 /**
2373   * @}
2374   */
2375 
2376 /* Private function ----------------------------------------------------------*/
2377 /** @addtogroup MMC_Private_Functions
2378   * @{
2379   */
2380 
2381 /**
2382   * @brief  DMA MMC transmit process complete callback
2383   * @param  hdma: DMA handle
2384   * @retval None
2385   */
MMC_DMATransmitCplt(DMA_HandleTypeDef * hdma)2386 static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)
2387 {
2388   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2389 
2390   /* Enable DATAEND Interrupt */
2391   __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DATAEND));
2392 }
2393 
2394 /**
2395   * @brief  DMA MMC receive process complete callback
2396   * @param  hdma: DMA handle
2397   * @retval None
2398   */
MMC_DMAReceiveCplt(DMA_HandleTypeDef * hdma)2399 static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
2400 {
2401   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2402   uint32_t errorstate;
2403 
2404   /* Send stop command in multiblock write */
2405   if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
2406   {
2407     errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
2408     if(errorstate != HAL_MMC_ERROR_NONE)
2409     {
2410       hmmc->ErrorCode |= errorstate;
2411 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2412       hmmc->ErrorCallback(hmmc);
2413 #else
2414       HAL_MMC_ErrorCallback(hmmc);
2415 #endif
2416     }
2417   }
2418 
2419   /* Disable the DMA transfer for transmit request by setting the DMAEN bit
2420   in the MMC DCTRL register */
2421   hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
2422 
2423   /* Clear all the static flags */
2424   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2425 
2426   hmmc->State = HAL_MMC_STATE_READY;
2427 
2428 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2429   hmmc->RxCpltCallback(hmmc);
2430 #else
2431   HAL_MMC_RxCpltCallback(hmmc);
2432 #endif
2433 }
2434 
2435 /**
2436   * @brief  DMA MMC communication error callback
2437   * @param  hdma: DMA handle
2438   * @retval None
2439   */
MMC_DMAError(DMA_HandleTypeDef * hdma)2440 static void MMC_DMAError(DMA_HandleTypeDef *hdma)
2441 {
2442   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2443   HAL_MMC_CardStateTypeDef CardState;
2444   uint32_t RxErrorCode, TxErrorCode;
2445 
2446   /* if DMA error is FIFO error ignore it */
2447   if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
2448   {
2449     RxErrorCode = hmmc->hdmarx->ErrorCode;
2450     TxErrorCode = hmmc->hdmatx->ErrorCode;
2451     if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
2452     {
2453       /* Clear All flags */
2454       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2455 
2456       /* Disable All interrupts */
2457       __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2458         SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2459 
2460       hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2461       CardState = HAL_MMC_GetCardState(hmmc);
2462       if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2463       {
2464         hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2465       }
2466 
2467       hmmc->State= HAL_MMC_STATE_READY;
2468     }
2469 
2470 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2471     hmmc->ErrorCallback(hmmc);
2472 #else
2473     HAL_MMC_ErrorCallback(hmmc);
2474 #endif
2475   }
2476 }
2477 
2478 /**
2479   * @brief  DMA MMC Tx Abort callback
2480   * @param  hdma: DMA handle
2481   * @retval None
2482   */
MMC_DMATxAbort(DMA_HandleTypeDef * hdma)2483 static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)
2484 {
2485   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2486   HAL_MMC_CardStateTypeDef CardState;
2487 
2488   if(hmmc->hdmatx != NULL)
2489   {
2490     hmmc->hdmatx = NULL;
2491   }
2492 
2493   /* All DMA channels are aborted */
2494   if(hmmc->hdmarx == NULL)
2495   {
2496     CardState = HAL_MMC_GetCardState(hmmc);
2497     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2498     hmmc->State = HAL_MMC_STATE_READY;
2499     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2500     {
2501       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2502 
2503       if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2504       {
2505 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2506         hmmc->AbortCpltCallback(hmmc);
2507 #else
2508         HAL_MMC_AbortCallback(hmmc);
2509 #endif
2510       }
2511       else
2512       {
2513 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2514         hmmc->ErrorCallback(hmmc);
2515 #else
2516         HAL_MMC_ErrorCallback(hmmc);
2517 #endif
2518       }
2519     }
2520   }
2521 }
2522 
2523 /**
2524   * @brief  DMA MMC Rx Abort callback
2525   * @param  hdma: DMA handle
2526   * @retval None
2527   */
MMC_DMARxAbort(DMA_HandleTypeDef * hdma)2528 static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)
2529 {
2530   MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2531   HAL_MMC_CardStateTypeDef CardState;
2532 
2533   if(hmmc->hdmarx != NULL)
2534   {
2535     hmmc->hdmarx = NULL;
2536   }
2537 
2538   /* All DMA channels are aborted */
2539   if(hmmc->hdmatx == NULL)
2540   {
2541     CardState = HAL_MMC_GetCardState(hmmc);
2542     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2543     hmmc->State = HAL_MMC_STATE_READY;
2544     if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2545     {
2546       hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2547 
2548       if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2549       {
2550 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2551         hmmc->AbortCpltCallback(hmmc);
2552 #else
2553         HAL_MMC_AbortCallback(hmmc);
2554 #endif
2555       }
2556       else
2557       {
2558 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2559         hmmc->ErrorCallback(hmmc);
2560 #else
2561         HAL_MMC_ErrorCallback(hmmc);
2562 #endif
2563       }
2564     }
2565   }
2566 }
2567 
2568 /**
2569   * @brief  Initializes the mmc card.
2570   * @param  hmmc: Pointer to MMC handle
2571   * @retval MMC Card error state
2572   */
MMC_InitCard(MMC_HandleTypeDef * hmmc)2573 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
2574 {
2575   HAL_MMC_CardCSDTypeDef CSD;
2576   uint32_t errorstate;
2577   uint16_t mmc_rca = 1U;
2578 
2579   /* Check the power State */
2580   if(SDMMC_GetPowerState(hmmc->Instance) == 0U)
2581   {
2582     /* Power off */
2583     return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2584   }
2585 
2586   /* Send CMD2 ALL_SEND_CID */
2587   errorstate = SDMMC_CmdSendCID(hmmc->Instance);
2588   if(errorstate != HAL_MMC_ERROR_NONE)
2589   {
2590     return errorstate;
2591   }
2592   else
2593   {
2594     /* Get Card identification number data */
2595     hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2596     hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
2597     hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
2598     hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
2599   }
2600 
2601   /* Send CMD3 SET_REL_ADDR with argument 0 */
2602   /* MMC Card publishes its RCA. */
2603   errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
2604   if(errorstate != HAL_MMC_ERROR_NONE)
2605   {
2606     return errorstate;
2607   }
2608 
2609   /* Get the MMC card RCA */
2610   hmmc->MmcCard.RelCardAdd = mmc_rca;
2611 
2612   /* Send CMD9 SEND_CSD with argument as card's RCA */
2613   errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2614   if(errorstate != HAL_MMC_ERROR_NONE)
2615   {
2616     return errorstate;
2617   }
2618   else
2619   {
2620     /* Get Card Specific Data */
2621     hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2622     hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
2623     hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
2624     hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
2625   }
2626 
2627   /* Get the Card Class */
2628   hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U);
2629 
2630   /* Get CSD parameters */
2631   if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
2632   {
2633     return hmmc->ErrorCode;
2634   }
2635 
2636   /* Select the Card */
2637   errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2638   if(errorstate != HAL_MMC_ERROR_NONE)
2639   {
2640     return errorstate;
2641   }
2642 
2643   /* Configure SDMMC peripheral interface */
2644   (void)SDMMC_Init(hmmc->Instance, hmmc->Init);
2645 
2646   /* All cards are initialized */
2647   return HAL_MMC_ERROR_NONE;
2648 }
2649 
2650 /**
2651   * @brief  Enquires cards about their operating voltage and configures clock
2652   *         controls and stores MMC information that will be needed in future
2653   *         in the MMC handle.
2654   * @param  hmmc: Pointer to MMC handle
2655   * @retval error state
2656   */
MMC_PowerON(MMC_HandleTypeDef * hmmc)2657 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
2658 {
2659   __IO uint32_t count = 0U;
2660   uint32_t response = 0U, validvoltage = 0U;
2661   uint32_t errorstate;
2662 
2663   /* CMD0: GO_IDLE_STATE */
2664   errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
2665   if(errorstate != HAL_MMC_ERROR_NONE)
2666   {
2667     return errorstate;
2668   }
2669 
2670   while(validvoltage == 0U)
2671   {
2672     if(count++ == SDMMC_MAX_VOLT_TRIAL)
2673     {
2674       return HAL_MMC_ERROR_INVALID_VOLTRANGE;
2675     }
2676 
2677     /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
2678     errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
2679     if(errorstate != HAL_MMC_ERROR_NONE)
2680     {
2681       return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2682     }
2683 
2684     /* Get command response */
2685     response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2686 
2687     /* Get operating voltage*/
2688     validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
2689   }
2690 
2691   /* When power routine is finished and command returns valid voltage */
2692   if (((response & (0xFF000000U)) >> 24U) == 0xC0U)
2693   {
2694     hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
2695   }
2696   else
2697   {
2698     hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
2699   }
2700 
2701   return HAL_MMC_ERROR_NONE;
2702 }
2703 
2704 /**
2705   * @brief  Turns the SDMMC output signals off.
2706   * @param  hmmc: Pointer to MMC handle
2707   * @retval None
2708   */
MMC_PowerOFF(MMC_HandleTypeDef * hmmc)2709 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
2710 {
2711   /* Set Power State to OFF */
2712   (void)SDMMC_PowerState_OFF(hmmc->Instance);
2713 }
2714 
2715 /**
2716   * @brief  Returns the current card's status.
2717   * @param  hmmc: Pointer to MMC handle
2718   * @param  pCardStatus: pointer to the buffer that will contain the MMC card
2719   *         status (Card Status register)
2720   * @retval error state
2721   */
MMC_SendStatus(MMC_HandleTypeDef * hmmc,uint32_t * pCardStatus)2722 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
2723 {
2724   uint32_t errorstate;
2725 
2726   if(pCardStatus == NULL)
2727   {
2728     return HAL_MMC_ERROR_PARAM;
2729   }
2730 
2731   /* Send Status command */
2732   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2733   if(errorstate != HAL_MMC_ERROR_NONE)
2734   {
2735     return errorstate;
2736   }
2737 
2738   /* Get MMC card status */
2739   *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2740 
2741   return HAL_MMC_ERROR_NONE;
2742 }
2743 
2744 /**
2745   * @brief  Reads extended CSD register to get the sectors number of the device
2746   * @param  hmmc: Pointer to MMC handle
2747   * @param  pFieldData: Pointer to the read buffer
2748   * @param  FieldIndex: Index of the field to be read
2749   * @param  Timeout: Specify timeout value
2750   * @retval HAL status
2751   */
MMC_ReadExtCSD(MMC_HandleTypeDef * hmmc,uint32_t * pFieldData,uint16_t FieldIndex,uint32_t Timeout)2752 static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout)
2753 {
2754   SDMMC_DataInitTypeDef config;
2755   uint32_t errorstate;
2756   uint32_t tickstart = HAL_GetTick();
2757   uint32_t count;
2758   uint32_t i = 0;
2759   uint32_t tmp_data;
2760 
2761   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2762 
2763   /* Initialize data control register */
2764   hmmc->Instance->DCTRL = 0;
2765 
2766   /* Configure the MMC DPSM (Data Path State Machine) */
2767   config.DataTimeOut   = SDMMC_DATATIMEOUT;
2768   config.DataLength    = 512;
2769   config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
2770   config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
2771   config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
2772   config.DPSM          = SDMMC_DPSM_ENABLE;
2773   (void)SDMMC_ConfigData(hmmc->Instance, &config);
2774 
2775   /* Set Block Size for Card */
2776   errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
2777   if(errorstate != HAL_MMC_ERROR_NONE)
2778   {
2779     /* Clear all the static flags */
2780     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2781     hmmc->ErrorCode |= errorstate;
2782     hmmc->State = HAL_MMC_STATE_READY;
2783     return HAL_ERROR;
2784   }
2785 
2786   /* Poll on SDMMC flags */
2787   while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
2788   {
2789     if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
2790     {
2791       /* Read data from SDMMC Rx FIFO */
2792       for(count = 0U; count < 8U; count++)
2793       {
2794         tmp_data = SDMMC_ReadFIFO(hmmc->Instance);
2795         /* eg : SEC_COUNT   : FieldIndex = 212 => i+count = 53 */
2796         /*      DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
2797         if ((i + count) == ((uint32_t)FieldIndex/4U))
2798         {
2799           *pFieldData = tmp_data;
2800         }
2801       }
2802       i += 8U;
2803     }
2804 
2805     if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
2806     {
2807       /* Clear all the static flags */
2808       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2809       hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
2810       hmmc->State= HAL_MMC_STATE_READY;
2811       return HAL_TIMEOUT;
2812     }
2813   }
2814 
2815   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2816   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
2817   if(errorstate != HAL_MMC_ERROR_NONE)
2818   {
2819     hmmc->ErrorCode |= errorstate;
2820   }
2821 
2822   /* Clear all the static flags */
2823   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2824 
2825   hmmc->State = HAL_MMC_STATE_READY;
2826 
2827   return HAL_OK;
2828 }
2829 
2830 
2831 /**
2832   * @brief  Wrap up reading in non-blocking mode.
2833   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2834   *              the configuration information.
2835   * @retval None
2836   */
MMC_Read_IT(MMC_HandleTypeDef * hmmc)2837 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
2838 {
2839   uint32_t count, data, dataremaining;
2840   uint8_t* tmp;
2841 
2842   tmp = hmmc->pRxBuffPtr;
2843   dataremaining = hmmc->RxXferSize;
2844 
2845   if (dataremaining > 0U)
2846   {
2847     /* Read data from SDMMC Rx FIFO */
2848     for(count = 0U; count < 8U; count++)
2849     {
2850       data = SDMMC_ReadFIFO(hmmc->Instance);
2851       *tmp = (uint8_t)(data & 0xFFU);
2852       tmp++;
2853       dataremaining--;
2854       *tmp = (uint8_t)((data >> 8U) & 0xFFU);
2855       tmp++;
2856       dataremaining--;
2857       *tmp = (uint8_t)((data >> 16U) & 0xFFU);
2858       tmp++;
2859       dataremaining--;
2860       *tmp = (uint8_t)((data >> 24U) & 0xFFU);
2861       tmp++;
2862       dataremaining--;
2863     }
2864 
2865     hmmc->pRxBuffPtr = tmp;
2866     hmmc->RxXferSize = dataremaining;
2867   }
2868 }
2869 
2870 /**
2871   * @brief  Wrap up writing in non-blocking mode.
2872   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2873   *              the configuration information.
2874   * @retval None
2875   */
MMC_Write_IT(MMC_HandleTypeDef * hmmc)2876 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
2877 {
2878   uint32_t count, data, dataremaining;
2879   uint8_t* tmp;
2880 
2881   tmp = hmmc->pTxBuffPtr;
2882   dataremaining = hmmc->TxXferSize;
2883 
2884   if (dataremaining > 0U)
2885   {
2886     /* Write data to SDMMC Tx FIFO */
2887     for(count = 0U; count < 8U; count++)
2888     {
2889       data = (uint32_t)(*tmp);
2890       tmp++;
2891       dataremaining--;
2892       data |= ((uint32_t)(*tmp) << 8U);
2893       tmp++;
2894       dataremaining--;
2895       data |= ((uint32_t)(*tmp) << 16U);
2896       tmp++;
2897       dataremaining--;
2898       data |= ((uint32_t)(*tmp) << 24U);
2899       tmp++;
2900       dataremaining--;
2901       (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
2902     }
2903 
2904     hmmc->pTxBuffPtr = tmp;
2905     hmmc->TxXferSize = dataremaining;
2906   }
2907 }
2908 
2909 /**
2910   * @}
2911   */
2912 
2913 #endif /* SDMMC1 */
2914 
2915 #endif /* HAL_MMC_MODULE_ENABLED */
2916 
2917 /**
2918   * @}
2919   */
2920 
2921 /**
2922   * @}
2923   */
2924 
2925 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
2926