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