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