1 /**
2   ******************************************************************************
3   * @file    stm32h5xx_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   ******************************************************************************
14   * @attention
15   *
16   * Copyright (c) 2023 STMicroelectronics.
17   * All rights reserved.
18   *
19   * This software is licensed under terms that can be found in the LICENSE file
20   * in the root directory of this software component.
21   * If no LICENSE file comes with this software, it is provided AS-IS.
22   *
23   ******************************************************************************
24   @verbatim
25   ==============================================================================
26                         ##### How to use this driver #####
27   ==============================================================================
28   [..]
29     This driver implements a high level communication layer for read and write from/to
30     this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
31     the user in HAL_MMC_MspInit() function (MSP layer).
32     Basically, the MSP layer configuration should be the same as we provide in the
33     examples.
34     You can easily tailor this configuration according to hardware resources.
35 
36   [..]
37     This driver is a generic layered driver for SDMMC memories which uses the HAL
38     SDMMC driver functions to interface with MMC and eMMC cards devices.
39     It is used as follows:
40 
41     (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
42         (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
43         (##) SDMMC pins configuration for MMC card
44             (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
45             (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
46                   and according to your pin assignment;
47         (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
48              and HAL_MMC_WriteBlocks_IT() APIs).
49             (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
50             (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
51             (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
52                   and __HAL_MMC_DISABLE_IT() inside the communication process.
53             (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
54                   and __HAL_MMC_CLEAR_IT()
55         (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used.
56 
57     (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
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 default 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 / (2 * ClockDiv)
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 by adjusting the "ClockDiv" field.
89         In transfer mode and according to the MMC Card standard, make sure that the
90         SDMMC_CK frequency doesn't exceed 25MHz and 100MHz in High-speed mode switch.
91 
92     (#) Select the corresponding MMC Card according to the address read with the step 2.
93 
94     (#) Configure the MMC Card in wide bus mode: 4-bits data.
95 
96   *** MMC Card Read operation ***
97   ==============================
98   [..]
99     (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
100         This function support only 512-bytes block length (the block size should be
101         chosen as 512 bytes).
102         You can choose either one block read operation or multiple block read operation
103         by adjusting the "NumberOfBlocks" parameter.
104         After this, you have to ensure that the transfer is done correctly. The check is done
105         through HAL_MMC_GetCardState() function for MMC card state.
106 
107     (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
108         This function support only 512-bytes block length (the block size should be
109         chosen as 512 bytes).
110         You can choose either one block read operation or multiple block read operation
111         by adjusting the "NumberOfBlocks" parameter.
112         After this, you have to ensure that the transfer is done correctly. The check is done
113         through HAL_MMC_GetCardState() function for MMC card state.
114         You could also check the DMA transfer process through the MMC Rx interrupt event.
115 
116     (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
117         This function allows the read of 512 bytes blocks.
118         You can choose either one block read operation or multiple block read operation
119         by adjusting the "NumberOfBlocks" parameter.
120         After this, you have to ensure that the transfer is done correctly. The check is done
121         through HAL_MMC_GetCardState() function for MMC card state.
122         You could also check the IT transfer process through the MMC Rx interrupt event.
123 
124   *** MMC Card Write operation ***
125   ===============================
126   [..]
127     (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
128         This function support only 512-bytes block length (the block size should be
129         chosen as 512 bytes).
130         You can choose either one block read operation or multiple block read operation
131         by adjusting the "NumberOfBlocks" parameter.
132         After this, you have to ensure that the transfer is done correctly. The check is done
133         through HAL_MMC_GetCardState() function for MMC card state.
134 
135     (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
136         This function support only 512-bytes block length (the block size should be
137         chosen as 512 byte).
138         You can choose either one block read operation or multiple block read operation
139         by adjusting the "NumberOfBlocks" parameter.
140         After this, you have to ensure that the transfer is done correctly. The check is done
141         through HAL_MMC_GetCardState() function for MMC card state.
142         You could also check the DMA transfer process through the MMC Tx interrupt event.
143 
144     (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
145         This function allows the read of 512 bytes blocks.
146         You can choose either one block read operation or multiple block read operation
147         by adjusting the "NumberOfBlocks" parameter.
148         After this, you have to ensure that the transfer is done correctly. The check is done
149         through HAL_MMC_GetCardState() function for MMC card state.
150         You could also check the IT transfer process through the MMC Tx interrupt event.
151 
152   *** MMC card information ***
153   ===========================
154   [..]
155     (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
156         It returns useful information about the MMC card such as block size, card type,
157         block number ...
158 
159   *** MMC card CSD register ***
160   ============================
161   [..]
162     (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
163         Some of the CSD parameters are useful for card initialization and identification.
164 
165   *** MMC card CID register ***
166   ============================
167   [..]
168     (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
169         Some of the CID parameters are useful for card initialization and identification.
170 
171   *** MMC HAL driver macros list ***
172   ==================================
173   [..]
174     Below the list of most used macros in MMC HAL driver.
175 
176     (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
177     (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
178     (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
179     (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
180 
181   [..]
182     (@) You can refer to the MMC HAL driver header file for more useful macros
183 
184   *** Callback registration ***
185   =============================================
186   [..]
187     The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
188     allows the user to configure dynamically the driver callbacks.
189 
190     Use Functions HAL_MMC_RegisterCallback() to register a user callback,
191     it allows to register following callbacks:
192       (+) TxCpltCallback : callback when a transmission transfer is completed.
193       (+) RxCpltCallback : callback when a reception transfer is completed.
194       (+) ErrorCallback : callback when error occurs.
195       (+) AbortCpltCallback : callback when abort is completed.
196       (+) Read_DMALnkLstBufCpltCallback : callback when the DMA reception of linked list node buffer is completed.
197       (+) Write_DMALnkLstBufCpltCallback : callback when the DMA transmission of linked list node buffer is completed.
198       (+) MspInitCallback    : MMC MspInit.
199       (+) MspDeInitCallback  : MMC MspDeInit.
200     This function takes as parameters the HAL peripheral handle, the Callback ID
201     and a pointer to the user callback function.
202 
203     Use function HAL_MMC_UnRegisterCallback() to reset a callback to the default
204     weak (overridden) function. It allows to reset following callbacks:
205       (+) TxCpltCallback : callback when a transmission transfer is completed.
206       (+) RxCpltCallback : callback when a reception transfer is completed.
207       (+) ErrorCallback : callback when error occurs.
208       (+) AbortCpltCallback : callback when abort is completed.
209       (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
210       (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
211       (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
212       (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
213       (+) MspInitCallback    : MMC MspInit.
214       (+) MspDeInitCallback  : MMC MspDeInit.
215     This function) takes as parameters the HAL peripheral handle and the Callback ID.
216 
217     By default, after the HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
218     all callbacks are reset to the corresponding legacy weak (overridden) functions.
219     Exception done for MspInit and MspDeInit callbacks that are respectively
220     reset to the legacy weak (overridden) functions in the HAL_MMC_Init
221     and HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
222     If not, MspInit or MspDeInit are not null, the HAL_MMC_Init and HAL_MMC_DeInit
223     keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
224 
225     Callbacks can be registered/unregistered in READY state only.
226     Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
227     in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
228     during the Init/DeInit.
229     In that case first register the MspInit/MspDeInit user callbacks
230     using HAL_MMC_RegisterCallback before calling HAL_MMC_DeInit
231     or HAL_MMC_Init function.
232 
233     When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
234     not defined, the callback registering feature is not available
235     and weak (overridden) callbacks are used.
236 
237   @endverbatim
238   ******************************************************************************
239   */
240 
241 /* Includes ------------------------------------------------------------------*/
242 #include "stm32h5xx_hal.h"
243 
244 /** @addtogroup STM32H5xx_HAL_Driver
245   * @{
246   */
247 
248 /** @defgroup MMC MMC
249   * @brief MMC HAL module driver
250   * @{
251   */
252 
253 #if defined (SDMMC1) || defined (SDMMC2)
254 #ifdef HAL_MMC_MODULE_ENABLED
255 
256 /* Private typedef -----------------------------------------------------------*/
257 /* Private define ------------------------------------------------------------*/
258 /** @addtogroup MMC_Private_Defines
259   * @{
260   */
261 #if defined (VDD_VALUE) && (VDD_VALUE <= 1950U)
262 #define MMC_VOLTAGE_RANGE               EMMC_LOW_VOLTAGE_RANGE
263 
264 #define MMC_EXT_CSD_PWR_CL_26_INDEX     201
265 #define MMC_EXT_CSD_PWR_CL_52_INDEX     200
266 #define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238
267 
268 #define MMC_EXT_CSD_PWR_CL_26_POS       8
269 #define MMC_EXT_CSD_PWR_CL_52_POS       0
270 #define MMC_EXT_CSD_PWR_CL_DDR_52_POS   16
271 #else
272 #define MMC_VOLTAGE_RANGE               EMMC_HIGH_VOLTAGE_RANGE
273 
274 #define MMC_EXT_CSD_PWR_CL_26_INDEX     203
275 #define MMC_EXT_CSD_PWR_CL_52_INDEX     202
276 #define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239
277 
278 #define MMC_EXT_CSD_PWR_CL_26_POS       24
279 #define MMC_EXT_CSD_PWR_CL_52_POS       16
280 #define MMC_EXT_CSD_PWR_CL_DDR_52_POS   24
281 #endif /* (VDD_VALUE) && (VDD_VALUE <= 1950U)*/
282 
283 #define MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_INDEX 216
284 #define MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_POS   0
285 #define MMC_EXT_CSD_S_A_TIMEOUT_INDEX             217
286 #define MMC_EXT_CSD_S_A_TIMEOUT_POS               8
287 
288 /* Frequencies used in the driver for clock divider calculation */
289 #define MMC_INIT_FREQ                   400000U   /* Initialization phase : 400 kHz max */
290 #define MMC_HIGH_SPEED_FREQ             52000000U /* High speed phase : 52 MHz max */
291 
292 /**
293   * @}
294   */
295 
296 /* Private macro -------------------------------------------------------------*/
297 /* Private variables ---------------------------------------------------------*/
298 /* Private function prototypes -----------------------------------------------*/
299 /* Private functions ---------------------------------------------------------*/
300 /** @defgroup MMC_Private_Functions MMC Private Functions
301   * @{
302   */
303 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
304 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
305 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
306 static void     MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
307 static void     MMC_Write_IT(MMC_HandleTypeDef *hmmc);
308 static void     MMC_Read_IT(MMC_HandleTypeDef *hmmc);
309 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state);
310 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state);
311 static HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex,
312                                         uint32_t Timeout);
313 static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide, uint32_t Speed);
314 
315 /**
316   * @}
317   */
318 /* Exported functions --------------------------------------------------------*/
319 /** @addtogroup MMC_Exported_Functions
320   * @{
321   */
322 
323 /** @addtogroup MMC_Exported_Functions_Group1
324   *  @brief   Initialization and de-initialization functions
325   *
326 @verbatim
327   ==============================================================================
328           ##### Initialization and de-initialization functions #####
329   ==============================================================================
330   [..]
331     This section provides functions allowing to initialize/de-initialize the MMC
332     card device to be ready for use.
333 
334 @endverbatim
335   * @{
336   */
337 
338 /**
339   * @brief  Initializes the MMC according to the specified parameters in the
340             MMC_HandleTypeDef and create the associated handle.
341   * @param  hmmc: Pointer to the MMC handle
342   * @retval HAL status
343   */
HAL_MMC_Init(MMC_HandleTypeDef * hmmc)344 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
345 {
346   /* Check the MMC handle allocation */
347   if (hmmc == NULL)
348   {
349     return HAL_ERROR;
350   }
351 
352   /* Check the parameters */
353   assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
354   assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge));
355   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
356   assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide));
357   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
358   assert_param(IS_SDMMC_CLKDIV(hmmc->Init.ClockDiv));
359 
360   if (hmmc->State == HAL_MMC_STATE_RESET)
361   {
362     /* Allocate lock resource and initialize it */
363     hmmc->Lock = HAL_UNLOCKED;
364 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
365     /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
366     hmmc->TxCpltCallback    = HAL_MMC_TxCpltCallback;
367     hmmc->RxCpltCallback    = HAL_MMC_RxCpltCallback;
368     hmmc->ErrorCallback     = HAL_MMC_ErrorCallback;
369     hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
370     hmmc->Read_DMALnkLstBufCpltCallback  = HAL_MMCEx_Read_DMALnkLstBufCpltCallback;
371     hmmc->Write_DMALnkLstBufCpltCallback = HAL_MMCEx_Write_DMALnkLstBufCpltCallback;
372 
373     if (hmmc->MspInitCallback == NULL)
374     {
375       hmmc->MspInitCallback = HAL_MMC_MspInit;
376     }
377 
378     /* Init the low level hardware */
379     hmmc->MspInitCallback(hmmc);
380 #else
381     /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
382     HAL_MMC_MspInit(hmmc);
383 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
384   }
385 
386   hmmc->State = HAL_MMC_STATE_BUSY;
387 
388   /* Initialize the Card parameters */
389   if (HAL_MMC_InitCard(hmmc) == HAL_ERROR)
390   {
391     return HAL_ERROR;
392   }
393 
394   /* Initialize the error code */
395   hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
396 
397   /* Initialize the MMC operation */
398   hmmc->Context = MMC_CONTEXT_NONE;
399 
400   /* Initialize the MMC state */
401   hmmc->State = HAL_MMC_STATE_READY;
402 
403   /* Configure bus width */
404   if (hmmc->Init.BusWide != SDMMC_BUS_WIDE_1B)
405   {
406     if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK)
407     {
408       return HAL_ERROR;
409     }
410   }
411 
412   return HAL_OK;
413 }
414 
415 /**
416   * @brief  Initializes the MMC Card.
417   * @param  hmmc: Pointer to MMC handle
418   * @note   This function initializes the MMC card. It could be used when a card
419             re-initialization is needed.
420   * @retval HAL status
421   */
HAL_MMC_InitCard(MMC_HandleTypeDef * hmmc)422 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
423 {
424   uint32_t errorstate;
425   MMC_InitTypeDef Init;
426   uint32_t sdmmc_clk;
427 
428   /* Default SDMMC peripheral configuration for MMC card initialization */
429   Init.ClockEdge           = SDMMC_CLOCK_EDGE_RISING;
430   Init.ClockPowerSave      = SDMMC_CLOCK_POWER_SAVE_DISABLE;
431   Init.BusWide             = SDMMC_BUS_WIDE_1B;
432   Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
433 
434   /* Init Clock should be less or equal to 400Khz*/
435   if (hmmc->Instance == SDMMC1)
436   {
437     sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC1);
438   }
439 #if defined (SDMMC2)
440   else if (hmmc->Instance == SDMMC2)
441   {
442     sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC2);
443   }
444 #endif  /* SDMMC2 */
445   else
446   {
447     sdmmc_clk = 0;
448   }
449   if (sdmmc_clk == 0U)
450   {
451     hmmc->State = HAL_MMC_STATE_READY;
452     hmmc->ErrorCode = SDMMC_ERROR_INVALID_PARAMETER;
453     return HAL_ERROR;
454   }
455   Init.ClockDiv = sdmmc_clk / (2U * MMC_INIT_FREQ);
456 
457 #if (USE_SD_TRANSCEIVER != 0U)
458   Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT;
459 #endif /* USE_SD_TRANSCEIVER */
460 
461   /* Initialize SDMMC peripheral interface with default configuration */
462   (void)SDMMC_Init(hmmc->Instance, Init);
463 
464   /* Set Power State to ON */
465   (void)SDMMC_PowerState_ON(hmmc->Instance);
466 
467   /* wait 74 Cycles: required power up waiting time before starting
468      the MMC initialization sequence */
469   if (Init.ClockDiv != 0U)
470   {
471     sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv);
472   }
473 
474   if (sdmmc_clk != 0U)
475   {
476     HAL_Delay(1U + (74U * 1000U / (sdmmc_clk)));
477   }
478 
479   /* Identify card operating voltage */
480   errorstate = MMC_PowerON(hmmc);
481   if (errorstate != HAL_MMC_ERROR_NONE)
482   {
483     hmmc->State = HAL_MMC_STATE_READY;
484     hmmc->ErrorCode |= errorstate;
485     return HAL_ERROR;
486   }
487 
488   /* Card initialization */
489   errorstate = MMC_InitCard(hmmc);
490   if (errorstate != HAL_MMC_ERROR_NONE)
491   {
492     hmmc->State = HAL_MMC_STATE_READY;
493     hmmc->ErrorCode |= errorstate;
494     return HAL_ERROR;
495   }
496 
497   /* Set Block Size for Card */
498   errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
499   if (errorstate != HAL_MMC_ERROR_NONE)
500   {
501     /* Clear all the static flags */
502     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
503     hmmc->ErrorCode |= errorstate;
504     hmmc->State = HAL_MMC_STATE_READY;
505     return HAL_ERROR;
506   }
507 
508   return HAL_OK;
509 }
510 
511 /**
512   * @brief  De-Initializes the MMC card.
513   * @param  hmmc: Pointer to MMC handle
514   * @retval HAL status
515   */
HAL_MMC_DeInit(MMC_HandleTypeDef * hmmc)516 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
517 {
518   /* Check the MMC handle allocation */
519   if (hmmc == NULL)
520   {
521     return HAL_ERROR;
522   }
523 
524   /* Check the parameters */
525   assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
526 
527   hmmc->State = HAL_MMC_STATE_BUSY;
528 
529   /* Set MMC power state to off */
530   MMC_PowerOFF(hmmc);
531 
532 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
533   if (hmmc->MspDeInitCallback == NULL)
534   {
535     hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
536   }
537 
538   /* DeInit the low level hardware */
539   hmmc->MspDeInitCallback(hmmc);
540 #else
541   /* De-Initialize the MSP layer */
542   HAL_MMC_MspDeInit(hmmc);
543 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
544 
545   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
546   hmmc->State = HAL_MMC_STATE_RESET;
547 
548   return HAL_OK;
549 }
550 
551 /**
552   * @brief  Initializes the MMC MSP.
553   * @param  hmmc: Pointer to MMC handle
554   * @retval None
555   */
HAL_MMC_MspInit(MMC_HandleTypeDef * hmmc)556 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
557 {
558   /* Prevent unused argument(s) compilation warning */
559   UNUSED(hmmc);
560 
561   /* NOTE : This function Should not be modified, when the callback is needed,
562             the HAL_MMC_MspInit could be implemented in the user file
563    */
564 }
565 
566 /**
567   * @brief  De-Initialize MMC MSP.
568   * @param  hmmc: Pointer to MMC handle
569   * @retval None
570   */
HAL_MMC_MspDeInit(MMC_HandleTypeDef * hmmc)571 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
572 {
573   /* Prevent unused argument(s) compilation warning */
574   UNUSED(hmmc);
575 
576   /* NOTE : This function Should not be modified, when the callback is needed,
577             the HAL_MMC_MspDeInit could be implemented in the user file
578    */
579 }
580 
581 /**
582   * @}
583   */
584 
585 /** @addtogroup MMC_Exported_Functions_Group2
586   *  @brief   Data transfer functions
587   *
588 @verbatim
589   ==============================================================================
590                         ##### IO operation functions #####
591   ==============================================================================
592   [..]
593     This subsection provides a set of functions allowing to manage the data
594     transfer from/to MMC card.
595 
596 @endverbatim
597   * @{
598   */
599 
600 /**
601   * @brief  Reads block(s) from a specified address in a card. The Data transfer
602   *         is managed by polling mode.
603   * @note   This API should be followed by a check on the card state through
604   *         HAL_MMC_GetCardState().
605   * @param  hmmc: Pointer to MMC handle
606   * @param  pData: pointer to the buffer that will contain the received data
607   * @param  BlockAdd: Block Address from where data is to be read
608   * @param  NumberOfBlocks: Number of MMC blocks to read
609   * @param  Timeout: Specify timeout value
610   * @retval HAL status
611   */
HAL_MMC_ReadBlocks(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks,uint32_t Timeout)612 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd,
613                                      uint32_t NumberOfBlocks,
614                                      uint32_t Timeout)
615 {
616   SDMMC_DataInitTypeDef config;
617   uint32_t errorstate;
618   uint32_t tickstart = HAL_GetTick();
619   uint32_t count;
620   uint32_t data;
621   uint32_t dataremaining;
622   uint32_t add = BlockAdd;
623   uint8_t *tempbuff = pData;
624 
625   if (NULL == pData)
626   {
627     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
628     return HAL_ERROR;
629   }
630 
631   if (hmmc->State == HAL_MMC_STATE_READY)
632   {
633     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
634 
635     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
636     {
637       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
638       return HAL_ERROR;
639     }
640 
641     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
642     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS)
643          & 0x000000FFU) != 0x0U)
644     {
645       if ((NumberOfBlocks % 8U) != 0U)
646       {
647         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
648         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
649         return HAL_ERROR;
650       }
651 
652       if ((BlockAdd % 8U) != 0U)
653       {
654         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
655         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
656         return HAL_ERROR;
657       }
658     }
659 
660     hmmc->State = HAL_MMC_STATE_BUSY;
661 
662     /* Initialize data control register */
663     hmmc->Instance->DCTRL = 0U;
664 
665     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
666     {
667       add *= MMC_BLOCKSIZE;
668     }
669 
670     /* Configure the MMC DPSM (Data Path State Machine) */
671     config.DataTimeOut   = SDMMC_DATATIMEOUT;
672     config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
673     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
674     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
675     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
676     config.DPSM          = SDMMC_DPSM_DISABLE;
677     (void)SDMMC_ConfigData(hmmc->Instance, &config);
678     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
679 
680     /* Read block(s) in polling mode */
681     if (NumberOfBlocks > 1U)
682     {
683       hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
684 
685       /* Read Multi Block command */
686       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
687     }
688     else
689     {
690       hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
691 
692       /* Read Single Block command */
693       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
694     }
695     if (errorstate != HAL_MMC_ERROR_NONE)
696     {
697       /* Clear all the static flags */
698       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
699       hmmc->ErrorCode |= errorstate;
700       hmmc->State = HAL_MMC_STATE_READY;
701       return HAL_ERROR;
702     }
703 
704     /* Poll on SDMMC flags */
705     dataremaining = config.DataLength;
706     while (!__HAL_MMC_GET_FLAG(hmmc,
707                                SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
708     {
709       if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= SDMMC_FIFO_SIZE))
710       {
711         /* Read data from SDMMC Rx FIFO */
712         for (count = 0U; count < (SDMMC_FIFO_SIZE / 4U); count++)
713         {
714           data = SDMMC_ReadFIFO(hmmc->Instance);
715           *tempbuff = (uint8_t)(data & 0xFFU);
716           tempbuff++;
717           *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
718           tempbuff++;
719           *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
720           tempbuff++;
721           *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
722           tempbuff++;
723         }
724         dataremaining -= SDMMC_FIFO_SIZE;
725       }
726 
727       if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
728       {
729         /* Clear all the static flags */
730         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
731         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
732         hmmc->State = HAL_MMC_STATE_READY;
733         return HAL_TIMEOUT;
734       }
735     }
736     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
737 
738     /* Send stop transmission command in case of multiblock read */
739     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
740     {
741       /* Send stop transmission command */
742       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
743       if (errorstate != HAL_MMC_ERROR_NONE)
744       {
745         /* Clear all the static flags */
746         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
747         hmmc->ErrorCode |= errorstate;
748         hmmc->State = HAL_MMC_STATE_READY;
749         return HAL_ERROR;
750       }
751     }
752 
753     /* Get error state */
754     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
755     {
756       /* Clear all the static flags */
757       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
758       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
759       hmmc->State = HAL_MMC_STATE_READY;
760       return HAL_ERROR;
761     }
762     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
763     {
764       /* Clear all the static flags */
765       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
766       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
767       hmmc->State = HAL_MMC_STATE_READY;
768       return HAL_ERROR;
769     }
770     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
771     {
772       /* Clear all the static flags */
773       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
774       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
775       hmmc->State = HAL_MMC_STATE_READY;
776       return HAL_ERROR;
777     }
778     else
779     {
780       /* Nothing to do */
781     }
782 
783     /* Clear all the static flags */
784     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
785 
786     hmmc->State = HAL_MMC_STATE_READY;
787 
788     return HAL_OK;
789   }
790   else
791   {
792     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
793     return HAL_ERROR;
794   }
795 }
796 
797 /**
798   * @brief  Allows to write block(s) to a specified address in a card. The Data
799   *         transfer is managed by polling mode.
800   * @note   This API should be followed by a check on the card state through
801   *         HAL_MMC_GetCardState().
802   * @param  hmmc: Pointer to MMC handle
803   * @param  pData: pointer to the buffer that will contain the data to transmit
804   * @param  BlockAdd: Block Address where data will be written
805   * @param  NumberOfBlocks: Number of MMC blocks to write
806   * @param  Timeout: Specify timeout value
807   * @retval HAL status
808   */
HAL_MMC_WriteBlocks(MMC_HandleTypeDef * hmmc,const uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks,uint32_t Timeout)809 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, const uint8_t *pData, uint32_t BlockAdd,
810                                       uint32_t NumberOfBlocks, uint32_t Timeout)
811 {
812   SDMMC_DataInitTypeDef config;
813   uint32_t errorstate;
814   uint32_t tickstart = HAL_GetTick();
815   uint32_t count;
816   uint32_t data;
817   uint32_t dataremaining;
818   uint32_t add = BlockAdd;
819   const uint8_t *tempbuff = pData;
820 
821   if (NULL == pData)
822   {
823     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
824     return HAL_ERROR;
825   }
826 
827   if (hmmc->State == HAL_MMC_STATE_READY)
828   {
829     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
830 
831     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
832     {
833       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
834       return HAL_ERROR;
835     }
836 
837     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
838     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
839     {
840       if ((NumberOfBlocks % 8U) != 0U)
841       {
842         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
843         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
844         return HAL_ERROR;
845       }
846 
847       if ((BlockAdd % 8U) != 0U)
848       {
849         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
850         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
851         return HAL_ERROR;
852       }
853     }
854 
855     hmmc->State = HAL_MMC_STATE_BUSY;
856 
857     /* Initialize data control register */
858     hmmc->Instance->DCTRL = 0U;
859 
860     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
861     {
862       add *= MMC_BLOCKSIZE;
863     }
864 
865     /* Configure the MMC DPSM (Data Path State Machine) */
866     config.DataTimeOut   = SDMMC_DATATIMEOUT;
867     config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
868     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
869     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
870     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
871     config.DPSM          = SDMMC_DPSM_DISABLE;
872     (void)SDMMC_ConfigData(hmmc->Instance, &config);
873     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
874 
875     /* Write Blocks in Polling mode */
876     if (NumberOfBlocks > 1U)
877     {
878       hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
879 
880       /* Write Multi Block command */
881       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
882     }
883     else
884     {
885       hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
886 
887       /* Write Single Block command */
888       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
889     }
890     if (errorstate != HAL_MMC_ERROR_NONE)
891     {
892       /* Clear all the static flags */
893       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
894       hmmc->ErrorCode |= errorstate;
895       hmmc->State = HAL_MMC_STATE_READY;
896       return HAL_ERROR;
897     }
898 
899     /* Write block(s) in polling mode */
900     dataremaining = config.DataLength;
901     while (!__HAL_MMC_GET_FLAG(hmmc,
902                                SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
903     {
904       if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= SDMMC_FIFO_SIZE))
905       {
906         /* Write data to SDMMC Tx FIFO */
907         for (count = 0U; count < (SDMMC_FIFO_SIZE / 4U); count++)
908         {
909           data = (uint32_t)(*tempbuff);
910           tempbuff++;
911           data |= ((uint32_t)(*tempbuff) << 8U);
912           tempbuff++;
913           data |= ((uint32_t)(*tempbuff) << 16U);
914           tempbuff++;
915           data |= ((uint32_t)(*tempbuff) << 24U);
916           tempbuff++;
917           (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
918         }
919         dataremaining -= SDMMC_FIFO_SIZE;
920       }
921 
922       if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
923       {
924         /* Clear all the static flags */
925         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
926         hmmc->ErrorCode |= errorstate;
927         hmmc->State = HAL_MMC_STATE_READY;
928         return HAL_TIMEOUT;
929       }
930     }
931     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
932 
933     /* Send stop transmission command in case of multiblock write */
934     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
935     {
936       /* Send stop transmission command */
937       errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
938       if (errorstate != HAL_MMC_ERROR_NONE)
939       {
940         /* Clear all the static flags */
941         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
942         hmmc->ErrorCode |= errorstate;
943         hmmc->State = HAL_MMC_STATE_READY;
944         return HAL_ERROR;
945       }
946     }
947 
948     /* Get error state */
949     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
950     {
951       /* Clear all the static flags */
952       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
953       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
954       hmmc->State = HAL_MMC_STATE_READY;
955       return HAL_ERROR;
956     }
957     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
958     {
959       /* Clear all the static flags */
960       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
961       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
962       hmmc->State = HAL_MMC_STATE_READY;
963       return HAL_ERROR;
964     }
965     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR))
966     {
967       /* Clear all the static flags */
968       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
969       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
970       hmmc->State = HAL_MMC_STATE_READY;
971       return HAL_ERROR;
972     }
973     else
974     {
975       /* Nothing to do */
976     }
977 
978     /* Clear all the static flags */
979     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
980 
981     hmmc->State = HAL_MMC_STATE_READY;
982 
983     return HAL_OK;
984   }
985   else
986   {
987     hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
988     return HAL_ERROR;
989   }
990 }
991 
992 /**
993   * @brief  Reads block(s) from a specified address in a card. The Data transfer
994   *         is managed in interrupt mode.
995   * @note   This API should be followed by a check on the card state through
996   *         HAL_MMC_GetCardState().
997   * @note   You could also check the IT transfer process through the MMC Rx
998   *         interrupt event.
999   * @param  hmmc: Pointer to MMC handle
1000   * @param  pData: Pointer to the buffer that will contain the received data
1001   * @param  BlockAdd: Block Address from where data is to be read
1002   * @param  NumberOfBlocks: Number of blocks to read.
1003   * @retval HAL status
1004   */
HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1005 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd,
1006                                         uint32_t NumberOfBlocks)
1007 {
1008   SDMMC_DataInitTypeDef config;
1009   uint32_t errorstate;
1010   uint32_t add = BlockAdd;
1011 
1012   if (NULL == pData)
1013   {
1014     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1015     return HAL_ERROR;
1016   }
1017 
1018   if (hmmc->State == HAL_MMC_STATE_READY)
1019   {
1020     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1021 
1022     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1023     {
1024       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1025       return HAL_ERROR;
1026     }
1027 
1028     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
1029     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
1030     {
1031       if ((NumberOfBlocks % 8U) != 0U)
1032       {
1033         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
1034         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
1035         return HAL_ERROR;
1036       }
1037 
1038       if ((BlockAdd % 8U) != 0U)
1039       {
1040         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
1041         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
1042         return HAL_ERROR;
1043       }
1044     }
1045 
1046     hmmc->State = HAL_MMC_STATE_BUSY;
1047 
1048     /* Initialize data control register */
1049     hmmc->Instance->DCTRL = 0U;
1050 
1051     hmmc->pRxBuffPtr = pData;
1052     hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1053 
1054     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1055     {
1056       add *= MMC_BLOCKSIZE;
1057     }
1058 
1059     /* Configure the MMC DPSM (Data Path State Machine) */
1060     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1061     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1062     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1063     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
1064     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1065     config.DPSM          = SDMMC_DPSM_DISABLE;
1066     (void)SDMMC_ConfigData(hmmc->Instance, &config);
1067     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
1068 
1069     /* Read Blocks in IT mode */
1070     if (NumberOfBlocks > 1U)
1071     {
1072       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
1073 
1074       /* Read Multi Block command */
1075       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
1076     }
1077     else
1078     {
1079       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
1080 
1081       /* Read Single Block command */
1082       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
1083     }
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     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND |
1095                                SDMMC_FLAG_RXFIFOHF));
1096 
1097     return HAL_OK;
1098   }
1099   else
1100   {
1101     return HAL_BUSY;
1102   }
1103 }
1104 
1105 /**
1106   * @brief  Writes block(s) to a specified address in a card. The Data transfer
1107   *         is managed in interrupt mode.
1108   * @note   This API should be followed by a check on the card state through
1109   *         HAL_MMC_GetCardState().
1110   * @note   You could also check the IT transfer process through the MMC Tx
1111   *         interrupt event.
1112   * @param  hmmc: Pointer to MMC handle
1113   * @param  pData: Pointer to the buffer that will contain the data to transmit
1114   * @param  BlockAdd: Block Address where data will be written
1115   * @param  NumberOfBlocks: Number of blocks to write
1116   * @retval HAL status
1117   */
HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef * hmmc,const uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1118 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, const uint8_t *pData,
1119                                          uint32_t BlockAdd, uint32_t NumberOfBlocks)
1120 {
1121   SDMMC_DataInitTypeDef config;
1122   uint32_t errorstate;
1123   uint32_t add = BlockAdd;
1124 
1125   if (NULL == pData)
1126   {
1127     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1128     return HAL_ERROR;
1129   }
1130 
1131   if (hmmc->State == HAL_MMC_STATE_READY)
1132   {
1133     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1134 
1135     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1136     {
1137       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1138       return HAL_ERROR;
1139     }
1140 
1141     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
1142     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
1143     {
1144       if ((NumberOfBlocks % 8U) != 0U)
1145       {
1146         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
1147         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
1148         return HAL_ERROR;
1149       }
1150 
1151       if ((BlockAdd % 8U) != 0U)
1152       {
1153         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
1154         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
1155         return HAL_ERROR;
1156       }
1157     }
1158 
1159     hmmc->State = HAL_MMC_STATE_BUSY;
1160 
1161     /* Initialize data control register */
1162     hmmc->Instance->DCTRL = 0U;
1163 
1164     hmmc->pTxBuffPtr = pData;
1165     hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1166 
1167     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1168     {
1169       add *= MMC_BLOCKSIZE;
1170     }
1171 
1172     /* Configure the MMC DPSM (Data Path State Machine) */
1173     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1174     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1175     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1176     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
1177     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1178     config.DPSM          = SDMMC_DPSM_DISABLE;
1179     (void)SDMMC_ConfigData(hmmc->Instance, &config);
1180 
1181     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
1182 
1183     /* Write Blocks in Polling mode */
1184     if (NumberOfBlocks > 1U)
1185     {
1186       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
1187 
1188       /* Write Multi Block command */
1189       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
1190     }
1191     else
1192     {
1193       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
1194 
1195       /* Write Single Block command */
1196       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
1197     }
1198     if (errorstate != HAL_MMC_ERROR_NONE)
1199     {
1200       /* Clear all the static flags */
1201       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1202       hmmc->ErrorCode |= errorstate;
1203       hmmc->State = HAL_MMC_STATE_READY;
1204       return HAL_ERROR;
1205     }
1206 
1207     /* Enable transfer interrupts */
1208     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND |
1209                                SDMMC_FLAG_TXFIFOHE));
1210 
1211     return HAL_OK;
1212   }
1213   else
1214   {
1215     return HAL_BUSY;
1216   }
1217 }
1218 
1219 /**
1220   * @brief  Reads block(s) from a specified address in a card. The Data transfer
1221   *         is managed by DMA mode.
1222   * @note   This API should be followed by a check on the card state through
1223   *         HAL_MMC_GetCardState().
1224   * @note   You could also check the DMA transfer process through the MMC Rx
1225   *         interrupt event.
1226   * @param  hmmc: Pointer MMC handle
1227   * @param  pData: Pointer to the buffer that will contain the received data
1228   * @param  BlockAdd: Block Address from where data is to be read
1229   * @param  NumberOfBlocks: Number of blocks to read.
1230   * @retval HAL status
1231   */
HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef * hmmc,uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1232 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd,
1233                                          uint32_t NumberOfBlocks)
1234 {
1235   SDMMC_DataInitTypeDef config;
1236   uint32_t errorstate;
1237   uint32_t add = BlockAdd;
1238 
1239   if (NULL == pData)
1240   {
1241     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1242     return HAL_ERROR;
1243   }
1244 
1245   if (hmmc->State == HAL_MMC_STATE_READY)
1246   {
1247     hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1248 
1249     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1250     {
1251       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1252       return HAL_ERROR;
1253     }
1254 
1255     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
1256     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
1257     {
1258       if ((NumberOfBlocks % 8U) != 0U)
1259       {
1260         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
1261         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
1262         return HAL_ERROR;
1263       }
1264 
1265       if ((BlockAdd % 8U) != 0U)
1266       {
1267         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
1268         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
1269         return HAL_ERROR;
1270       }
1271     }
1272 
1273     hmmc->State = HAL_MMC_STATE_BUSY;
1274 
1275     /* Initialize data control register */
1276     hmmc->Instance->DCTRL = 0U;
1277 
1278     hmmc->pRxBuffPtr = pData;
1279     hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1280 
1281     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1282     {
1283       add *= MMC_BLOCKSIZE;
1284     }
1285 
1286     /* Configure the MMC DPSM (Data Path State Machine) */
1287     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1288     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1289     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1290     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
1291     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1292     config.DPSM          = SDMMC_DPSM_DISABLE;
1293     (void)SDMMC_ConfigData(hmmc->Instance, &config);
1294 
1295     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
1296     hmmc->Instance->IDMABASER = (uint32_t) pData ;
1297     hmmc->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
1298 
1299     /* Read Blocks in DMA mode */
1300     if (NumberOfBlocks > 1U)
1301     {
1302       hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1303 
1304       /* Read Multi Block command */
1305       errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
1306     }
1307     else
1308     {
1309       hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1310 
1311       /* Read Single Block command */
1312       errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
1313     }
1314     if (errorstate != HAL_MMC_ERROR_NONE)
1315     {
1316       /* Clear all the static flags */
1317       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1318       hmmc->ErrorCode = errorstate;
1319       hmmc->State = HAL_MMC_STATE_READY;
1320       return HAL_ERROR;
1321     }
1322 
1323     /* Enable transfer interrupts */
1324     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
1325 
1326     return HAL_OK;
1327   }
1328   else
1329   {
1330     return HAL_BUSY;
1331   }
1332 }
1333 
1334 /**
1335   * @brief  Writes block(s) to a specified address in a card. The Data transfer
1336   *         is managed by DMA mode.
1337   * @note   This API should be followed by a check on the card state through
1338   *         HAL_MMC_GetCardState().
1339   * @note   You could also check the DMA transfer process through the MMC Tx
1340   *         interrupt event.
1341   * @param  hmmc: Pointer to MMC handle
1342   * @param  pData: Pointer to the buffer that will contain the data to transmit
1343   * @param  BlockAdd: Block Address where data will be written
1344   * @param  NumberOfBlocks: Number of blocks to write
1345   * @retval HAL status
1346   */
HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef * hmmc,const uint8_t * pData,uint32_t BlockAdd,uint32_t NumberOfBlocks)1347 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, const uint8_t *pData,
1348                                           uint32_t BlockAdd, uint32_t NumberOfBlocks)
1349 {
1350   SDMMC_DataInitTypeDef config;
1351   uint32_t errorstate;
1352   uint32_t add = BlockAdd;
1353 
1354   if (NULL == pData)
1355   {
1356     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1357     return HAL_ERROR;
1358   }
1359 
1360   if (hmmc->State == HAL_MMC_STATE_READY)
1361   {
1362     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1363 
1364     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1365     {
1366       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1367       return HAL_ERROR;
1368     }
1369 
1370     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
1371     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
1372     {
1373       if ((NumberOfBlocks % 8U) != 0U)
1374       {
1375         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
1376         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
1377         return HAL_ERROR;
1378       }
1379 
1380       if ((BlockAdd % 8U) != 0U)
1381       {
1382         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
1383         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
1384         return HAL_ERROR;
1385       }
1386     }
1387 
1388     hmmc->State = HAL_MMC_STATE_BUSY;
1389 
1390     /* Initialize data control register */
1391     hmmc->Instance->DCTRL = 0U;
1392 
1393     hmmc->pTxBuffPtr = pData;
1394     hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1395 
1396     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1397     {
1398       add *= MMC_BLOCKSIZE;
1399     }
1400 
1401     /* Configure the MMC DPSM (Data Path State Machine) */
1402     config.DataTimeOut   = SDMMC_DATATIMEOUT;
1403     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1404     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1405     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
1406     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
1407     config.DPSM          = SDMMC_DPSM_DISABLE;
1408     (void)SDMMC_ConfigData(hmmc->Instance, &config);
1409 
1410     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
1411 
1412     hmmc->Instance->IDMABASER = (uint32_t) pData ;
1413     hmmc->Instance->IDMACTRL  = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
1414 
1415     /* Write Blocks in Polling mode */
1416     if (NumberOfBlocks > 1U)
1417     {
1418       hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1419 
1420       /* Write Multi Block command */
1421       errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
1422     }
1423     else
1424     {
1425       hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1426 
1427       /* Write Single Block command */
1428       errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
1429     }
1430     if (errorstate != HAL_MMC_ERROR_NONE)
1431     {
1432       /* Clear all the static flags */
1433       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1434       hmmc->ErrorCode |= errorstate;
1435       hmmc->State = HAL_MMC_STATE_READY;
1436       return HAL_ERROR;
1437     }
1438 
1439     /* Enable transfer interrupts */
1440     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
1441 
1442     return HAL_OK;
1443   }
1444   else
1445   {
1446     return HAL_BUSY;
1447   }
1448 }
1449 
1450 /**
1451   * @brief  Erases the specified memory area of the given MMC card.
1452   * @note   This API should be followed by a check on the card state through
1453   *         HAL_MMC_GetCardState().
1454   * @param  hmmc: Pointer to MMC handle
1455   * @param  BlockStartAdd: Start Block address
1456   * @param  BlockEndAdd: End Block address
1457   * @retval HAL status
1458   */
HAL_MMC_Erase(MMC_HandleTypeDef * hmmc,uint32_t BlockStartAdd,uint32_t BlockEndAdd)1459 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
1460 {
1461   uint32_t errorstate;
1462   uint32_t start_add = BlockStartAdd;
1463   uint32_t end_add = BlockEndAdd;
1464 
1465   if (hmmc->State == HAL_MMC_STATE_READY)
1466   {
1467     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1468 
1469     if (end_add < start_add)
1470     {
1471       hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1472       return HAL_ERROR;
1473     }
1474 
1475     if (end_add > (hmmc->MmcCard.LogBlockNbr))
1476     {
1477       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1478       return HAL_ERROR;
1479     }
1480 
1481     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
1482     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS)
1483          & 0x000000FFU) != 0x0U)
1484     {
1485       if (((start_add % 8U) != 0U) || ((end_add % 8U) != 0U))
1486       {
1487         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
1488         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
1489         return HAL_ERROR;
1490       }
1491     }
1492 
1493     hmmc->State = HAL_MMC_STATE_BUSY;
1494 
1495     /* Check if the card command class supports erase command */
1496     if (((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
1497     {
1498       /* Clear all the static flags */
1499       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1500       hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
1501       hmmc->State = HAL_MMC_STATE_READY;
1502       return HAL_ERROR;
1503     }
1504 
1505     if ((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
1506     {
1507       /* Clear all the static flags */
1508       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1509       hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
1510       hmmc->State = HAL_MMC_STATE_READY;
1511       return HAL_ERROR;
1512     }
1513 
1514     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1515     {
1516       start_add *= MMC_BLOCKSIZE;
1517       end_add   *= MMC_BLOCKSIZE;
1518     }
1519 
1520     /* Send CMD35 MMC_ERASE_GRP_START with argument as addr  */
1521     errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
1522     if (errorstate != HAL_MMC_ERROR_NONE)
1523     {
1524       /* Clear all the static flags */
1525       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1526       hmmc->ErrorCode |= errorstate;
1527       hmmc->State = HAL_MMC_STATE_READY;
1528       return HAL_ERROR;
1529     }
1530 
1531     /* Send CMD36 MMC_ERASE_GRP_END with argument as addr  */
1532     errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
1533     if (errorstate != HAL_MMC_ERROR_NONE)
1534     {
1535       /* Clear all the static flags */
1536       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1537       hmmc->ErrorCode |= errorstate;
1538       hmmc->State = HAL_MMC_STATE_READY;
1539       return HAL_ERROR;
1540     }
1541 
1542     /* Send CMD38 ERASE */
1543     errorstate = SDMMC_CmdErase(hmmc->Instance, 0UL);
1544     if (errorstate != HAL_MMC_ERROR_NONE)
1545     {
1546       /* Clear all the static flags */
1547       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1548       hmmc->ErrorCode |= errorstate;
1549       hmmc->State = HAL_MMC_STATE_READY;
1550       return HAL_ERROR;
1551     }
1552 
1553     hmmc->State = HAL_MMC_STATE_READY;
1554 
1555     return HAL_OK;
1556   }
1557   else
1558   {
1559     return HAL_BUSY;
1560   }
1561 }
1562 
1563 /**
1564   * @brief  This function handles MMC card interrupt request.
1565   * @param  hmmc: Pointer to MMC handle
1566   * @retval None
1567   */
HAL_MMC_IRQHandler(MMC_HandleTypeDef * hmmc)1568 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
1569 {
1570   uint32_t errorstate;
1571   uint32_t context = hmmc->Context;
1572 
1573   /* Check for SDMMC interrupt flags */
1574   if ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1575   {
1576     MMC_Read_IT(hmmc);
1577   }
1578 
1579   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) != RESET)
1580   {
1581     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND);
1582 
1583     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND  | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
1584                          SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR  | SDMMC_IT_TXFIFOHE | \
1585                          SDMMC_IT_RXFIFOHF);
1586 
1587     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
1588     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
1589 
1590     if ((context & MMC_CONTEXT_DMA) != 0U)
1591     {
1592       hmmc->Instance->DLEN = 0;
1593       hmmc->Instance->DCTRL = 0;
1594       hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA ;
1595 
1596       /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1597       if (((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1598       {
1599         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1600         if (errorstate != HAL_MMC_ERROR_NONE)
1601         {
1602           hmmc->ErrorCode |= errorstate;
1603 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1604           hmmc->ErrorCallback(hmmc);
1605 #else
1606           HAL_MMC_ErrorCallback(hmmc);
1607 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1608         }
1609       }
1610 
1611       /* Clear all the static flags */
1612       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1613 
1614       hmmc->State = HAL_MMC_STATE_READY;
1615       if (((context & MMC_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1616       {
1617 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1618         hmmc->TxCpltCallback(hmmc);
1619 #else
1620         HAL_MMC_TxCpltCallback(hmmc);
1621 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1622       }
1623       if (((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1624       {
1625 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1626         hmmc->RxCpltCallback(hmmc);
1627 #else
1628         HAL_MMC_RxCpltCallback(hmmc);
1629 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1630       }
1631     }
1632     else if ((context & MMC_CONTEXT_IT) != 0U)
1633     {
1634       /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1635       if (((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1636       {
1637         errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1638         if (errorstate != HAL_MMC_ERROR_NONE)
1639         {
1640           hmmc->ErrorCode |= errorstate;
1641 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1642           hmmc->ErrorCallback(hmmc);
1643 #else
1644           HAL_MMC_ErrorCallback(hmmc);
1645 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1646         }
1647       }
1648 
1649       /* Clear all the static flags */
1650       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1651 
1652       hmmc->State = HAL_MMC_STATE_READY;
1653       if (((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1654       {
1655 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1656         hmmc->RxCpltCallback(hmmc);
1657 #else
1658         HAL_MMC_RxCpltCallback(hmmc);
1659 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1660       }
1661       else
1662       {
1663 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1664         hmmc->TxCpltCallback(hmmc);
1665 #else
1666         HAL_MMC_TxCpltCallback(hmmc);
1667 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1668       }
1669     }
1670     else
1671     {
1672       /* Nothing to do */
1673     }
1674   }
1675 
1676   else if ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1677   {
1678     MMC_Write_IT(hmmc);
1679   }
1680 
1681   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL |
1682                               SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
1683   {
1684     /* Set Error code */
1685     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL) != RESET)
1686     {
1687       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
1688     }
1689     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DTIMEOUT) != RESET)
1690     {
1691       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
1692     }
1693     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXOVERR) != RESET)
1694     {
1695       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
1696     }
1697     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXUNDERR) != RESET)
1698     {
1699       hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
1700     }
1701 
1702     /* Clear All flags */
1703     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1704 
1705     /* Disable all interrupts */
1706     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
1707                          SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR);
1708 
1709     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
1710     hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
1711     hmmc->Instance->CMD |= SDMMC_CMD_CMDSTOP;
1712     hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
1713     hmmc->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP);
1714     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DABORT);
1715 
1716     if ((context & MMC_CONTEXT_IT) != 0U)
1717     {
1718       /* Set the MMC state to ready to be able to start again the process */
1719       hmmc->State = HAL_MMC_STATE_READY;
1720 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1721       hmmc->ErrorCallback(hmmc);
1722 #else
1723       HAL_MMC_ErrorCallback(hmmc);
1724 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1725     }
1726     else if ((context & MMC_CONTEXT_DMA) != 0U)
1727     {
1728       if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
1729       {
1730         /* Disable Internal DMA */
1731         __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
1732         hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
1733 
1734         /* Set the MMC state to ready to be able to start again the process */
1735         hmmc->State = HAL_MMC_STATE_READY;
1736 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1737         hmmc->ErrorCallback(hmmc);
1738 #else
1739         HAL_MMC_ErrorCallback(hmmc);
1740 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1741       }
1742     }
1743     else
1744     {
1745       /* Nothing to do */
1746     }
1747   }
1748 
1749   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_IDMABTC) != RESET)
1750   {
1751     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_IT_IDMABTC);
1752 
1753     if ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
1754     {
1755 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1756       hmmc->Write_DMALnkLstBufCpltCallback(hmmc);
1757 #else
1758       HAL_MMCEx_Write_DMALnkLstBufCpltCallback(hmmc);
1759 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1760     }
1761     else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
1762     {
1763 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1764       hmmc->Read_DMALnkLstBufCpltCallback(hmmc);
1765 #else
1766       HAL_MMCEx_Read_DMALnkLstBufCpltCallback(hmmc);
1767 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1768     }
1769   }
1770 
1771   else
1772   {
1773     /* Nothing to do */
1774   }
1775 }
1776 
1777 /**
1778   * @brief return the MMC state
1779   * @param hmmc: Pointer to mmc handle
1780   * @retval HAL state
1781   */
HAL_MMC_GetState(const MMC_HandleTypeDef * hmmc)1782 HAL_MMC_StateTypeDef HAL_MMC_GetState(const MMC_HandleTypeDef *hmmc)
1783 {
1784   return hmmc->State;
1785 }
1786 
1787 /**
1788   * @brief  Return the MMC error code
1789   * @param  hmmc : Pointer to a MMC_HandleTypeDef structure that contains
1790   *              the configuration information.
1791   * @retval MMC Error Code
1792   */
HAL_MMC_GetError(const MMC_HandleTypeDef * hmmc)1793 uint32_t HAL_MMC_GetError(const MMC_HandleTypeDef *hmmc)
1794 {
1795   return hmmc->ErrorCode;
1796 }
1797 
1798 /**
1799   * @brief Tx Transfer completed callbacks
1800   * @param hmmc: Pointer to MMC handle
1801   * @retval None
1802   */
HAL_MMC_TxCpltCallback(MMC_HandleTypeDef * hmmc)1803 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
1804 {
1805   /* Prevent unused argument(s) compilation warning */
1806   UNUSED(hmmc);
1807 
1808   /* NOTE : This function should not be modified, when the callback is needed,
1809             the HAL_MMC_TxCpltCallback can be implemented in the user file
1810    */
1811 }
1812 
1813 /**
1814   * @brief Rx Transfer completed callbacks
1815   * @param hmmc: Pointer MMC handle
1816   * @retval None
1817   */
HAL_MMC_RxCpltCallback(MMC_HandleTypeDef * hmmc)1818 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
1819 {
1820   /* Prevent unused argument(s) compilation warning */
1821   UNUSED(hmmc);
1822 
1823   /* NOTE : This function should not be modified, when the callback is needed,
1824             the HAL_MMC_RxCpltCallback can be implemented in the user file
1825    */
1826 }
1827 
1828 /**
1829   * @brief MMC error callbacks
1830   * @param hmmc: Pointer MMC handle
1831   * @retval None
1832   */
HAL_MMC_ErrorCallback(MMC_HandleTypeDef * hmmc)1833 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
1834 {
1835   /* Prevent unused argument(s) compilation warning */
1836   UNUSED(hmmc);
1837 
1838   /* NOTE : This function should not be modified, when the callback is needed,
1839             the HAL_MMC_ErrorCallback can be implemented in the user file
1840    */
1841 }
1842 
1843 /**
1844   * @brief MMC Abort callbacks
1845   * @param hmmc: Pointer MMC handle
1846   * @retval None
1847   */
HAL_MMC_AbortCallback(MMC_HandleTypeDef * hmmc)1848 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
1849 {
1850   /* Prevent unused argument(s) compilation warning */
1851   UNUSED(hmmc);
1852 
1853   /* NOTE : This function should not be modified, when the callback is needed,
1854             the HAL_MMC_AbortCallback can be implemented in the user file
1855    */
1856 }
1857 
1858 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1859 /**
1860   * @brief  Register a User MMC Callback
1861   *         To be used instead of the weak (overridden) predefined callback
1862   * @note   The HAL_MMC_RegisterCallback() may be called before HAL_MMC_Init() in
1863   *         HAL_MMC_STATE_RESET to register callbacks for HAL_MMC_MSP_INIT_CB_ID
1864   *         and HAL_MMC_MSP_DEINIT_CB_ID.
1865   * @param hmmc : MMC handle
1866   * @param CallbackId : ID of the callback to be registered
1867   *        This parameter can be one of the following values:
1868   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID                 MMC Tx Complete Callback ID
1869   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID                 MMC Rx Complete Callback ID
1870   *          @arg @ref HAL_MMC_ERROR_CB_ID                   MMC Error Callback ID
1871   *          @arg @ref HAL_MMC_ABORT_CB_ID                   MMC Abort Callback ID
1872   *          @arg @ref HAL_MMC_READ_DMA_LNKLST_BUF_CPLT_CB_ID  MMC DMA Rx Linked List Node buffer Callback ID
1873   *          @arg @ref HAL_MMC_WRITE_DMA_LNKLST_BUF_CPLT_CB_ID MMC DMA Tx Linked List Node buffer Callback ID
1874   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID                MMC MspInit Callback ID
1875   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID              MMC MspDeInit Callback ID
1876   * @param pCallback : pointer to the Callback function
1877   * @retval status
1878   */
HAL_MMC_RegisterCallback(MMC_HandleTypeDef * hmmc,HAL_MMC_CallbackIDTypeDef CallbackId,pMMC_CallbackTypeDef pCallback)1879 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId,
1880                                            pMMC_CallbackTypeDef pCallback)
1881 {
1882   HAL_StatusTypeDef status = HAL_OK;
1883 
1884   if (pCallback == NULL)
1885   {
1886     /* Update the error code */
1887     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1888     return HAL_ERROR;
1889   }
1890 
1891   if (hmmc->State == HAL_MMC_STATE_READY)
1892   {
1893     switch (CallbackId)
1894     {
1895       case HAL_MMC_TX_CPLT_CB_ID :
1896         hmmc->TxCpltCallback = pCallback;
1897         break;
1898       case HAL_MMC_RX_CPLT_CB_ID :
1899         hmmc->RxCpltCallback = pCallback;
1900         break;
1901       case HAL_MMC_ERROR_CB_ID :
1902         hmmc->ErrorCallback = pCallback;
1903         break;
1904       case HAL_MMC_ABORT_CB_ID :
1905         hmmc->AbortCpltCallback = pCallback;
1906         break;
1907       case HAL_MMC_READ_DMA_LNKLST_BUF_CPLT_CB_ID :
1908         hmmc->Read_DMALnkLstBufCpltCallback = pCallback;
1909         break;
1910       case HAL_MMC_WRITE_DMA_LNKLST_BUF_CPLT_CB_ID :
1911         hmmc->Write_DMALnkLstBufCpltCallback = pCallback;
1912         break;
1913       case HAL_MMC_MSP_INIT_CB_ID :
1914         hmmc->MspInitCallback = pCallback;
1915         break;
1916       case HAL_MMC_MSP_DEINIT_CB_ID :
1917         hmmc->MspDeInitCallback = pCallback;
1918         break;
1919       default :
1920         /* Update the error code */
1921         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1922         /* update return status */
1923         status =  HAL_ERROR;
1924         break;
1925     }
1926   }
1927   else if (hmmc->State == HAL_MMC_STATE_RESET)
1928   {
1929     switch (CallbackId)
1930     {
1931       case HAL_MMC_MSP_INIT_CB_ID :
1932         hmmc->MspInitCallback = pCallback;
1933         break;
1934       case HAL_MMC_MSP_DEINIT_CB_ID :
1935         hmmc->MspDeInitCallback = pCallback;
1936         break;
1937       default :
1938         /* Update the error code */
1939         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1940         /* update return status */
1941         status =  HAL_ERROR;
1942         break;
1943     }
1944   }
1945   else
1946   {
1947     /* Update the error code */
1948     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1949     /* update return status */
1950     status =  HAL_ERROR;
1951   }
1952 
1953   return status;
1954 }
1955 
1956 /**
1957   * @brief  Unregister a User MMC Callback
1958   *         MMC Callback is redirected to the weak (overridden) predefined callback
1959   * @note   The HAL_MMC_UnRegisterCallback() may be called before HAL_MMC_Init() in
1960   *         HAL_MMC_STATE_RESET to register callbacks for HAL_MMC_MSP_INIT_CB_ID
1961   *         and HAL_MMC_MSP_DEINIT_CB_ID.
1962   * @param hmmc : MMC handle
1963   * @param CallbackId : ID of the callback to be unregistered
1964   *        This parameter can be one of the following values:
1965   *          @arg @ref HAL_MMC_TX_CPLT_CB_ID                 MMC Tx Complete Callback ID
1966   *          @arg @ref HAL_MMC_RX_CPLT_CB_ID                 MMC Rx Complete Callback ID
1967   *          @arg @ref HAL_MMC_ERROR_CB_ID                   MMC Error Callback ID
1968   *          @arg @ref HAL_MMC_ABORT_CB_ID                   MMC Abort Callback ID
1969   *          @arg @ref HAL_MMC_READ_DMA_LNKLST_BUF_CPLT_CB_ID  MMC DMA Rx Linked List Node buffer Callback ID
1970   *          @arg @ref HAL_MMC_WRITE_DMA_LNKLST_BUF_CPLT_CB_ID MMC DMA Tx Linked List Node buffer Callback ID
1971   *          @arg @ref HAL_MMC_MSP_INIT_CB_ID                MMC MspInit Callback ID
1972   *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID              MMC MspDeInit Callback ID
1973   * @retval status
1974   */
HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef * hmmc,HAL_MMC_CallbackIDTypeDef CallbackId)1975 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
1976 {
1977   HAL_StatusTypeDef status = HAL_OK;
1978 
1979   if (hmmc->State == HAL_MMC_STATE_READY)
1980   {
1981     switch (CallbackId)
1982     {
1983       case HAL_MMC_TX_CPLT_CB_ID :
1984         hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
1985         break;
1986       case HAL_MMC_RX_CPLT_CB_ID :
1987         hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
1988         break;
1989       case HAL_MMC_ERROR_CB_ID :
1990         hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
1991         break;
1992       case HAL_MMC_ABORT_CB_ID :
1993         hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
1994         break;
1995       case HAL_MMC_READ_DMA_LNKLST_BUF_CPLT_CB_ID :
1996         hmmc->Read_DMALnkLstBufCpltCallback = HAL_MMCEx_Read_DMALnkLstBufCpltCallback;
1997         break;
1998       case HAL_MMC_WRITE_DMA_LNKLST_BUF_CPLT_CB_ID :
1999         hmmc->Write_DMALnkLstBufCpltCallback = HAL_MMCEx_Write_DMALnkLstBufCpltCallback;
2000         break;
2001       case HAL_MMC_MSP_INIT_CB_ID :
2002         hmmc->MspInitCallback = HAL_MMC_MspInit;
2003         break;
2004       case HAL_MMC_MSP_DEINIT_CB_ID :
2005         hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
2006         break;
2007       default :
2008         /* Update the error code */
2009         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
2010         /* update return status */
2011         status =  HAL_ERROR;
2012         break;
2013     }
2014   }
2015   else if (hmmc->State == HAL_MMC_STATE_RESET)
2016   {
2017     switch (CallbackId)
2018     {
2019       case HAL_MMC_MSP_INIT_CB_ID :
2020         hmmc->MspInitCallback = HAL_MMC_MspInit;
2021         break;
2022       case HAL_MMC_MSP_DEINIT_CB_ID :
2023         hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
2024         break;
2025       default :
2026         /* Update the error code */
2027         hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
2028         /* update return status */
2029         status =  HAL_ERROR;
2030         break;
2031     }
2032   }
2033   else
2034   {
2035     /* Update the error code */
2036     hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
2037     /* update return status */
2038     status =  HAL_ERROR;
2039   }
2040 
2041   return status;
2042 }
2043 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
2044 
2045 /**
2046   * @}
2047   */
2048 
2049 /** @addtogroup MMC_Exported_Functions_Group3
2050   *  @brief   management functions
2051   *
2052 @verbatim
2053   ==============================================================================
2054                       ##### Peripheral Control functions #####
2055   ==============================================================================
2056   [..]
2057     This subsection provides a set of functions allowing to control the MMC card
2058     operations and get the related information
2059 
2060 @endverbatim
2061   * @{
2062   */
2063 
2064 /**
2065   * @brief  Returns information the information of the card which are stored on
2066   *         the CID register.
2067   * @param  hmmc: Pointer to MMC handle
2068   * @param  pCID: Pointer to a HAL_MMC_CIDTypedef structure that
2069   *         contains all CID register parameters
2070   * @retval HAL status
2071   */
HAL_MMC_GetCardCID(MMC_HandleTypeDef * hmmc,HAL_MMC_CardCIDTypeDef * pCID)2072 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
2073 {
2074   pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
2075 
2076   pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
2077 
2078   pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
2079 
2080   pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
2081 
2082   pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
2083 
2084   pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
2085 
2086   pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
2087 
2088   pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
2089 
2090   pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
2091 
2092   pCID->Reserved2 = 1U;
2093 
2094   return HAL_OK;
2095 }
2096 
2097 /**
2098   * @brief  Returns information the information of the card which are stored on
2099   *         the CSD register.
2100   * @param  hmmc: Pointer to MMC handle
2101   * @param  pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
2102   *         contains all CSD register parameters
2103   * @retval HAL status
2104   */
HAL_MMC_GetCardCSD(MMC_HandleTypeDef * hmmc,HAL_MMC_CardCSDTypeDef * pCSD)2105 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
2106 {
2107   uint32_t block_nbr = 0;
2108 
2109   pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
2110 
2111   pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
2112 
2113   pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
2114 
2115   pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
2116 
2117   pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
2118 
2119   pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
2120 
2121   pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
2122 
2123   pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
2124 
2125   pCSD->PartBlockRead   = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
2126 
2127   pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
2128 
2129   pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
2130 
2131   pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
2132 
2133   pCSD->Reserved2 = 0U; /*!< Reserved */
2134 
2135   if (MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
2136   {
2137     return HAL_ERROR;
2138   }
2139 
2140   if (hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
2141   {
2142     pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
2143 
2144     pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
2145 
2146     pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
2147 
2148     pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
2149 
2150     pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
2151 
2152     pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
2153 
2154     hmmc->MmcCard.BlockNbr  = (pCSD->DeviceSize + 1U) ;
2155     hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
2156     hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
2157 
2158     hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / MMC_BLOCKSIZE);
2159     hmmc->MmcCard.LogBlockSize = MMC_BLOCKSIZE;
2160   }
2161   else if (hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
2162   {
2163     hmmc->MmcCard.BlockNbr = block_nbr;
2164     hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
2165     hmmc->MmcCard.BlockSize = MMC_BLOCKSIZE;
2166     hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
2167   }
2168   else
2169   {
2170     /* Clear all the static flags */
2171     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2172     hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2173     hmmc->State = HAL_MMC_STATE_READY;
2174     return HAL_ERROR;
2175   }
2176 
2177   pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
2178 
2179   pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
2180 
2181   pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
2182 
2183   pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
2184 
2185   pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
2186 
2187   pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
2188 
2189   pCSD->MaxWrBlockLen = (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
2190 
2191   pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
2192 
2193   pCSD->Reserved3 = 0;
2194 
2195   pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
2196 
2197   pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
2198 
2199   pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
2200 
2201   pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
2202 
2203   pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
2204 
2205   pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
2206 
2207   pCSD->ECC = (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
2208 
2209   pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
2210 
2211   pCSD->Reserved4 = 1;
2212 
2213   return HAL_OK;
2214 }
2215 
2216 /**
2217   * @brief  Gets the MMC card info.
2218   * @param  hmmc: Pointer to MMC handle
2219   * @param  pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
2220   *         will contain the MMC card status information
2221   * @retval HAL status
2222   */
HAL_MMC_GetCardInfo(MMC_HandleTypeDef * hmmc,HAL_MMC_CardInfoTypeDef * pCardInfo)2223 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
2224 {
2225   pCardInfo->CardType     = (uint32_t)(hmmc->MmcCard.CardType);
2226   pCardInfo->Class        = (uint32_t)(hmmc->MmcCard.Class);
2227   pCardInfo->RelCardAdd   = (uint32_t)(hmmc->MmcCard.RelCardAdd);
2228   pCardInfo->BlockNbr     = (uint32_t)(hmmc->MmcCard.BlockNbr);
2229   pCardInfo->BlockSize    = (uint32_t)(hmmc->MmcCard.BlockSize);
2230   pCardInfo->LogBlockNbr  = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
2231   pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
2232 
2233   return HAL_OK;
2234 }
2235 
2236 /**
2237   * @brief  Returns information the information of the card which are stored on
2238   *         the Extended CSD register.
2239   * @param  hmmc Pointer to MMC handle
2240   * @param  pExtCSD Pointer to a memory area (512 bytes) that contains all
2241   *         Extended CSD register parameters
2242   * @param  Timeout Specify timeout value
2243   * @retval HAL status
2244   */
HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef * hmmc,uint32_t * pExtCSD,uint32_t Timeout)2245 HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout)
2246 {
2247   SDMMC_DataInitTypeDef config;
2248   uint32_t errorstate;
2249   uint32_t tickstart = HAL_GetTick();
2250   uint32_t count;
2251   uint32_t *tmp_buf;
2252 
2253   if (NULL == pExtCSD)
2254   {
2255     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2256     return HAL_ERROR;
2257   }
2258 
2259   if (hmmc->State == HAL_MMC_STATE_READY)
2260   {
2261     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2262 
2263     hmmc->State = HAL_MMC_STATE_BUSY;
2264 
2265     /* Initialize data control register */
2266     hmmc->Instance->DCTRL = 0;
2267 
2268     /* Initiaize the destination pointer */
2269     tmp_buf = pExtCSD;
2270 
2271     /* Configure the MMC DPSM (Data Path State Machine) */
2272     config.DataTimeOut   = SDMMC_DATATIMEOUT;
2273     config.DataLength    = MMC_BLOCKSIZE;
2274     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
2275     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
2276     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
2277     config.DPSM          = SDMMC_DPSM_DISABLE;
2278     (void)SDMMC_ConfigData(hmmc->Instance, &config);
2279     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
2280 
2281     /* Send ExtCSD Read command to Card */
2282     errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
2283     if (errorstate != HAL_MMC_ERROR_NONE)
2284     {
2285       /* Clear all the static flags */
2286       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2287       hmmc->ErrorCode |= errorstate;
2288       hmmc->State = HAL_MMC_STATE_READY;
2289       return HAL_ERROR;
2290     }
2291 
2292     /* Poll on SDMMC flags */
2293     while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR |
2294                                SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
2295     {
2296       if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
2297       {
2298         /* Read data from SDMMC Rx FIFO */
2299         for (count = 0U; count < (SDMMC_FIFO_SIZE / 4U); count++)
2300         {
2301           *tmp_buf = SDMMC_ReadFIFO(hmmc->Instance);
2302           tmp_buf++;
2303         }
2304       }
2305 
2306       if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
2307       {
2308         /* Clear all the static flags */
2309         __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2310         hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
2311         hmmc->State = HAL_MMC_STATE_READY;
2312         return HAL_TIMEOUT;
2313       }
2314     }
2315 
2316     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
2317 
2318     /* Get error state */
2319     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
2320     {
2321       /* Clear all the static flags */
2322       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2323       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
2324       hmmc->State = HAL_MMC_STATE_READY;
2325       return HAL_ERROR;
2326     }
2327     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
2328     {
2329       /* Clear all the static flags */
2330       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2331       hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
2332       hmmc->State = HAL_MMC_STATE_READY;
2333       return HAL_ERROR;
2334     }
2335     else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
2336     {
2337       /* Clear all the static flags */
2338       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2339       hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
2340       hmmc->State = HAL_MMC_STATE_READY;
2341       return HAL_ERROR;
2342     }
2343     else
2344     {
2345       /* Nothing to do */
2346     }
2347 
2348     /* Clear all the static flags */
2349     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2350     hmmc->State = HAL_MMC_STATE_READY;
2351   }
2352 
2353   return HAL_OK;
2354 }
2355 
2356 /**
2357   * @brief  Enables wide bus operation for the requested card if supported by
2358   *         card.
2359   * @param  hmmc: Pointer to MMC handle
2360   * @param  WideMode: Specifies the MMC card wide bus mode
2361   *          This parameter can be one of the following values:
2362   *            @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
2363   *            @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
2364   *            @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
2365   * @retval HAL status
2366   */
HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef * hmmc,uint32_t WideMode)2367 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
2368 {
2369   uint32_t count;
2370   SDMMC_InitTypeDef Init;
2371   uint32_t errorstate;
2372   uint32_t response = 0U;
2373 
2374   /* Check the parameters */
2375   assert_param(IS_SDMMC_BUS_WIDE(WideMode));
2376 
2377   /* Change State */
2378   hmmc->State = HAL_MMC_STATE_BUSY;
2379 
2380   /* Check and update the power class if needed */
2381   if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U)
2382   {
2383     if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U)
2384     {
2385       errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_DDR);
2386     }
2387     else
2388     {
2389       errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_HIGH);
2390     }
2391   }
2392   else
2393   {
2394     errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_DEFAULT);
2395   }
2396 
2397   if (errorstate == HAL_MMC_ERROR_NONE)
2398   {
2399     if (WideMode == SDMMC_BUS_WIDE_8B)
2400     {
2401       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
2402     }
2403     else if (WideMode == SDMMC_BUS_WIDE_4B)
2404     {
2405       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
2406     }
2407     else if (WideMode == SDMMC_BUS_WIDE_1B)
2408     {
2409       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
2410     }
2411     else
2412     {
2413       /* WideMode is not a valid argument*/
2414       errorstate = HAL_MMC_ERROR_PARAM;
2415     }
2416 
2417     /* Check for switch error and violation of the trial number of sending CMD 13 */
2418     if (errorstate == HAL_MMC_ERROR_NONE)
2419     {
2420       /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2421       count = SDMMC_MAX_TRIAL;
2422       do
2423       {
2424         errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2425         if (errorstate != HAL_MMC_ERROR_NONE)
2426         {
2427           break;
2428         }
2429 
2430         /* Get command response */
2431         response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2432         count--;
2433       } while (((response & 0x100U) == 0U) && (count != 0U));
2434 
2435       /* Check the status after the switch command execution */
2436       if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
2437       {
2438         /* Check the bit SWITCH_ERROR of the device status */
2439         if ((response & 0x80U) != 0U)
2440         {
2441           errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
2442         }
2443         else
2444         {
2445           /* Configure the SDMMC peripheral */
2446           Init = hmmc->Init;
2447           Init.BusWide = WideMode;
2448           (void)SDMMC_Init(hmmc->Instance, Init);
2449         }
2450       }
2451       else if (count == 0U)
2452       {
2453         errorstate = SDMMC_ERROR_TIMEOUT;
2454       }
2455       else
2456       {
2457         /* Nothing to do */
2458       }
2459     }
2460   }
2461 
2462   /* Change State */
2463   hmmc->State = HAL_MMC_STATE_READY;
2464 
2465   if (errorstate != HAL_MMC_ERROR_NONE)
2466   {
2467     /* Clear all the static flags */
2468     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2469     hmmc->ErrorCode |= errorstate;
2470     return HAL_ERROR;
2471   }
2472 
2473   return HAL_OK;
2474 }
2475 
2476 /**
2477   * @brief  Configure the speed bus mode
2478   * @param  hmmc: Pointer to the MMC handle
2479   * @param  SpeedMode: Specifies the MMC card speed bus mode
2480   *          This parameter can be one of the following values:
2481   *            @arg SDMMC_SPEED_MODE_AUTO: Max speed mode supported by the card
2482   *            @arg SDMMC_SPEED_MODE_DEFAULT: Default Speed (MMC @ 26MHz)
2483   *            @arg SDMMC_SPEED_MODE_HIGH: High Speed (MMC @ 52 MHz)
2484   *            @arg SDMMC_SPEED_MODE_DDR: High Speed DDR (MMC DDR @ 52 MHz)
2485   * @retval HAL status
2486   */
2487 
HAL_MMC_ConfigSpeedBusOperation(MMC_HandleTypeDef * hmmc,uint32_t SpeedMode)2488 HAL_StatusTypeDef HAL_MMC_ConfigSpeedBusOperation(MMC_HandleTypeDef *hmmc, uint32_t SpeedMode)
2489 {
2490   uint32_t tickstart;
2491   HAL_StatusTypeDef status = HAL_OK;
2492   uint32_t device_type;
2493   uint32_t errorstate;
2494 
2495   /* Check the parameters */
2496   assert_param(IS_SDMMC_SPEED_MODE(SpeedMode));
2497 
2498   /* Change State */
2499   hmmc->State = HAL_MMC_STATE_BUSY;
2500 
2501   /* Field DEVICE_TYPE [196 = 49*4] of Extended CSD register */
2502   device_type = (hmmc->Ext_CSD[49] & 0x000000FFU);
2503 
2504   switch (SpeedMode)
2505   {
2506     case SDMMC_SPEED_MODE_AUTO:
2507     {
2508       if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
2509       {
2510         /* High Speed DDR mode allowed */
2511         errorstate = MMC_HighSpeed(hmmc, ENABLE);
2512         if (errorstate != HAL_MMC_ERROR_NONE)
2513         {
2514           hmmc->ErrorCode |= errorstate;
2515         }
2516         else
2517         {
2518           if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_CLKDIV) != 0U)
2519           {
2520             /* DDR mode not supported with CLKDIV = 0 */
2521             errorstate = MMC_DDR_Mode(hmmc, ENABLE);
2522             if (errorstate != HAL_MMC_ERROR_NONE)
2523             {
2524               hmmc->ErrorCode |= errorstate;
2525             }
2526           }
2527         }
2528       }
2529       else if ((device_type & 0x02U) != 0U)
2530       {
2531         /* High Speed mode allowed */
2532         errorstate = MMC_HighSpeed(hmmc, ENABLE);
2533         if (errorstate != HAL_MMC_ERROR_NONE)
2534         {
2535           hmmc->ErrorCode |= errorstate;
2536         }
2537       }
2538       else
2539       {
2540         /* Nothing to do : keep current speed */
2541       }
2542       break;
2543     }
2544     case SDMMC_SPEED_MODE_DDR:
2545     {
2546       if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
2547       {
2548         /* High Speed DDR mode allowed */
2549         errorstate = MMC_HighSpeed(hmmc, ENABLE);
2550         if (errorstate != HAL_MMC_ERROR_NONE)
2551         {
2552           hmmc->ErrorCode |= errorstate;
2553         }
2554         else
2555         {
2556           if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_CLKDIV) != 0U)
2557           {
2558             /* DDR mode not supported with CLKDIV = 0 */
2559             errorstate = MMC_DDR_Mode(hmmc, ENABLE);
2560             if (errorstate != HAL_MMC_ERROR_NONE)
2561             {
2562               hmmc->ErrorCode |= errorstate;
2563             }
2564           }
2565         }
2566       }
2567       else
2568       {
2569         /* High Speed DDR mode not allowed */
2570         hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2571         status = HAL_ERROR;
2572       }
2573       break;
2574     }
2575     case SDMMC_SPEED_MODE_HIGH:
2576     {
2577       if ((device_type & 0x02U) != 0U)
2578       {
2579         /* High Speed mode allowed */
2580         errorstate = MMC_HighSpeed(hmmc, ENABLE);
2581         if (errorstate != HAL_MMC_ERROR_NONE)
2582         {
2583           hmmc->ErrorCode |= errorstate;
2584         }
2585       }
2586       else
2587       {
2588         /* High Speed mode not allowed */
2589         hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2590         status = HAL_ERROR;
2591       }
2592       break;
2593     }
2594     case SDMMC_SPEED_MODE_DEFAULT:
2595     {
2596       if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U)
2597       {
2598         /* High Speed DDR mode activated */
2599         errorstate = MMC_DDR_Mode(hmmc, DISABLE);
2600         if (errorstate != HAL_MMC_ERROR_NONE)
2601         {
2602           hmmc->ErrorCode |= errorstate;
2603         }
2604       }
2605       if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U)
2606       {
2607         /* High Speed mode activated */
2608         errorstate = MMC_HighSpeed(hmmc, DISABLE);
2609         if (errorstate != HAL_MMC_ERROR_NONE)
2610         {
2611           hmmc->ErrorCode |= errorstate;
2612         }
2613       }
2614       break;
2615     }
2616     default:
2617       hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2618       status = HAL_ERROR;
2619       break;
2620   }
2621 
2622   /* Verify that MMC card is ready to use after Speed mode switch*/
2623   tickstart = HAL_GetTick();
2624   while ((HAL_MMC_GetCardState(hmmc) != HAL_MMC_CARD_TRANSFER))
2625   {
2626     if ((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
2627     {
2628       hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
2629       hmmc->State = HAL_MMC_STATE_READY;
2630       return HAL_TIMEOUT;
2631     }
2632   }
2633 
2634   /* Change State */
2635   hmmc->State = HAL_MMC_STATE_READY;
2636   return status;
2637 }
2638 
2639 /**
2640   * @brief  Gets the current mmc card data state.
2641   * @param  hmmc: pointer to MMC handle
2642   * @retval Card state
2643   */
HAL_MMC_GetCardState(MMC_HandleTypeDef * hmmc)2644 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
2645 {
2646   uint32_t cardstate;
2647   uint32_t errorstate;
2648   uint32_t resp1 = 0U;
2649 
2650   errorstate = MMC_SendStatus(hmmc, &resp1);
2651   if (errorstate != HAL_MMC_ERROR_NONE)
2652   {
2653     hmmc->ErrorCode |= errorstate;
2654   }
2655 
2656   cardstate = ((resp1 >> 9U) & 0x0FU);
2657 
2658   return (HAL_MMC_CardStateTypeDef)cardstate;
2659 }
2660 
2661 /**
2662   * @brief  Abort the current transfer and disable the MMC.
2663   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2664   *                the configuration information for MMC module.
2665   * @retval HAL status
2666   */
HAL_MMC_Abort(MMC_HandleTypeDef * hmmc)2667 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
2668 {
2669   uint32_t error_code;
2670   uint32_t tickstart;
2671 
2672   if (hmmc->State == HAL_MMC_STATE_BUSY)
2673   {
2674     /* DIsable All interrupts */
2675     __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
2676                          SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR);
2677     __SDMMC_CMDTRANS_DISABLE(hmmc->Instance);
2678 
2679     /*we will send the CMD12 in all cases in order to stop the data transfers*/
2680     /*In case the data transfer just finished, the external memory will not respond
2681       and will return HAL_MMC_ERROR_CMD_RSP_TIMEOUT*/
2682     /*In case the data transfer aborted , the external memory will respond and will return HAL_MMC_ERROR_NONE*/
2683     /*Other scenario will return HAL_ERROR*/
2684 
2685     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2686     error_code = hmmc->ErrorCode;
2687     if ((error_code != HAL_MMC_ERROR_NONE) && (error_code != HAL_MMC_ERROR_CMD_RSP_TIMEOUT))
2688     {
2689       return HAL_ERROR;
2690     }
2691 
2692     tickstart = HAL_GetTick();
2693     if ((hmmc->Instance->DCTRL & SDMMC_DCTRL_DTDIR) == SDMMC_TRANSFER_DIR_TO_CARD)
2694     {
2695       if (hmmc->ErrorCode == HAL_MMC_ERROR_NONE)
2696       {
2697         while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DABORT | SDMMC_FLAG_BUSYD0END))
2698         {
2699           if ((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
2700           {
2701             hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
2702             hmmc->State = HAL_MMC_STATE_READY;
2703             return HAL_TIMEOUT;
2704           }
2705         }
2706       }
2707 
2708       if (hmmc->ErrorCode == HAL_MMC_ERROR_CMD_RSP_TIMEOUT)
2709       {
2710         while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND))
2711         {
2712           if ((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
2713           {
2714             hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
2715             hmmc->State = HAL_MMC_STATE_READY;
2716             return HAL_TIMEOUT;
2717           }
2718         }
2719       }
2720     }
2721     else if ((hmmc->Instance->DCTRL & SDMMC_DCTRL_DTDIR) == SDMMC_TRANSFER_DIR_TO_SDMMC)
2722     {
2723       while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DABORT | SDMMC_FLAG_DATAEND))
2724       {
2725         if ((HAL_GetTick() - tickstart) >=  SDMMC_DATATIMEOUT)
2726         {
2727           hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
2728           hmmc->State = HAL_MMC_STATE_READY;
2729           return HAL_TIMEOUT;
2730         }
2731       }
2732     }
2733     else
2734     {
2735       /* Nothing to do*/
2736     }
2737 
2738     /*The reason of all these while conditions previously is that we need to wait the SDMMC and clear
2739       the appropriate flags that will be set depending of the abort/non abort of the memory */
2740     /*Not waiting the SDMMC flags will cause the next SDMMC_DISABLE_IDMA to not get cleared and will result
2741       in next SDMMC read/write operation to fail */
2742 
2743     /*SDMMC ready for clear data flags*/
2744     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
2745     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2746     /* If IDMA Context, disable Internal DMA */
2747     hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
2748 
2749     hmmc->State = HAL_MMC_STATE_READY;
2750 
2751     /* Initialize the MMC operation */
2752     hmmc->Context = MMC_CONTEXT_NONE;
2753   }
2754   return HAL_OK;
2755 }
2756 /**
2757   * @brief  Abort the current transfer and disable the MMC (IT mode).
2758   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2759   *                the configuration information for MMC module.
2760   * @retval HAL status
2761   */
HAL_MMC_Abort_IT(MMC_HandleTypeDef * hmmc)2762 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
2763 {
2764   HAL_MMC_CardStateTypeDef CardState;
2765 
2766   /* DIsable All interrupts */
2767   __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \
2768                        SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR);
2769 
2770   /* If IDMA Context, disable Internal DMA */
2771   hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
2772 
2773   /* Clear All flags */
2774   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2775 
2776   CardState = HAL_MMC_GetCardState(hmmc);
2777   hmmc->State = HAL_MMC_STATE_READY;
2778 
2779   if ((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2780   {
2781     hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2782   }
2783   if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2784   {
2785     return HAL_ERROR;
2786   }
2787   else
2788   {
2789 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2790     hmmc->AbortCpltCallback(hmmc);
2791 #else
2792     HAL_MMC_AbortCallback(hmmc);
2793 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
2794   }
2795 
2796   return HAL_OK;
2797 }
2798 
2799 /**
2800   * @brief  Perform specific commands sequence for the different type of erase.
2801   * @note   This API should be followed by a check on the card state through
2802   *         HAL_MMC_GetCardState().
2803   * @param  hmmc Pointer to MMC handle
2804   * @param  EraseType Specifies the type of erase to be performed
2805   *          This parameter can be one of the following values:
2806   *             @arg HAL_MMC_TRIM Erase the write blocks identified by CMD35 & 36
2807   *             @arg HAL_MMC_ERASE Erase the erase groups identified by CMD35 & 36
2808   *             @arg HAL_MMC_DISCARD Discard the write blocks identified by CMD35 & 36
2809   *             @arg HAL_MMC_SECURE_ERASE Perform a secure purge according SRT on the erase groups identified
2810   *                  by CMD35 & 36
2811   *             @arg HAL_MMC_SECURE_TRIM_STEP1 Mark the write blocks identified by CMD35 & 36 for secure erase
2812   *             @arg HAL_MMC_SECURE_TRIM_STEP2 Perform a secure purge according SRT on the write blocks
2813   *                  previously identified
2814   * @param  BlockStartAdd Start Block address
2815   * @param  BlockEndAdd End Block address
2816   * @retval HAL status
2817   */
HAL_MMC_EraseSequence(MMC_HandleTypeDef * hmmc,uint32_t EraseType,uint32_t BlockStartAdd,uint32_t BlockEndAdd)2818 HAL_StatusTypeDef HAL_MMC_EraseSequence(MMC_HandleTypeDef *hmmc, uint32_t EraseType,
2819                                         uint32_t BlockStartAdd, uint32_t BlockEndAdd)
2820 {
2821   uint32_t errorstate;
2822   uint32_t start_add = BlockStartAdd;
2823   uint32_t end_add = BlockEndAdd;
2824   uint32_t tickstart = HAL_GetTick();
2825 
2826   /* Check the erase type value is correct */
2827   assert_param(IS_MMC_ERASE_TYPE(EraseType));
2828 
2829   /* Check the coherence between start and end address */
2830   if (end_add < start_add)
2831   {
2832     hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2833     return HAL_ERROR;
2834   }
2835 
2836   /* Check that the end address is not out of range of device memory */
2837   if (end_add > (hmmc->MmcCard.LogBlockNbr))
2838   {
2839     hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
2840     return HAL_ERROR;
2841   }
2842 
2843   /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
2844   if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
2845   {
2846     if (((start_add % 8U) != 0U) || ((end_add % 8U) != 0U))
2847     {
2848       /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
2849       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
2850       return HAL_ERROR;
2851     }
2852   }
2853 
2854   /* Check if the card command class supports erase command */
2855   if (((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
2856   {
2857     hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2858     return HAL_ERROR;
2859   }
2860 
2861   /* Check the state of the driver */
2862   if (hmmc->State == HAL_MMC_STATE_READY)
2863   {
2864     /* Change State */
2865     hmmc->State = HAL_MMC_STATE_BUSY;
2866 
2867     /* Check that the card is not locked */
2868     if ((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
2869     {
2870       hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
2871       hmmc->State = HAL_MMC_STATE_READY;
2872       return HAL_ERROR;
2873     }
2874 
2875     /* In case of low capacity card, the address is not block number but bytes */
2876     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2877     {
2878       start_add *= MMC_BLOCKSIZE;
2879       end_add   *= MMC_BLOCKSIZE;
2880     }
2881 
2882     /* Send CMD35 MMC_ERASE_GRP_START with start address as argument */
2883     errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
2884     if (errorstate == HAL_MMC_ERROR_NONE)
2885     {
2886       /* Send CMD36 MMC_ERASE_GRP_END with end address as argument */
2887       errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
2888       if (errorstate == HAL_MMC_ERROR_NONE)
2889       {
2890         /* Send CMD38 ERASE with erase type as argument */
2891         errorstate = SDMMC_CmdErase(hmmc->Instance, EraseType);
2892         if (errorstate == HAL_MMC_ERROR_NONE)
2893         {
2894           if ((EraseType == HAL_MMC_SECURE_ERASE) || (EraseType == HAL_MMC_SECURE_TRIM_STEP2))
2895           {
2896             /* Wait that the device is ready by checking the D0 line */
2897             while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
2898             {
2899               if ((HAL_GetTick() - tickstart) >= SDMMC_MAXERASETIMEOUT)
2900               {
2901                 errorstate = HAL_MMC_ERROR_TIMEOUT;
2902               }
2903             }
2904 
2905             /* Clear the flag corresponding to end D0 bus line */
2906             __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
2907           }
2908         }
2909       }
2910     }
2911 
2912     /* Change State */
2913     hmmc->State = HAL_MMC_STATE_READY;
2914 
2915     /* Manage errors */
2916     if (errorstate != HAL_MMC_ERROR_NONE)
2917     {
2918       /* Clear all the static flags */
2919       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2920       hmmc->ErrorCode |= errorstate;
2921 
2922       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
2923       {
2924         return HAL_ERROR;
2925       }
2926       else
2927       {
2928         return HAL_TIMEOUT;
2929       }
2930     }
2931     else
2932     {
2933       return HAL_OK;
2934     }
2935   }
2936   else
2937   {
2938     return HAL_BUSY;
2939   }
2940 }
2941 
2942 /**
2943   * @brief  Perform sanitize operation on the device.
2944   * @note   This API should be followed by a check on the card state through
2945   *         HAL_MMC_GetCardState().
2946   * @param  hmmc Pointer to MMC handle
2947   * @retval HAL status
2948   */
HAL_MMC_Sanitize(MMC_HandleTypeDef * hmmc)2949 HAL_StatusTypeDef HAL_MMC_Sanitize(MMC_HandleTypeDef *hmmc)
2950 {
2951   uint32_t errorstate;
2952   uint32_t response = 0U;
2953   uint32_t count;
2954   uint32_t tickstart = HAL_GetTick();
2955 
2956   /* Check the state of the driver */
2957   if (hmmc->State == HAL_MMC_STATE_READY)
2958   {
2959     /* Change State */
2960     hmmc->State = HAL_MMC_STATE_BUSY;
2961 
2962     /* Index : 165 - Value : 0x01 */
2963     errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03A50100U);
2964     if (errorstate == HAL_MMC_ERROR_NONE)
2965     {
2966       /* Wait that the device is ready by checking the D0 line */
2967       while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
2968       {
2969         if ((HAL_GetTick() - tickstart) >= SDMMC_MAXERASETIMEOUT)
2970         {
2971           errorstate = HAL_MMC_ERROR_TIMEOUT;
2972         }
2973       }
2974 
2975       /* Clear the flag corresponding to end D0 bus line */
2976       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
2977 
2978       if (errorstate == HAL_MMC_ERROR_NONE)
2979       {
2980         /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2981         count = SDMMC_MAX_TRIAL;
2982         do
2983         {
2984           errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2985           if (errorstate != HAL_MMC_ERROR_NONE)
2986           {
2987             break;
2988           }
2989 
2990           /* Get command response */
2991           response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2992           count--;
2993         } while (((response & 0x100U) == 0U) && (count != 0U));
2994 
2995         /* Check the status after the switch command execution */
2996         if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
2997         {
2998           /* Check the bit SWITCH_ERROR of the device status */
2999           if ((response & 0x80U) != 0U)
3000           {
3001             errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
3002           }
3003         }
3004         else if (count == 0U)
3005         {
3006           errorstate = SDMMC_ERROR_TIMEOUT;
3007         }
3008         else
3009         {
3010           /* Nothing to do */
3011         }
3012       }
3013     }
3014 
3015     /* Change State */
3016     hmmc->State = HAL_MMC_STATE_READY;
3017 
3018     /* Manage errors */
3019     if (errorstate != HAL_MMC_ERROR_NONE)
3020     {
3021       /* Clear all the static flags */
3022       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3023       hmmc->ErrorCode |= errorstate;
3024 
3025       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
3026       {
3027         return HAL_ERROR;
3028       }
3029       else
3030       {
3031         return HAL_TIMEOUT;
3032       }
3033     }
3034     else
3035     {
3036       return HAL_OK;
3037     }
3038   }
3039   else
3040   {
3041     return HAL_BUSY;
3042   }
3043 }
3044 
3045 /**
3046   * @brief  Configure the Secure Removal Type (SRT) in the Extended CSD register.
3047   * @note   This API should be followed by a check on the card state through
3048   *         HAL_MMC_GetCardState().
3049   * @param  hmmc Pointer to MMC handle
3050   * @param  SRTMode Specifies the type of erase to be performed
3051   *          This parameter can be one of the following values:
3052   *            @arg HAL_MMC_SRT_ERASE Information removed by an erase
3053   *            @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character
3054   *                 followed by an erase
3055   *            @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character,
3056   *                 its complement then a random character
3057   *            @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined
3058   * @retval HAL status
3059   */
HAL_MMC_ConfigSecRemovalType(MMC_HandleTypeDef * hmmc,uint32_t SRTMode)3060 HAL_StatusTypeDef HAL_MMC_ConfigSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t SRTMode)
3061 {
3062   uint32_t srt;
3063   uint32_t errorstate;
3064   uint32_t response = 0U;
3065   uint32_t count;
3066 
3067   /* Check the erase type value is correct */
3068   assert_param(IS_MMC_SRT_TYPE(SRTMode));
3069 
3070   /* Check the state of the driver */
3071   if (hmmc->State == HAL_MMC_STATE_READY)
3072   {
3073     /* Get the supported values by the device */
3074     if (HAL_MMC_GetSupportedSecRemovalType(hmmc, &srt) == HAL_OK)
3075     {
3076       /* Change State */
3077       hmmc->State = HAL_MMC_STATE_BUSY;
3078 
3079       /* Check the value passed as parameter is supported by the device */
3080       if ((SRTMode & srt) != 0U)
3081       {
3082         /* Index : 16 - Value : SRTMode */
3083         srt |= ((POSITION_VAL(SRTMode)) << 4U);
3084         errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03100000U | (srt << 8U)));
3085         if (errorstate == HAL_MMC_ERROR_NONE)
3086         {
3087           /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3088           count = SDMMC_MAX_TRIAL;
3089           do
3090           {
3091             errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3092             if (errorstate != HAL_MMC_ERROR_NONE)
3093             {
3094               break;
3095             }
3096 
3097             /* Get command response */
3098             response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3099             count--;
3100           } while (((response & 0x100U) == 0U) && (count != 0U));
3101 
3102           /* Check the status after the switch command execution */
3103           if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
3104           {
3105             /* Check the bit SWITCH_ERROR of the device status */
3106             if ((response & 0x80U) != 0U)
3107             {
3108               errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
3109             }
3110           }
3111           else if (count == 0U)
3112           {
3113             errorstate = SDMMC_ERROR_TIMEOUT;
3114           }
3115           else
3116           {
3117             /* Nothing to do */
3118           }
3119         }
3120       }
3121       else
3122       {
3123         errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3124       }
3125 
3126       /* Change State */
3127       hmmc->State = HAL_MMC_STATE_READY;
3128     }
3129     else
3130     {
3131       errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
3132     }
3133 
3134     /* Manage errors */
3135     if (errorstate != HAL_MMC_ERROR_NONE)
3136     {
3137       /* Clear all the static flags */
3138       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3139       hmmc->ErrorCode |= errorstate;
3140       return HAL_ERROR;
3141     }
3142     else
3143     {
3144       return HAL_OK;
3145     }
3146   }
3147   else
3148   {
3149     return HAL_BUSY;
3150   }
3151 }
3152 
3153 /**
3154   * @brief  Gets the supported values of the the Secure Removal Type (SRT).
3155   * @param  hmmc pointer to MMC handle
3156   * @param  SupportedSRT pointer for supported SRT value
3157   *          This parameter is a bit field of the following values:
3158   *            @arg HAL_MMC_SRT_ERASE Information removed by an erase
3159   *            @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character followed
3160   *                  by an erase
3161   *            @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character,
3162   *                 its complement then a random character
3163   *            @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined
3164   * @retval HAL status
3165   */
HAL_MMC_GetSupportedSecRemovalType(MMC_HandleTypeDef * hmmc,uint32_t * SupportedSRT)3166 HAL_StatusTypeDef HAL_MMC_GetSupportedSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t *SupportedSRT)
3167 {
3168   /* Check the state of the driver */
3169   if (hmmc->State == HAL_MMC_STATE_READY)
3170   {
3171     /* Change State */
3172     hmmc->State = HAL_MMC_STATE_BUSY;
3173 
3174     /* Read field SECURE_REMOVAL_TYPE [16 = 4*4] of the Extended CSD register */
3175     *SupportedSRT = (hmmc->Ext_CSD[4] & 0x0000000FU); /* Bits [3:0] of field 16 */
3176 
3177     /* Change State */
3178     hmmc->State = HAL_MMC_STATE_READY;
3179 
3180     return HAL_OK;
3181   }
3182   else
3183   {
3184     return HAL_BUSY;
3185   }
3186 }
3187 
3188 /**
3189   * @brief  Switch the device from Standby State to Sleep State.
3190   * @param  hmmc pointer to MMC handle
3191   * @retval HAL status
3192   */
HAL_MMC_SleepDevice(MMC_HandleTypeDef * hmmc)3193 HAL_StatusTypeDef HAL_MMC_SleepDevice(MMC_HandleTypeDef *hmmc)
3194 {
3195   uint32_t errorstate,
3196            sleep_timeout,
3197            timeout,
3198            count,
3199            response = 0U  ;
3200   uint32_t tickstart = HAL_GetTick();
3201 
3202   /* Check the state of the driver */
3203   if (hmmc->State == HAL_MMC_STATE_READY)
3204   {
3205     /* Change State */
3206     hmmc->State = HAL_MMC_STATE_BUSY;
3207 
3208     /* Set the power-off notification to powered-on : Ext_CSD[34] = 1 */
3209     errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220100U));
3210     if (errorstate == HAL_MMC_ERROR_NONE)
3211     {
3212       /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3213       count = SDMMC_MAX_TRIAL;
3214       do
3215       {
3216         errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3217         if (errorstate != HAL_MMC_ERROR_NONE)
3218         {
3219           break;
3220         }
3221 
3222         /* Get command response */
3223         response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3224         count--;
3225       } while (((response & 0x100U) == 0U) && (count != 0U));
3226 
3227       /* Check the status after the switch command execution */
3228       if (count == 0U)
3229       {
3230         errorstate = SDMMC_ERROR_TIMEOUT;
3231       }
3232       else if (errorstate == HAL_MMC_ERROR_NONE)
3233       {
3234         /* Check the bit SWITCH_ERROR of the device status */
3235         if ((response & 0x80U) != 0U)
3236         {
3237           errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3238         }
3239         else
3240         {
3241           /* Set the power-off notification to sleep notification : Ext_CSD[34] = 4 */
3242           errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220400U));
3243           if (errorstate == HAL_MMC_ERROR_NONE)
3244           {
3245             /* Field SLEEP_NOTIFICATION_TIME [216] */
3246             sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_INDEX / 4)] >>
3247                               MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_POS) & 0x000000FFU);
3248 
3249             /* Sleep/Awake Timeout = 10us * 2^SLEEP_NOTIFICATION_TIME */
3250             /* In HAL, the tick interrupt occurs each ms */
3251             if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U))
3252             {
3253               sleep_timeout = 0x17U; /* Max register value defined is 0x17 */
3254             }
3255             timeout = (((1UL << sleep_timeout) / 100U) + 1U);
3256 
3257             /* Wait that the device is ready by checking the D0 line */
3258             while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
3259             {
3260               if ((HAL_GetTick() - tickstart) >= timeout)
3261               {
3262                 errorstate = SDMMC_ERROR_TIMEOUT;
3263               }
3264             }
3265 
3266             /* Clear the flag corresponding to end D0 bus line */
3267             __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
3268 
3269             if (errorstate == HAL_MMC_ERROR_NONE)
3270             {
3271               /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3272               count = SDMMC_MAX_TRIAL;
3273               do
3274               {
3275                 errorstate = SDMMC_CmdSendStatus(hmmc->Instance,
3276                                                  (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3277                 if (errorstate != HAL_MMC_ERROR_NONE)
3278                 {
3279                   break;
3280                 }
3281 
3282                 /* Get command response */
3283                 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3284                 count--;
3285               } while (((response & 0x100U) == 0U) && (count != 0U));
3286 
3287               /* Check the status after the switch command execution */
3288               if (count == 0U)
3289               {
3290                 errorstate = SDMMC_ERROR_TIMEOUT;
3291               }
3292               else if (errorstate == HAL_MMC_ERROR_NONE)
3293               {
3294                 /* Check the bit SWITCH_ERROR of the device status */
3295                 if ((response & 0x80U) != 0U)
3296                 {
3297                   errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3298                 }
3299                 else
3300                 {
3301                   /* Switch the device in stand-by mode */
3302                   (void)SDMMC_CmdSelDesel(hmmc->Instance, 0U);
3303 
3304                   /* Field S_A_TIEMOUT [217] */
3305                   sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_S_A_TIMEOUT_INDEX / 4)] >>
3306                                     MMC_EXT_CSD_S_A_TIMEOUT_POS) & 0x000000FFU);
3307 
3308                   /* Sleep/Awake Timeout = 100ns * 2^S_A_TIMEOUT */
3309                   /* In HAL, the tick interrupt occurs each ms */
3310                   if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U))
3311                   {
3312                     sleep_timeout = 0x17U; /* Max register value defined is 0x17 */
3313                   }
3314                   timeout = (((1UL << sleep_timeout) / 10000U) + 1U);
3315 
3316                   if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_STANDBY)
3317                   {
3318                     /* Send CMD5 CMD_MMC_SLEEP_AWAKE with RCA and SLEEP as argument */
3319                     errorstate = SDMMC_CmdSleepMmc(hmmc->Instance,
3320                                                    ((hmmc->MmcCard.RelCardAdd << 16U) | (0x1U << 15U)));
3321                     if (errorstate == HAL_MMC_ERROR_NONE)
3322                     {
3323                       /* Wait that the device is ready by checking the D0 line */
3324                       while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
3325                       {
3326                         if ((HAL_GetTick() - tickstart) >= timeout)
3327                         {
3328                           errorstate = SDMMC_ERROR_TIMEOUT;
3329                         }
3330                       }
3331 
3332                       /* Clear the flag corresponding to end D0 bus line */
3333                       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
3334                     }
3335                   }
3336                   else
3337                   {
3338                     errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE;
3339                   }
3340                 }
3341               }
3342               else
3343               {
3344                 /* Nothing to do */
3345               }
3346             }
3347           }
3348         }
3349       }
3350       else
3351       {
3352         /* Nothing to do */
3353       }
3354     }
3355 
3356     /* Change State */
3357     hmmc->State = HAL_MMC_STATE_READY;
3358 
3359     /* Manage errors */
3360     if (errorstate != HAL_MMC_ERROR_NONE)
3361     {
3362       /* Clear all the static flags */
3363       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3364       hmmc->ErrorCode |= errorstate;
3365 
3366       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
3367       {
3368         return HAL_ERROR;
3369       }
3370       else
3371       {
3372         return HAL_TIMEOUT;
3373       }
3374     }
3375     else
3376     {
3377       return HAL_OK;
3378     }
3379   }
3380   else
3381   {
3382     return HAL_BUSY;
3383   }
3384 }
3385 
3386 /**
3387   * @brief  Switch the device from Sleep State to Standby State.
3388   * @param  hmmc pointer to MMC handle
3389   * @retval HAL status
3390   */
HAL_MMC_AwakeDevice(MMC_HandleTypeDef * hmmc)3391 HAL_StatusTypeDef HAL_MMC_AwakeDevice(MMC_HandleTypeDef *hmmc)
3392 {
3393   uint32_t errorstate;
3394   uint32_t sleep_timeout;
3395   uint32_t timeout;
3396   uint32_t count;
3397   uint32_t response = 0U;
3398   uint32_t tickstart = HAL_GetTick();
3399 
3400   /* Check the state of the driver */
3401   if (hmmc->State == HAL_MMC_STATE_READY)
3402   {
3403     /* Change State */
3404     hmmc->State = HAL_MMC_STATE_BUSY;
3405 
3406     /* Field S_A_TIEMOUT [217] */
3407     sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_S_A_TIMEOUT_INDEX / 4)] >> MMC_EXT_CSD_S_A_TIMEOUT_POS) &
3408                      0x000000FFU);
3409 
3410     /* Sleep/Awake Timeout = 100ns * 2^S_A_TIMEOUT */
3411     /* In HAL, the tick interrupt occurs each ms */
3412     if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U))
3413     {
3414       sleep_timeout = 0x17U; /* Max register value defined is 0x17 */
3415     }
3416     timeout = (((1UL << sleep_timeout) / 10000U) + 1U);
3417 
3418     /* Send CMD5 CMD_MMC_SLEEP_AWAKE with RCA and AWAKE as argument */
3419     errorstate = SDMMC_CmdSleepMmc(hmmc->Instance, (hmmc->MmcCard.RelCardAdd << 16U));
3420     if (errorstate == HAL_MMC_ERROR_NONE)
3421     {
3422       /* Wait that the device is ready by checking the D0 line */
3423       while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
3424       {
3425         if ((HAL_GetTick() - tickstart) >= timeout)
3426         {
3427           errorstate = SDMMC_ERROR_TIMEOUT;
3428         }
3429       }
3430 
3431       /* Clear the flag corresponding to end D0 bus line */
3432       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
3433 
3434       if (errorstate == HAL_MMC_ERROR_NONE)
3435       {
3436         if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_STANDBY)
3437         {
3438           /* Switch the device in transfer mode */
3439           errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (hmmc->MmcCard.RelCardAdd << 16U));
3440           if (errorstate == HAL_MMC_ERROR_NONE)
3441           {
3442             if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_TRANSFER)
3443             {
3444               /* Set the power-off notification to powered-on : Ext_CSD[34] = 1 */
3445               errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220100U));
3446               if (errorstate == HAL_MMC_ERROR_NONE)
3447               {
3448                 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3449                 count = SDMMC_MAX_TRIAL;
3450                 do
3451                 {
3452                   errorstate = SDMMC_CmdSendStatus(hmmc->Instance,
3453                                                    (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3454                   if (errorstate != HAL_MMC_ERROR_NONE)
3455                   {
3456                     break;
3457                   }
3458 
3459                   /* Get command response */
3460                   response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3461                   count--;
3462                 } while (((response & 0x100U) == 0U) && (count != 0U));
3463 
3464                 /* Check the status after the switch command execution */
3465                 if (count == 0U)
3466                 {
3467                   errorstate = SDMMC_ERROR_TIMEOUT;
3468                 }
3469                 else if (errorstate == HAL_MMC_ERROR_NONE)
3470                 {
3471                   /* Check the bit SWITCH_ERROR of the device status */
3472                   if ((response & 0x80U) != 0U)
3473                   {
3474                     errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3475                   }
3476                 }
3477                 else
3478                 {
3479                   /* NOthing to do */
3480                 }
3481               }
3482             }
3483             else
3484             {
3485               errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE;
3486             }
3487           }
3488         }
3489         else
3490         {
3491           errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE;
3492         }
3493       }
3494     }
3495 
3496     /* Change State */
3497     hmmc->State = HAL_MMC_STATE_READY;
3498 
3499     /* Manage errors */
3500     if (errorstate != HAL_MMC_ERROR_NONE)
3501     {
3502       /* Clear all the static flags */
3503       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3504       hmmc->ErrorCode |= errorstate;
3505 
3506       if (errorstate != HAL_MMC_ERROR_TIMEOUT)
3507       {
3508         return HAL_ERROR;
3509       }
3510       else
3511       {
3512         return HAL_TIMEOUT;
3513       }
3514     }
3515     else
3516     {
3517       return HAL_OK;
3518     }
3519   }
3520   else
3521   {
3522     return HAL_BUSY;
3523   }
3524 }
3525 /**
3526   * @}
3527   */
3528 
3529 /**
3530   * @}
3531   */
3532 
3533 /* Private function ----------------------------------------------------------*/
3534 /** @addtogroup MMC_Private_Functions
3535   * @{
3536   */
3537 
3538 /**
3539   * @brief  Initializes the mmc card.
3540   * @param  hmmc: Pointer to MMC handle
3541   * @retval MMC Card error state
3542   */
MMC_InitCard(MMC_HandleTypeDef * hmmc)3543 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
3544 {
3545   HAL_MMC_CardCSDTypeDef CSD;
3546   uint32_t errorstate;
3547   uint16_t mmc_rca = 2U;
3548   MMC_InitTypeDef Init;
3549 
3550   /* Check the power State */
3551   if (SDMMC_GetPowerState(hmmc->Instance) == 0U)
3552   {
3553     /* Power off */
3554     return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
3555   }
3556 
3557   /* Send CMD2 ALL_SEND_CID */
3558   errorstate = SDMMC_CmdSendCID(hmmc->Instance);
3559   if (errorstate != HAL_MMC_ERROR_NONE)
3560   {
3561     return errorstate;
3562   }
3563   else
3564   {
3565     /* Get Card identification number data */
3566     hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3567     hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
3568     hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
3569     hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
3570   }
3571 
3572   /* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */
3573   /* MMC Card publishes its RCA. */
3574   errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca);
3575   if (errorstate != HAL_MMC_ERROR_NONE)
3576   {
3577     return errorstate;
3578   }
3579 
3580   /* Get the MMC card RCA */
3581   hmmc->MmcCard.RelCardAdd = mmc_rca;
3582 
3583   /* Send CMD9 SEND_CSD with argument as card's RCA */
3584   errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
3585   if (errorstate != HAL_MMC_ERROR_NONE)
3586   {
3587     return errorstate;
3588   }
3589   else
3590   {
3591     /* Get Card Specific Data */
3592     hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3593     hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
3594     hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
3595     hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
3596   }
3597 
3598   /* Get the Card Class */
3599   hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U);
3600 
3601   /* Select the Card */
3602   errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3603   if (errorstate != HAL_MMC_ERROR_NONE)
3604   {
3605     return errorstate;
3606   }
3607 
3608   /* Get CSD parameters */
3609   if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
3610   {
3611     return hmmc->ErrorCode;
3612   }
3613 
3614   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3615   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3616   if (errorstate != HAL_MMC_ERROR_NONE)
3617   {
3618     hmmc->ErrorCode |= errorstate;
3619   }
3620 
3621   /* Get Extended CSD parameters */
3622   if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != HAL_OK)
3623   {
3624     return hmmc->ErrorCode;
3625   }
3626 
3627   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3628   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3629   if (errorstate != HAL_MMC_ERROR_NONE)
3630   {
3631     hmmc->ErrorCode |= errorstate;
3632   }
3633 
3634   /* Configure the SDMMC peripheral */
3635   Init = hmmc->Init;
3636   Init.BusWide = SDMMC_BUS_WIDE_1B;
3637   (void)SDMMC_Init(hmmc->Instance, Init);
3638 
3639   /* All cards are initialized */
3640   return HAL_MMC_ERROR_NONE;
3641 }
3642 
3643 /**
3644   * @brief  Enquires cards about their operating voltage and configures clock
3645   *         controls and stores MMC information that will be needed in future
3646   *         in the MMC handle.
3647   * @param  hmmc: Pointer to MMC handle
3648   * @retval error state
3649   */
MMC_PowerON(MMC_HandleTypeDef * hmmc)3650 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
3651 {
3652   __IO uint32_t count = 0U;
3653   uint32_t response = 0U;
3654   uint32_t validvoltage = 0U;
3655   uint32_t errorstate;
3656 
3657   /* CMD0: GO_IDLE_STATE */
3658   errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
3659   if (errorstate != HAL_MMC_ERROR_NONE)
3660   {
3661     return errorstate;
3662   }
3663 
3664   while (validvoltage == 0U)
3665   {
3666     if (count++ == SDMMC_MAX_VOLT_TRIAL)
3667     {
3668       return HAL_MMC_ERROR_INVALID_VOLTRANGE;
3669     }
3670 
3671     /* SEND CMD1 APP_CMD with voltage range as argument */
3672     errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE);
3673     if (errorstate != HAL_MMC_ERROR_NONE)
3674     {
3675       return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
3676     }
3677 
3678     /* Get command response */
3679     response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3680 
3681     /* Get operating voltage*/
3682     validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
3683   }
3684 
3685   /* When power routine is finished and command returns valid voltage */
3686   if (((response & (0xFF000000U)) >> 24) == 0xC0U)
3687   {
3688     hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
3689   }
3690   else
3691   {
3692     hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
3693   }
3694 
3695   return HAL_MMC_ERROR_NONE;
3696 }
3697 
3698 /**
3699   * @brief  Turns the SDMMC output signals off.
3700   * @param  hmmc: Pointer to MMC handle
3701   * @retval None
3702   */
MMC_PowerOFF(MMC_HandleTypeDef * hmmc)3703 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
3704 {
3705   /* Set Power State to OFF */
3706   (void)SDMMC_PowerState_OFF(hmmc->Instance);
3707 }
3708 
3709 /**
3710   * @brief  Returns the current card's status.
3711   * @param  hmmc: Pointer to MMC handle
3712   * @param  pCardStatus: pointer to the buffer that will contain the MMC card
3713   *         status (Card Status register)
3714   * @retval error state
3715   */
MMC_SendStatus(MMC_HandleTypeDef * hmmc,uint32_t * pCardStatus)3716 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
3717 {
3718   uint32_t errorstate;
3719 
3720   if (pCardStatus == NULL)
3721   {
3722     return HAL_MMC_ERROR_PARAM;
3723   }
3724 
3725   /* Send Status command */
3726   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
3727   if (errorstate != HAL_MMC_ERROR_NONE)
3728   {
3729     return errorstate;
3730   }
3731 
3732   /* Get MMC card status */
3733   *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3734 
3735   return HAL_MMC_ERROR_NONE;
3736 }
3737 
3738 /**
3739   * @brief  Reads extended CSD register to get the sectors number of the device
3740   * @param  hmmc: Pointer to MMC handle
3741   * @param  pFieldData: Pointer to the read buffer
3742   * @param  FieldIndex: Index of the field to be read
3743   * @param  Timeout: Specify timeout value
3744   * @retval HAL status
3745   */
MMC_ReadExtCSD(MMC_HandleTypeDef * hmmc,uint32_t * pFieldData,uint16_t FieldIndex,uint32_t Timeout)3746 static HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData,
3747                                         uint16_t FieldIndex, uint32_t Timeout)
3748 {
3749   SDMMC_DataInitTypeDef config;
3750   uint32_t errorstate;
3751   uint32_t tickstart = HAL_GetTick();
3752   uint32_t count;
3753   uint32_t i = 0;
3754   uint32_t tmp_data;
3755 
3756   hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
3757 
3758   /* Initialize data control register */
3759   hmmc->Instance->DCTRL = 0;
3760 
3761   /* Configure the MMC DPSM (Data Path State Machine) */
3762   config.DataTimeOut   = SDMMC_DATATIMEOUT;
3763   config.DataLength    = MMC_BLOCKSIZE;
3764   config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
3765   config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
3766   config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
3767   config.DPSM          = SDMMC_DPSM_ENABLE;
3768   (void)SDMMC_ConfigData(hmmc->Instance, &config);
3769 
3770   /* Set Block Size for Card */
3771   errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
3772   if (errorstate != HAL_MMC_ERROR_NONE)
3773   {
3774     /* Clear all the static flags */
3775     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3776     hmmc->ErrorCode |= errorstate;
3777     hmmc->State = HAL_MMC_STATE_READY;
3778     return HAL_ERROR;
3779   }
3780 
3781   /* Poll on SDMMC flags */
3782   while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT |
3783                              SDMMC_FLAG_DATAEND))
3784   {
3785     if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
3786     {
3787       /* Read data from SDMMC Rx FIFO */
3788       for (count = 0U; count < (SDMMC_FIFO_SIZE / 4U); count++)
3789       {
3790         tmp_data = SDMMC_ReadFIFO(hmmc->Instance);
3791         /* eg : SEC_COUNT   : FieldIndex = 212 => i+count = 53 */
3792         /*      DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
3793         if ((i + count) == ((uint32_t)FieldIndex / 4U))
3794         {
3795           *pFieldData = tmp_data;
3796         }
3797       }
3798       i += 8U;
3799     }
3800 
3801     if (((HAL_GetTick() - tickstart) >=  Timeout) || (Timeout == 0U))
3802     {
3803       /* Clear all the static flags */
3804       __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3805       hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
3806       hmmc->State = HAL_MMC_STATE_READY;
3807       return HAL_TIMEOUT;
3808     }
3809   }
3810 
3811   /* Get error state */
3812   if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
3813   {
3814     /* Clear all the static flags */
3815     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3816     hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
3817     hmmc->State = HAL_MMC_STATE_READY;
3818     return HAL_ERROR;
3819   }
3820   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
3821   {
3822     /* Clear all the static flags */
3823     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3824     hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
3825     hmmc->State = HAL_MMC_STATE_READY;
3826     return HAL_ERROR;
3827   }
3828   else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
3829   {
3830     /* Clear all the static flags */
3831     __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3832     hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
3833     hmmc->State = HAL_MMC_STATE_READY;
3834     return HAL_ERROR;
3835   }
3836   else
3837   {
3838     /* Nothing to do */
3839   }
3840 
3841   /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3842   errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
3843   if (errorstate != HAL_MMC_ERROR_NONE)
3844   {
3845     hmmc->ErrorCode |= errorstate;
3846   }
3847 
3848   /* Clear all the static flags */
3849   __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
3850 
3851   hmmc->State = HAL_MMC_STATE_READY;
3852 
3853   return HAL_OK;
3854 }
3855 
3856 /**
3857   * @brief  Wrap up reading in non-blocking mode.
3858   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
3859   *              the configuration information.
3860   * @retval None
3861   */
MMC_Read_IT(MMC_HandleTypeDef * hmmc)3862 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
3863 {
3864   uint32_t count;
3865   uint32_t data;
3866   uint8_t *tmp;
3867 
3868   tmp = hmmc->pRxBuffPtr;
3869 
3870   if (hmmc->RxXferSize >= SDMMC_FIFO_SIZE)
3871   {
3872     /* Read data from SDMMC Rx FIFO */
3873     for (count = 0U; count < (SDMMC_FIFO_SIZE / 4U); count++)
3874     {
3875       data = SDMMC_ReadFIFO(hmmc->Instance);
3876       *tmp = (uint8_t)(data & 0xFFU);
3877       tmp++;
3878       *tmp = (uint8_t)((data >> 8U) & 0xFFU);
3879       tmp++;
3880       *tmp = (uint8_t)((data >> 16U) & 0xFFU);
3881       tmp++;
3882       *tmp = (uint8_t)((data >> 24U) & 0xFFU);
3883       tmp++;
3884     }
3885 
3886     hmmc->pRxBuffPtr = tmp;
3887     hmmc->RxXferSize -= SDMMC_FIFO_SIZE;
3888   }
3889 }
3890 
3891 /**
3892   * @brief  Wrap up writing in non-blocking mode.
3893   * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
3894   *              the configuration information.
3895   * @retval None
3896   */
MMC_Write_IT(MMC_HandleTypeDef * hmmc)3897 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
3898 {
3899   uint32_t count;
3900   uint32_t data;
3901   const uint8_t *tmp;
3902 
3903   tmp = hmmc->pTxBuffPtr;
3904 
3905   if (hmmc->TxXferSize >= SDMMC_FIFO_SIZE)
3906   {
3907     /* Write data to SDMMC Tx FIFO */
3908     for (count = 0U; count < (SDMMC_FIFO_SIZE / 4U); count++)
3909     {
3910       data = (uint32_t)(*tmp);
3911       tmp++;
3912       data |= ((uint32_t)(*tmp) << 8U);
3913       tmp++;
3914       data |= ((uint32_t)(*tmp) << 16U);
3915       tmp++;
3916       data |= ((uint32_t)(*tmp) << 24U);
3917       tmp++;
3918       (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
3919     }
3920 
3921     hmmc->pTxBuffPtr = tmp;
3922     hmmc->TxXferSize -= SDMMC_FIFO_SIZE;
3923   }
3924 }
3925 
3926 /**
3927   * @brief  Switches the MMC card to high speed mode.
3928   * @param  hmmc: MMC handle
3929   * @param  state: State of high speed mode
3930   * @retval MMC Card error state
3931   */
MMC_HighSpeed(MMC_HandleTypeDef * hmmc,FunctionalState state)3932 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state)
3933 {
3934   uint32_t errorstate = HAL_MMC_ERROR_NONE;
3935   uint32_t response = 0U;
3936   uint32_t count;
3937   uint32_t sdmmc_clk;
3938   SDMMC_InitTypeDef Init;
3939 
3940   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) && (state == DISABLE))
3941   {
3942     errorstate = MMC_PwrClassUpdate(hmmc, (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS), SDMMC_SPEED_MODE_DEFAULT);
3943     if (errorstate == HAL_MMC_ERROR_NONE)
3944     {
3945       /* Index : 185 - Value : 0 */
3946       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90000U);
3947     }
3948   }
3949 
3950   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) == 0U) && (state != DISABLE))
3951   {
3952     errorstate = MMC_PwrClassUpdate(hmmc, (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS), SDMMC_SPEED_MODE_HIGH);
3953     if (errorstate == HAL_MMC_ERROR_NONE)
3954     {
3955       /* Index : 185 - Value : 1 */
3956       errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90100U);
3957     }
3958   }
3959 
3960   if (errorstate == HAL_MMC_ERROR_NONE)
3961   {
3962     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3963     count = SDMMC_MAX_TRIAL;
3964     do
3965     {
3966       errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3967       if (errorstate != HAL_MMC_ERROR_NONE)
3968       {
3969         break;
3970       }
3971 
3972       /* Get command response */
3973       response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3974       count--;
3975     } while (((response & 0x100U) == 0U) && (count != 0U));
3976 
3977     /* Check the status after the switch command execution */
3978     if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
3979     {
3980       /* Check the bit SWITCH_ERROR of the device status */
3981       if ((response & 0x80U) != 0U)
3982       {
3983         errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3984       }
3985       else
3986       {
3987         /* Configure high speed */
3988         Init.ClockEdge           = hmmc->Init.ClockEdge;
3989         Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
3990         Init.BusWide             = (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS);
3991         Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
3992 
3993         if (state == DISABLE)
3994         {
3995           Init.ClockDiv = hmmc->Init.ClockDiv;
3996           (void)SDMMC_Init(hmmc->Instance, Init);
3997 
3998           CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
3999         }
4000         else
4001         {
4002           /* High Speed Clock should be less or equal to 52MHz*/
4003           if (hmmc->Instance == SDMMC1)
4004           {
4005             sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC1);
4006           }
4007 #if defined (SDMMC2)
4008           else if (hmmc->Instance == SDMMC2)
4009           {
4010             sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC2);
4011           }
4012 #endif  /* SDMMC2 */
4013           else
4014           {
4015             sdmmc_clk = 0;
4016           }
4017 
4018           if (sdmmc_clk == 0U)
4019           {
4020             errorstate = SDMMC_ERROR_INVALID_PARAMETER;
4021           }
4022           else
4023           {
4024             if (sdmmc_clk <= MMC_HIGH_SPEED_FREQ)
4025             {
4026               Init.ClockDiv = 0;
4027             }
4028             else
4029             {
4030               Init.ClockDiv = (sdmmc_clk / (2U * MMC_HIGH_SPEED_FREQ)) + 1U;
4031             }
4032             (void)SDMMC_Init(hmmc->Instance, Init);
4033 
4034             SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
4035           }
4036         }
4037       }
4038     }
4039     else if (count == 0U)
4040     {
4041       errorstate = SDMMC_ERROR_TIMEOUT;
4042     }
4043     else
4044     {
4045       /* Nothing to do */
4046     }
4047   }
4048 
4049   return errorstate;
4050 }
4051 
4052 /**
4053   * @brief  Switches the MMC card to Double Data Rate (DDR) mode.
4054   * @param  hmmc: MMC handle
4055   * @param  state: State of DDR mode
4056   * @retval MMC Card error state
4057   */
MMC_DDR_Mode(MMC_HandleTypeDef * hmmc,FunctionalState state)4058 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state)
4059 {
4060   uint32_t errorstate = HAL_MMC_ERROR_NONE;
4061   uint32_t response = 0U;
4062   uint32_t count;
4063 
4064   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) && (state == DISABLE))
4065   {
4066     if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
4067     {
4068       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_4B, SDMMC_SPEED_MODE_HIGH);
4069       if (errorstate == HAL_MMC_ERROR_NONE)
4070       {
4071         /* Index : 183 - Value : 1 */
4072         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
4073       }
4074     }
4075     else
4076     {
4077       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_8B, SDMMC_SPEED_MODE_HIGH);
4078       if (errorstate == HAL_MMC_ERROR_NONE)
4079       {
4080         /* Index : 183 - Value : 2 */
4081         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
4082       }
4083     }
4084   }
4085 
4086   if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) == 0U) && (state != DISABLE))
4087   {
4088     if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
4089     {
4090       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_4B, SDMMC_SPEED_MODE_DDR);
4091       if (errorstate == HAL_MMC_ERROR_NONE)
4092       {
4093         /* Index : 183 - Value : 5 */
4094         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70500U);
4095       }
4096     }
4097     else
4098     {
4099       errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_8B, SDMMC_SPEED_MODE_DDR);
4100       if (errorstate == HAL_MMC_ERROR_NONE)
4101       {
4102         /* Index : 183 - Value : 6 */
4103         errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70600U);
4104       }
4105     }
4106   }
4107 
4108   if (errorstate == HAL_MMC_ERROR_NONE)
4109   {
4110     /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
4111     count = SDMMC_MAX_TRIAL;
4112     do
4113     {
4114       errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
4115       if (errorstate != HAL_MMC_ERROR_NONE)
4116       {
4117         break;
4118       }
4119 
4120       /* Get command response */
4121       response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
4122       count--;
4123     } while (((response & 0x100U) == 0U) && (count != 0U));
4124 
4125     /* Check the status after the switch command execution */
4126     if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
4127     {
4128       /* Check the bit SWITCH_ERROR of the device status */
4129       if ((response & 0x80U) != 0U)
4130       {
4131         errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
4132       }
4133       else
4134       {
4135         /* Configure DDR mode */
4136         if (state == DISABLE)
4137         {
4138           CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
4139         }
4140         else
4141         {
4142           SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
4143         }
4144       }
4145     }
4146     else if (count == 0U)
4147     {
4148       errorstate = SDMMC_ERROR_TIMEOUT;
4149     }
4150     else
4151     {
4152       /* Nothing to do */
4153     }
4154   }
4155 
4156   return errorstate;
4157 }
4158 
4159 /**
4160   * @brief  Update the power class of the device.
4161   * @param  hmmc MMC handle
4162   * @param  Wide Wide of MMC bus
4163   * @param  Speed Speed of the MMC bus
4164   * @retval MMC Card error state
4165   */
MMC_PwrClassUpdate(MMC_HandleTypeDef * hmmc,uint32_t Wide,uint32_t Speed)4166 static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide, uint32_t Speed)
4167 {
4168   uint32_t count;
4169   uint32_t response = 0U;
4170   uint32_t errorstate = HAL_MMC_ERROR_NONE;
4171   uint32_t power_class;
4172   uint32_t supported_pwr_class;
4173 
4174   if ((Wide == SDMMC_BUS_WIDE_8B) || (Wide == SDMMC_BUS_WIDE_4B))
4175   {
4176     power_class = 0U; /* Default value after power-on or software reset */
4177 
4178     /* Read the PowerClass field of the Extended CSD register */
4179     if (MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */
4180     {
4181       errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
4182     }
4183     else
4184     {
4185       power_class = ((power_class >> 24U) & 0x000000FFU);
4186     }
4187 
4188     /* Get the supported PowerClass field of the Extended CSD register */
4189     if (Speed == SDMMC_SPEED_MODE_DDR)
4190     {
4191       /* Field PWR_CL_DDR_52_xxx [238 or 239] */
4192       supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_DDR_52_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_DDR_52_POS) &
4193                              0x000000FFU);
4194     }
4195     else if (Speed == SDMMC_SPEED_MODE_HIGH)
4196     {
4197       /* Field PWR_CL_52_xxx [200 or 202] */
4198       supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_52_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_52_POS) &
4199                              0x000000FFU);
4200     }
4201     else
4202     {
4203       /* Field PWR_CL_26_xxx [201 or 203] */
4204       supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_26_POS) &
4205                              0x000000FFU);
4206     }
4207 
4208     if (errorstate == HAL_MMC_ERROR_NONE)
4209     {
4210       if (Wide == SDMMC_BUS_WIDE_8B)
4211       {
4212         /* Bit [7:4]: power class for 8-bits bus configuration - Bit [3:0]: power class for 4-bits bus configuration */
4213         supported_pwr_class = (supported_pwr_class >> 4U);
4214       }
4215 
4216       if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU))
4217       {
4218         /* Need to change current power class */
4219         errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U)));
4220 
4221         if (errorstate == HAL_MMC_ERROR_NONE)
4222         {
4223           /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
4224           count = SDMMC_MAX_TRIAL;
4225           do
4226           {
4227             errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
4228             if (errorstate != HAL_MMC_ERROR_NONE)
4229             {
4230               break;
4231             }
4232 
4233             /* Get command response */
4234             response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
4235             count--;
4236           } while (((response & 0x100U) == 0U) && (count != 0U));
4237 
4238           /* Check the status after the switch command execution */
4239           if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
4240           {
4241             /* Check the bit SWITCH_ERROR of the device status */
4242             if ((response & 0x80U) != 0U)
4243             {
4244               errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
4245             }
4246           }
4247           else if (count == 0U)
4248           {
4249             errorstate = SDMMC_ERROR_TIMEOUT;
4250           }
4251           else
4252           {
4253             /* Nothing to do */
4254           }
4255         }
4256       }
4257     }
4258   }
4259 
4260   return errorstate;
4261 }
4262 
4263 /**
4264   * @brief Read DMA Linked list node Transfer completed callbacks
4265   * @param hmmc: MMC handle
4266   * @retval None
4267   */
HAL_MMCEx_Read_DMALnkLstBufCpltCallback(MMC_HandleTypeDef * hmmc)4268 __weak void HAL_MMCEx_Read_DMALnkLstBufCpltCallback(MMC_HandleTypeDef *hmmc)
4269 {
4270   /* Prevent unused argument(s) compilation warning */
4271   UNUSED(hmmc);
4272 
4273   /* NOTE : This function should not be modified, when the callback is needed,
4274             the HAL_MMCEx_Read_DMALnkLstBufCpltCallback can be implemented in the user file
4275    */
4276 }
4277 /**
4278   * @brief Read DMA Linked list node Transfer completed callbacks
4279   * @param hmmc: MMC handle
4280   * @retval None
4281   */
HAL_MMCEx_Write_DMALnkLstBufCpltCallback(MMC_HandleTypeDef * hmmc)4282 __weak void HAL_MMCEx_Write_DMALnkLstBufCpltCallback(MMC_HandleTypeDef *hmmc)
4283 {
4284   /* Prevent unused argument(s) compilation warning */
4285   UNUSED(hmmc);
4286 
4287   /* NOTE : This function should not be modified, when the callback is needed,
4288             the HAL_MMCEx_Write_DMALnkLstBufCpltCallback can be implemented in the user file
4289    */
4290 }
4291 
4292 /**
4293   * @}
4294   */
4295 
4296 #endif /* HAL_MMC_MODULE_ENABLED */
4297 #endif /* SDMMC1 || SDMMC2 */
4298 
4299 /**
4300   * @}
4301   */
4302 
4303 /**
4304   * @}
4305   */
4306