Updated and Validated
[betaflight.git] / lib / main / STM32F7 / Drivers / STM32F7xx_HAL_Driver / Src / stm32f7xx_hal_mmc.c
blobe0e44fcdbb888eab47255a2cbcb005b78514a624
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
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.
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:
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 functions
42 HAL_NVIC_SetPriority(); 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
51 HAL_NVIC_SetPriority();
52 (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
53 (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
54 and __HAL_MMC_DISABLE_IT() inside the communication process.
55 (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
56 and __HAL_MMC_CLEAR_IT()
57 (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
60 *** MMC Card Initialization and configuration ***
61 ================================================
62 [..]
63 To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
64 SDMMC IP (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
65 This function provide the following operations:
67 (#) Initialize the SDMMC peripheral interface with defaullt configuration.
68 The initialization process is done at 400KHz. You can change or adapt
69 this frequency by adjusting the "ClockDiv" field.
70 The MMC Card frequency (SDMMC_CK) is computed as follows:
72 SDMMC_CK = SDMMCCLK / (ClockDiv + 2)
74 In initialization mode and according to the MMC Card standard,
75 make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
77 This phase of initialization is done through SDMMC_Init() and
78 SDMMC_PowerState_ON() SDMMC low level APIs.
80 (#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
81 This phase allows the card initialization and identification
82 and check the MMC Card type (Standard Capacity or High Capacity)
83 The initialization flow is compatible with MMC standard.
85 This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
86 of plug-off plug-in.
88 (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
89 frequency is set to 24MHz. You can change or adapt this frequency by adjusting
90 the "ClockDiv" field.
91 In transfer mode and according to the MMC Card standard, make sure that the
92 SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
93 To be able to use a frequency higher than 24MHz, you should use the SDMMC
94 peripheral in bypass mode. Refer to the corresponding reference manual
95 for more details.
97 (#) Select the corresponding MMC Card according to the address read with the step 2.
99 (#) Configure the MMC Card in wide bus mode: 4-bits data.
101 *** MMC Card Read operation ***
102 ==============================
103 [..]
104 (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
105 This function allows the read of 512 bytes blocks.
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.
111 (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
112 This function allows the read of 512 bytes blocks.
113 You can choose either one block read operation or multiple block read operation
114 by adjusting the "NumberOfBlocks" parameter.
115 After this, you have to ensure that the transfer is done correctly. The check is done
116 through HAL_MMC_GetCardState() function for MMC card state.
117 You could also check the DMA transfer process through the MMC Rx interrupt event.
119 (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
120 This function allows the read of 512 bytes blocks.
121 You can choose either one block read operation or multiple block read operation
122 by adjusting the "NumberOfBlocks" parameter.
123 After this, you have to ensure that the transfer is done correctly. The check is done
124 through HAL_MMC_GetCardState() function for MMC card state.
125 You could also check the IT transfer process through the MMC Rx interrupt event.
127 *** MMC Card Write operation ***
128 ===============================
129 [..]
130 (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
131 This function allows the read of 512 bytes blocks.
132 You can choose either one block read operation or multiple block read operation
133 by adjusting the "NumberOfBlocks" parameter.
134 After this, you have to ensure that the transfer is done correctly. The check is done
135 through HAL_MMC_GetCardState() function for MMC card state.
137 (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
138 This function allows the read of 512 bytes blocks.
139 You can choose either one block read operation or multiple block read operation
140 by adjusting the "NumberOfBlocks" parameter.
141 After this, you have to ensure that the transfer is done correctly. The check is done
142 through HAL_MMC_GetCardState() function for MMC card state.
143 You could also check the DMA transfer process through the MMC Tx interrupt event.
145 (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
146 This function allows the read of 512 bytes blocks.
147 You can choose either one block read operation or multiple block read operation
148 by adjusting the "NumberOfBlocks" parameter.
149 After this, you have to ensure that the transfer is done correctly. The check is done
150 through HAL_MMC_GetCardState() function for MMC card state.
151 You could also check the IT transfer process through the MMC Tx interrupt event.
153 *** MMC card information ***
154 ===========================
155 [..]
156 (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
157 It returns useful information about the MMC card such as block size, card type,
158 block number ...
160 *** MMC card CSD register ***
161 ============================
162 [..]
163 (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
164 Some of the CSD parameters are useful for card initialization and identification.
166 *** MMC card CID register ***
167 ============================
168 [..]
169 (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
170 Some of the CID parameters are useful for card initialization and identification.
172 *** MMC HAL driver macros list ***
173 ==================================
174 [..]
175 Below the list of most used macros in MMC HAL driver.
177 (+) __HAL_MMC_ENABLE : Enable the MMC device
178 (+) __HAL_MMC_DISABLE : Disable the MMC device
179 (+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer
180 (+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer
181 (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
182 (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
183 (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
184 (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
186 [..]
187 (@) You can refer to the MMC HAL driver header file for more useful macros
189 *** Callback registration ***
190 =============================================
191 [..]
192 The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
193 allows the user to configure dynamically the driver callbacks.
195 Use Functions @ref HAL_MMC_RegisterCallback() to register a user callback,
196 it allows to register following callbacks:
197 (+) TxCpltCallback : callback when a transmission transfer is completed.
198 (+) RxCpltCallback : callback when a reception transfer is completed.
199 (+) ErrorCallback : callback when error occurs.
200 (+) AbortCpltCallback : callback when abort is completed.
201 (+) MspInitCallback : MMC MspInit.
202 (+) MspDeInitCallback : MMC MspDeInit.
203 This function takes as parameters the HAL peripheral handle, the Callback ID
204 and a pointer to the user callback function.
206 Use function @ref HAL_MMC_UnRegisterCallback() to reset a callback to the default
207 weak (surcharged) function. It allows to reset following callbacks:
208 (+) TxCpltCallback : callback when a transmission transfer is completed.
209 (+) RxCpltCallback : callback when a reception transfer is completed.
210 (+) ErrorCallback : callback when error occurs.
211 (+) AbortCpltCallback : callback when abort is completed.
212 (+) MspInitCallback : MMC MspInit.
213 (+) MspDeInitCallback : MMC MspDeInit.
214 This function) takes as parameters the HAL peripheral handle and the Callback ID.
216 By default, after the @ref HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
217 all callbacks are reset to the corresponding legacy weak (surcharged) functions.
218 Exception done for MspInit and MspDeInit callbacks that are respectively
219 reset to the legacy weak (surcharged) functions in the @ref HAL_MMC_Init
220 and @ref HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
221 If not, MspInit or MspDeInit are not null, the @ref HAL_MMC_Init and @ref HAL_MMC_DeInit
222 keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
224 Callbacks can be registered/unregistered in READY state only.
225 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
226 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
227 during the Init/DeInit.
228 In that case first register the MspInit/MspDeInit user callbacks
229 using @ref HAL__RegisterCallback before calling @ref HAL_MMC_DeInit
230 or @ref HAL_MMC_Init function.
232 When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
233 not defined, the callback registering feature is not available
234 and weak (surcharged) callbacks are used.
235 @endverbatim
236 ******************************************************************************
237 * @attention
239 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
240 * All rights reserved.</center></h2>
242 * This software component is licensed by ST under BSD 3-Clause license,
243 * the "License"; You may not use this file except in compliance with the
244 * License. You may obtain a copy of the License at:
245 * opensource.org/licenses/BSD-3-Clause
247 ******************************************************************************
250 /* Includes ------------------------------------------------------------------*/
251 #include "stm32f7xx_hal.h"
253 /** @addtogroup STM32F7xx_HAL_Driver
254 * @{
257 /** @defgroup MMC MMC
258 * @brief MMC HAL module driver
259 * @{
262 #ifdef HAL_MMC_MODULE_ENABLED
264 /* Private typedef -----------------------------------------------------------*/
265 /* Private define ------------------------------------------------------------*/
266 /** @addtogroup MMC_Private_Defines
267 * @{
271 * @}
274 /* Private macro -------------------------------------------------------------*/
275 /* Private variables ---------------------------------------------------------*/
276 /* Private function prototypes -----------------------------------------------*/
277 /* Private functions ---------------------------------------------------------*/
278 /** @defgroup MMC_Private_Functions MMC Private Functions
279 * @{
281 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
282 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
283 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
284 static HAL_StatusTypeDef MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
285 static HAL_StatusTypeDef MMC_Write_IT(MMC_HandleTypeDef *hmmc);
286 static HAL_StatusTypeDef MMC_Read_IT(MMC_HandleTypeDef *hmmc);
287 static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma);
288 static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
289 static void MMC_DMAError(DMA_HandleTypeDef *hdma);
290 static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
291 static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
293 * @}
296 /* Exported functions --------------------------------------------------------*/
297 /** @addtogroup MMC_Exported_Functions
298 * @{
301 /** @addtogroup MMC_Exported_Functions_Group1
302 * @brief Initialization and de-initialization functions
304 @verbatim
305 ==============================================================================
306 ##### Initialization and de-initialization functions #####
307 ==============================================================================
308 [..]
309 This section provides functions allowing to initialize/de-initialize the MMC
310 card device to be ready for use.
312 @endverbatim
313 * @{
317 * @brief Initializes the MMC according to the specified parameters in the
318 MMC_HandleTypeDef and create the associated handle.
319 * @param hmmc Pointer to the MMC handle
320 * @retval HAL status
322 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
324 /* Check the MMC handle allocation */
325 if(hmmc == NULL)
327 return HAL_ERROR;
330 /* Check the parameters */
331 assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
332 assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge));
333 assert_param(IS_SDMMC_CLOCK_BYPASS(hmmc->Init.ClockBypass));
334 assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
335 assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide));
336 assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
337 assert_param(IS_SDMMC_CLKDIV(hmmc->Init.ClockDiv));
339 if(hmmc->State == HAL_MMC_STATE_RESET)
341 /* Allocate lock resource and initialize it */
342 hmmc->Lock = HAL_UNLOCKED;
343 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
344 /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
345 hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
346 hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
347 hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
348 hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
350 if(hmmc->MspInitCallback == NULL)
352 hmmc->MspInitCallback = HAL_MMC_MspInit;
355 /* Init the low level hardware */
356 hmmc->MspInitCallback(hmmc);
357 #else
358 /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
359 HAL_MMC_MspInit(hmmc);
360 #endif
363 hmmc->State = HAL_MMC_STATE_BUSY;
365 /* Initialize the Card parameters */
366 HAL_MMC_InitCard(hmmc);
368 /* Initialize the error code */
369 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
371 /* Initialize the MMC operation */
372 hmmc->Context = MMC_CONTEXT_NONE;
374 /* Initialize the MMC state */
375 hmmc->State = HAL_MMC_STATE_READY;
377 return HAL_OK;
381 * @brief Initializes the MMC Card.
382 * @param hmmc Pointer to MMC handle
383 * @note This function initializes the MMC card. It could be used when a card
384 re-initialization is needed.
385 * @retval HAL status
387 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
389 uint32_t errorstate = HAL_MMC_ERROR_NONE;
390 MMC_InitTypeDef Init;
392 /* Default SDMMC peripheral configuration for MMC card initialization */
393 Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
394 Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
395 Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
396 Init.BusWide = SDMMC_BUS_WIDE_1B;
397 Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
398 Init.ClockDiv = SDMMC_INIT_CLK_DIV;
400 /* Initialize SDMMC peripheral interface with default configuration */
401 SDMMC_Init(hmmc->Instance, Init);
403 /* Disable SDMMC Clock */
404 __HAL_MMC_DISABLE(hmmc);
406 /* Set Power State to ON */
407 SDMMC_PowerState_ON(hmmc->Instance);
409 /* Enable MMC Clock */
410 __HAL_MMC_ENABLE(hmmc);
412 /* Required power up waiting time before starting the SD initialization sequence */
413 HAL_Delay(2);
415 /* Identify card operating voltage */
416 errorstate = MMC_PowerON(hmmc);
417 if(errorstate != HAL_MMC_ERROR_NONE)
419 hmmc->State = HAL_MMC_STATE_READY;
420 hmmc->ErrorCode |= errorstate;
421 return HAL_ERROR;
424 /* Card initialization */
425 errorstate = MMC_InitCard(hmmc);
426 if(errorstate != HAL_MMC_ERROR_NONE)
428 hmmc->State = HAL_MMC_STATE_READY;
429 hmmc->ErrorCode |= errorstate;
430 return HAL_ERROR;
433 return HAL_OK;
437 * @brief De-Initializes the MMC card.
438 * @param hmmc Pointer to MMC handle
439 * @retval HAL status
441 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
443 /* Check the MMC handle allocation */
444 if(hmmc == NULL)
446 return HAL_ERROR;
449 /* Check the parameters */
450 assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
452 hmmc->State = HAL_MMC_STATE_BUSY;
454 /* Set MMC power state to off */
455 MMC_PowerOFF(hmmc);
457 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
458 if(hmmc->MspDeInitCallback == NULL)
460 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
463 /* DeInit the low level hardware */
464 hmmc->MspDeInitCallback(hmmc);
465 #else
466 /* De-Initialize the MSP layer */
467 HAL_MMC_MspDeInit(hmmc);
468 #endif
470 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
471 hmmc->State = HAL_MMC_STATE_RESET;
473 return HAL_OK;
478 * @brief Initializes the MMC MSP.
479 * @param hmmc Pointer to MMC handle
480 * @retval None
482 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
484 /* Prevent unused argument(s) compilation warning */
485 UNUSED(hmmc);
487 /* NOTE : This function Should not be modified, when the callback is needed,
488 the HAL_MMC_MspInit could be implemented in the user file
493 * @brief De-Initialize MMC MSP.
494 * @param hmmc Pointer to MMC handle
495 * @retval None
497 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
499 /* Prevent unused argument(s) compilation warning */
500 UNUSED(hmmc);
502 /* NOTE : This function Should not be modified, when the callback is needed,
503 the HAL_MMC_MspDeInit could be implemented in the user file
508 * @}
511 /** @addtogroup MMC_Exported_Functions_Group2
512 * @brief Data transfer functions
514 @verbatim
515 ==============================================================================
516 ##### IO operation functions #####
517 ==============================================================================
518 [..]
519 This subsection provides a set of functions allowing to manage the data
520 transfer from/to MMC card.
522 @endverbatim
523 * @{
527 * @brief Reads block(s) from a specified address in a card. The Data transfer
528 * is managed by polling mode.
529 * @note This API should be followed by a check on the card state through
530 * HAL_MMC_GetCardState().
531 * @param hmmc Pointer to MMC handle
532 * @param pData pointer to the buffer that will contain the received data
533 * @param BlockAdd Block Address from where data is to be read
534 * @param NumberOfBlocks Number of MMC blocks to read
535 * @param Timeout Specify timeout value
536 * @retval HAL status
538 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
540 SDMMC_DataInitTypeDef config;
541 uint32_t errorstate = HAL_MMC_ERROR_NONE;
542 uint32_t tickstart = HAL_GetTick();
543 uint32_t count = 0, *tempbuff = (uint32_t *)pData;
545 if(NULL == pData)
547 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
548 return HAL_ERROR;
551 if(hmmc->State == HAL_MMC_STATE_READY)
553 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
555 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
557 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
558 return HAL_ERROR;
561 hmmc->State = HAL_MMC_STATE_BUSY;
563 /* Initialize data control register */
564 hmmc->Instance->DCTRL = 0;
566 /* Check the Card capacity in term of Logical number of blocks */
567 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
569 BlockAdd *= 512;
572 /* Set Block Size for Card */
573 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
574 if(errorstate != HAL_MMC_ERROR_NONE)
576 /* Clear all the static flags */
577 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
578 hmmc->ErrorCode |= errorstate;
579 hmmc->State = HAL_MMC_STATE_READY;
580 return HAL_ERROR;
583 /* Configure the MMC DPSM (Data Path State Machine) */
584 config.DataTimeOut = SDMMC_DATATIMEOUT;
585 config.DataLength = NumberOfBlocks * BLOCKSIZE;
586 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
587 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
588 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
589 config.DPSM = SDMMC_DPSM_ENABLE;
590 SDMMC_ConfigData(hmmc->Instance, &config);
592 /* Read block(s) in polling mode */
593 if(NumberOfBlocks > 1)
595 hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
597 /* Read Multi Block command */
598 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, BlockAdd);
600 else
602 hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
604 /* Read Single Block command */
605 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, BlockAdd);
607 if(errorstate != HAL_MMC_ERROR_NONE)
609 /* Clear all the static flags */
610 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
611 hmmc->ErrorCode |= errorstate;
612 hmmc->State = HAL_MMC_STATE_READY;
613 return HAL_ERROR;
616 /* Poll on SDMMC flags */
617 while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
619 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
621 /* Read data from SDMMC Rx FIFO */
622 for(count = 0U; count < 8U; count++)
624 *(tempbuff + count) = SDMMC_ReadFIFO(hmmc->Instance);
626 tempbuff += 8U;
629 if((Timeout == 0U)||((HAL_GetTick()-tickstart) >= Timeout))
631 /* Clear all the static flags */
632 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
633 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
634 hmmc->State= HAL_MMC_STATE_READY;
635 return HAL_TIMEOUT;
639 /* Send stop transmission command in case of multiblock read */
640 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
642 /* Send stop transmission command */
643 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
644 if(errorstate != HAL_MMC_ERROR_NONE)
646 /* Clear all the static flags */
647 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
648 hmmc->ErrorCode |= errorstate;
649 hmmc->State = HAL_MMC_STATE_READY;
650 return HAL_ERROR;
654 /* Get error state */
655 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
657 /* Clear all the static flags */
658 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
659 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
660 hmmc->State = HAL_MMC_STATE_READY;
661 return HAL_ERROR;
663 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
665 /* Clear all the static flags */
666 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
667 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
668 hmmc->State = HAL_MMC_STATE_READY;
669 return HAL_ERROR;
671 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
673 /* Clear all the static flags */
674 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
675 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
676 hmmc->State = HAL_MMC_STATE_READY;
677 return HAL_ERROR;
680 /* Empty FIFO if there is still any data */
681 while ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXDAVL)))
683 *tempbuff = SDMMC_ReadFIFO(hmmc->Instance);
684 tempbuff++;
686 if((Timeout == 0U)||((HAL_GetTick()-tickstart) >= Timeout))
688 /* Clear all the static flags */
689 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
690 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
691 hmmc->State= HAL_MMC_STATE_READY;
692 return HAL_ERROR;
696 /* Clear all the static flags */
697 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
699 hmmc->State = HAL_MMC_STATE_READY;
701 return HAL_OK;
703 else
705 hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
706 return HAL_ERROR;
711 * @brief Allows to write block(s) to a specified address in a card. The Data
712 * transfer is managed by polling mode.
713 * @note This API should be followed by a check on the card state through
714 * HAL_MMC_GetCardState().
715 * @param hmmc Pointer to MMC handle
716 * @param pData pointer to the buffer that will contain the data to transmit
717 * @param BlockAdd Block Address where data will be written
718 * @param NumberOfBlocks Number of MMC blocks to write
719 * @param Timeout Specify timeout value
720 * @retval HAL status
722 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
724 SDMMC_DataInitTypeDef config;
725 uint32_t errorstate = HAL_MMC_ERROR_NONE;
726 uint32_t tickstart = HAL_GetTick();
727 uint32_t count = 0;
728 uint32_t *tempbuff = (uint32_t *)pData;
730 if(NULL == pData)
732 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
733 return HAL_ERROR;
736 if(hmmc->State == HAL_MMC_STATE_READY)
738 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
740 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
742 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
743 return HAL_ERROR;
746 hmmc->State = HAL_MMC_STATE_BUSY;
748 /* Initialize data control register */
749 hmmc->Instance->DCTRL = 0;
751 /* Check the Card capacity in term of Logical number of blocks */
752 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
754 BlockAdd *= 512;
757 /* Set Block Size for Card */
758 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
759 if(errorstate != HAL_MMC_ERROR_NONE)
761 /* Clear all the static flags */
762 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
763 hmmc->ErrorCode |= errorstate;
764 hmmc->State = HAL_MMC_STATE_READY;
765 return HAL_ERROR;
768 /* Write Blocks in Polling mode */
769 if(NumberOfBlocks > 1U)
771 hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
773 /* Write Multi Block command */
774 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, BlockAdd);
776 else
778 hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
780 /* Write Single Block command */
781 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, BlockAdd);
783 if(errorstate != HAL_MMC_ERROR_NONE)
785 /* Clear all the static flags */
786 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
787 hmmc->ErrorCode |= errorstate;
788 hmmc->State = HAL_MMC_STATE_READY;
789 return HAL_ERROR;
792 /* Configure the MMC DPSM (Data Path State Machine) */
793 config.DataTimeOut = SDMMC_DATATIMEOUT;
794 config.DataLength = NumberOfBlocks * BLOCKSIZE;
795 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
796 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
797 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
798 config.DPSM = SDMMC_DPSM_ENABLE;
799 SDMMC_ConfigData(hmmc->Instance, &config);
801 /* Write block(s) in polling mode */
802 while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
804 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE))
806 /* Write data to SDMMC Tx FIFO */
807 for(count = 0U; count < 8U; count++)
809 SDMMC_WriteFIFO(hmmc->Instance, (tempbuff + count));
811 tempbuff += 8U;
814 if((Timeout == 0U)||((HAL_GetTick()-tickstart) >= Timeout))
816 /* Clear all the static flags */
817 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
818 hmmc->ErrorCode |= errorstate;
819 hmmc->State = HAL_MMC_STATE_READY;
820 return HAL_TIMEOUT;
824 /* Send stop transmission command in case of multiblock write */
825 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
827 /* Send stop transmission command */
828 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
829 if(errorstate != HAL_MMC_ERROR_NONE)
831 /* Clear all the static flags */
832 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
833 hmmc->ErrorCode |= errorstate;
834 hmmc->State = HAL_MMC_STATE_READY;
835 return HAL_ERROR;
839 /* Get error state */
840 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
842 /* Clear all the static flags */
843 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
844 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
845 hmmc->State = HAL_MMC_STATE_READY;
846 return HAL_ERROR;
848 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
850 /* Clear all the static flags */
851 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
852 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
853 hmmc->State = HAL_MMC_STATE_READY;
854 return HAL_ERROR;
856 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR))
858 /* Clear all the static flags */
859 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
860 hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
861 hmmc->State = HAL_MMC_STATE_READY;
862 return HAL_ERROR;
865 /* Clear all the static flags */
866 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
868 hmmc->State = HAL_MMC_STATE_READY;
870 return HAL_OK;
872 else
874 hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
875 return HAL_ERROR;
880 * @brief Reads block(s) from a specified address in a card. The Data transfer
881 * is managed in interrupt mode.
882 * @note This API should be followed by a check on the card state through
883 * HAL_MMC_GetCardState().
884 * @note You could also check the IT transfer process through the MMC Rx
885 * interrupt event.
886 * @param hmmc Pointer to MMC handle
887 * @param pData Pointer to the buffer that will contain the received data
888 * @param BlockAdd Block Address from where data is to be read
889 * @param NumberOfBlocks Number of blocks to read.
890 * @retval HAL status
892 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
894 SDMMC_DataInitTypeDef config;
895 uint32_t errorstate = HAL_MMC_ERROR_NONE;
897 if(NULL == pData)
899 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
900 return HAL_ERROR;
903 if(hmmc->State == HAL_MMC_STATE_READY)
905 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
907 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
909 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
910 return HAL_ERROR;
913 hmmc->State = HAL_MMC_STATE_BUSY;
915 /* Initialize data control register */
916 hmmc->Instance->DCTRL = 0U;
918 hmmc->pRxBuffPtr = (uint32_t *)pData;
919 hmmc->RxXferSize = BLOCKSIZE * NumberOfBlocks;
921 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_FLAG_RXFIFOHF));
923 /* Check the Card capacity in term of Logical number of blocks */
924 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
926 BlockAdd *= 512;
929 /* Configure the MMC DPSM (Data Path State Machine) */
930 config.DataTimeOut = SDMMC_DATATIMEOUT;
931 config.DataLength = BLOCKSIZE * NumberOfBlocks;
932 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
933 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
934 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
935 config.DPSM = SDMMC_DPSM_ENABLE;
936 SDMMC_ConfigData(hmmc->Instance, &config);
938 /* Set Block Size for Card */
939 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
940 if(errorstate != HAL_MMC_ERROR_NONE)
942 /* Clear all the static flags */
943 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
944 hmmc->ErrorCode |= errorstate;
945 hmmc->State = HAL_MMC_STATE_READY;
946 return HAL_ERROR;
949 /* Read Blocks in IT mode */
950 if(NumberOfBlocks > 1U)
952 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
954 /* Read Multi Block command */
955 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, BlockAdd);
957 else
959 hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
961 /* Read Single Block command */
962 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, BlockAdd);
964 if(errorstate != HAL_MMC_ERROR_NONE)
966 /* Clear all the static flags */
967 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
968 hmmc->ErrorCode |= errorstate;
969 hmmc->State = HAL_MMC_STATE_READY;
970 return HAL_ERROR;
973 return HAL_OK;
975 else
977 return HAL_BUSY;
982 * @brief Writes block(s) to a specified address in a card. The Data transfer
983 * is managed in interrupt mode.
984 * @note This API should be followed by a check on the card state through
985 * HAL_MMC_GetCardState().
986 * @note You could also check the IT transfer process through the MMC Tx
987 * interrupt event.
988 * @param hmmc Pointer to MMC handle
989 * @param pData Pointer to the buffer that will contain the data to transmit
990 * @param BlockAdd Block Address where data will be written
991 * @param NumberOfBlocks Number of blocks to write
992 * @retval HAL status
994 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
996 SDMMC_DataInitTypeDef config;
997 uint32_t errorstate = HAL_MMC_ERROR_NONE;
999 if(NULL == pData)
1001 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1002 return HAL_ERROR;
1005 if(hmmc->State == HAL_MMC_STATE_READY)
1007 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1009 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1011 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1012 return HAL_ERROR;
1015 hmmc->State = HAL_MMC_STATE_BUSY;
1017 /* Initialize data control register */
1018 hmmc->Instance->DCTRL = 0U;
1020 hmmc->pTxBuffPtr = (uint32_t *)pData;
1021 hmmc->TxXferSize = BLOCKSIZE * NumberOfBlocks;
1023 /* Enable transfer interrupts */
1024 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_FLAG_TXFIFOHE));
1026 /* Check the Card capacity in term of Logical number of blocks */
1027 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
1029 BlockAdd *= 512;
1032 /* Set Block Size for Card */
1033 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
1034 if(errorstate != HAL_MMC_ERROR_NONE)
1036 /* Clear all the static flags */
1037 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1038 hmmc->ErrorCode |= errorstate;
1039 hmmc->State = HAL_MMC_STATE_READY;
1040 return HAL_ERROR;
1043 /* Write Blocks in Polling mode */
1044 if(NumberOfBlocks > 1U)
1046 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
1048 /* Write Multi Block command */
1049 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, BlockAdd);
1051 else
1053 hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
1055 /* Write Single Block command */
1056 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, BlockAdd);
1058 if(errorstate != HAL_MMC_ERROR_NONE)
1060 /* Clear all the static flags */
1061 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1062 hmmc->ErrorCode |= errorstate;
1063 hmmc->State = HAL_MMC_STATE_READY;
1064 return HAL_ERROR;
1067 /* Configure the MMC DPSM (Data Path State Machine) */
1068 config.DataTimeOut = SDMMC_DATATIMEOUT;
1069 config.DataLength = BLOCKSIZE * NumberOfBlocks;
1070 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1071 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
1072 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
1073 config.DPSM = SDMMC_DPSM_ENABLE;
1074 SDMMC_ConfigData(hmmc->Instance, &config);
1076 return HAL_OK;
1078 else
1080 return HAL_BUSY;
1085 * @brief Reads block(s) from a specified address in a card. The Data transfer
1086 * is managed by DMA mode.
1087 * @note This API should be followed by a check on the card state through
1088 * HAL_MMC_GetCardState().
1089 * @note You could also check the DMA transfer process through the MMC Rx
1090 * interrupt event.
1091 * @param hmmc Pointer MMC handle
1092 * @param pData Pointer to the buffer that will contain the received data
1093 * @param BlockAdd Block Address from where data is to be read
1094 * @param NumberOfBlocks Number of blocks to read.
1095 * @retval HAL status
1097 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1099 SDMMC_DataInitTypeDef config;
1100 uint32_t errorstate = HAL_MMC_ERROR_NONE;
1102 if(NULL == pData)
1104 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1105 return HAL_ERROR;
1108 if(hmmc->State == HAL_MMC_STATE_READY)
1110 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1112 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1114 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1115 return HAL_ERROR;
1118 hmmc->State = HAL_MMC_STATE_BUSY;
1120 /* Initialize data control register */
1121 hmmc->Instance->DCTRL = 0U;
1123 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
1125 /* Set the DMA transfer complete callback */
1126 hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt;
1128 /* Set the DMA error callback */
1129 hmmc->hdmarx->XferErrorCallback = MMC_DMAError;
1131 /* Set the DMA Abort callback */
1132 hmmc->hdmarx->XferAbortCallback = NULL;
1134 /* Enable the DMA Channel */
1135 HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4);
1137 /* Enable MMC DMA transfer */
1138 __HAL_MMC_DMA_ENABLE(hmmc);
1140 /* Check the Card capacity in term of Logical number of blocks */
1141 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
1143 BlockAdd *= 512;
1146 /* Configure the MMC DPSM (Data Path State Machine) */
1147 config.DataTimeOut = SDMMC_DATATIMEOUT;
1148 config.DataLength = BLOCKSIZE * NumberOfBlocks;
1149 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1150 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
1151 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
1152 config.DPSM = SDMMC_DPSM_ENABLE;
1153 SDMMC_ConfigData(hmmc->Instance, &config);
1155 /* Set Block Size for Card */
1156 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
1157 if(errorstate != HAL_MMC_ERROR_NONE)
1159 /* Clear all the static flags */
1160 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1161 hmmc->ErrorCode |= errorstate;
1162 hmmc->State = HAL_MMC_STATE_READY;
1163 return HAL_ERROR;
1166 /* Read Blocks in DMA mode */
1167 if(NumberOfBlocks > 1U)
1169 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1171 /* Read Multi Block command */
1172 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, BlockAdd);
1174 else
1176 hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1178 /* Read Single Block command */
1179 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, BlockAdd);
1181 if(errorstate != HAL_MMC_ERROR_NONE)
1183 /* Clear all the static flags */
1184 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1185 hmmc->ErrorCode |= errorstate;
1186 hmmc->State = HAL_MMC_STATE_READY;
1187 return HAL_ERROR;
1190 return HAL_OK;
1192 else
1194 return HAL_BUSY;
1199 * @brief Writes block(s) to a specified address in a card. The Data transfer
1200 * is managed by DMA mode.
1201 * @note This API should be followed by a check on the card state through
1202 * HAL_MMC_GetCardState().
1203 * @note You could also check the DMA transfer process through the MMC Tx
1204 * interrupt event.
1205 * @param hmmc Pointer to MMC handle
1206 * @param pData Pointer to the buffer that will contain the data to transmit
1207 * @param BlockAdd Block Address where data will be written
1208 * @param NumberOfBlocks Number of blocks to write
1209 * @retval HAL status
1211 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1213 SDMMC_DataInitTypeDef config;
1214 uint32_t errorstate = HAL_MMC_ERROR_NONE;
1216 if(NULL == pData)
1218 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1219 return HAL_ERROR;
1222 if(hmmc->State == HAL_MMC_STATE_READY)
1224 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1226 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1228 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1229 return HAL_ERROR;
1232 hmmc->State = HAL_MMC_STATE_BUSY;
1234 /* Initialize data control register */
1235 hmmc->Instance->DCTRL = 0U;
1237 /* Enable MMC Error interrupts */
1238 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR));
1240 /* Set the DMA transfer complete callback */
1241 hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt;
1243 /* Set the DMA error callback */
1244 hmmc->hdmatx->XferErrorCallback = MMC_DMAError;
1246 /* Set the DMA Abort callback */
1247 hmmc->hdmatx->XferAbortCallback = NULL;
1249 /* Check the Card capacity in term of Logical number of blocks */
1250 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
1252 BlockAdd *= 512;
1255 /* Set Block Size for Card */
1256 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, BLOCKSIZE);
1257 if(errorstate != HAL_MMC_ERROR_NONE)
1259 /* Clear all the static flags */
1260 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1261 hmmc->ErrorCode |= errorstate;
1262 hmmc->State = HAL_MMC_STATE_READY;
1263 return HAL_ERROR;
1266 /* Write Blocks in Polling mode */
1267 if(NumberOfBlocks > 1U)
1269 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1271 /* Write Multi Block command */
1272 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, BlockAdd);
1274 else
1276 hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1278 /* Write Single Block command */
1279 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, BlockAdd);
1281 if(errorstate != HAL_MMC_ERROR_NONE)
1283 /* Clear all the static flags */
1284 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1285 hmmc->ErrorCode |= errorstate;
1286 hmmc->State = HAL_MMC_STATE_READY;
1287 return HAL_ERROR;
1290 /* Enable SDMMC DMA transfer */
1291 __HAL_MMC_DMA_ENABLE(hmmc);
1293 /* Enable the DMA Channel */
1294 HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4);
1296 /* Configure the MMC DPSM (Data Path State Machine) */
1297 config.DataTimeOut = SDMMC_DATATIMEOUT;
1298 config.DataLength = BLOCKSIZE * NumberOfBlocks;
1299 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1300 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
1301 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
1302 config.DPSM = SDMMC_DPSM_ENABLE;
1303 SDMMC_ConfigData(hmmc->Instance, &config);
1305 return HAL_OK;
1307 else
1309 return HAL_BUSY;
1314 * @brief Erases the specified memory area of the given MMC card.
1315 * @note This API should be followed by a check on the card state through
1316 * HAL_MMC_GetCardState().
1317 * @param hmmc Pointer to MMC handle
1318 * @param BlockStartAdd Start Block address
1319 * @param BlockEndAdd End Block address
1320 * @retval HAL status
1322 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
1324 uint32_t errorstate = HAL_MMC_ERROR_NONE;
1326 if(hmmc->State == HAL_MMC_STATE_READY)
1328 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1330 if(BlockEndAdd < BlockStartAdd)
1332 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1333 return HAL_ERROR;
1336 if(BlockEndAdd > (hmmc->MmcCard.LogBlockNbr))
1338 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1339 return HAL_ERROR;
1342 hmmc->State = HAL_MMC_STATE_BUSY;
1344 /* Check if the card command class supports erase command */
1345 if(((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
1347 /* Clear all the static flags */
1348 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1349 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
1350 hmmc->State = HAL_MMC_STATE_READY;
1351 return HAL_ERROR;
1354 if((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
1356 /* Clear all the static flags */
1357 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1358 hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
1359 hmmc->State = HAL_MMC_STATE_READY;
1360 return HAL_ERROR;
1363 /* Check the Card capacity in term of Logical number of blocks */
1364 if ((hmmc->MmcCard.LogBlockNbr) < CAPACITY)
1366 BlockStartAdd *= 512U;
1367 BlockEndAdd *= 512U;
1370 /* Send CMD35 MMC_ERASE_GRP_START with argument as addr */
1371 errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, BlockStartAdd);
1372 if(errorstate != HAL_MMC_ERROR_NONE)
1374 /* Clear all the static flags */
1375 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1376 hmmc->ErrorCode |= errorstate;
1377 hmmc->State = HAL_MMC_STATE_READY;
1378 return HAL_ERROR;
1381 /* Send CMD36 MMC_ERASE_GRP_END with argument as addr */
1382 errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, BlockEndAdd);
1383 if(errorstate != HAL_MMC_ERROR_NONE)
1385 /* Clear all the static flags */
1386 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1387 hmmc->ErrorCode |= errorstate;
1388 hmmc->State = HAL_MMC_STATE_READY;
1389 return HAL_ERROR;
1392 /* Send CMD38 ERASE */
1393 errorstate = SDMMC_CmdErase(hmmc->Instance);
1394 if(errorstate != HAL_MMC_ERROR_NONE)
1396 /* Clear all the static flags */
1397 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1398 hmmc->ErrorCode |= errorstate;
1399 hmmc->State = HAL_MMC_STATE_READY;
1400 return HAL_ERROR;
1403 hmmc->State = HAL_MMC_STATE_READY;
1405 return HAL_OK;
1407 else
1409 return HAL_BUSY;
1414 * @brief This function handles MMC card interrupt request.
1415 * @param hmmc Pointer to MMC handle
1416 * @retval None
1418 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
1420 uint32_t errorstate = HAL_MMC_ERROR_NONE;
1422 /* Check for SDMMC interrupt flags */
1423 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DATAEND) != RESET)
1425 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND);
1427 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
1428 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
1430 if((hmmc->Context & MMC_CONTEXT_IT) != RESET)
1432 if(((hmmc->Context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != RESET) || ((hmmc->Context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != RESET))
1434 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1435 if(errorstate != HAL_MMC_ERROR_NONE)
1437 hmmc->ErrorCode |= errorstate;
1438 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1439 hmmc->ErrorCallback(hmmc);
1440 #else
1441 HAL_MMC_ErrorCallback(hmmc);
1442 #endif
1446 /* Clear all the static flags */
1447 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1449 hmmc->State = HAL_MMC_STATE_READY;
1450 if(((hmmc->Context & MMC_CONTEXT_READ_SINGLE_BLOCK) != RESET) || ((hmmc->Context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != RESET))
1452 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1453 hmmc->RxCpltCallback(hmmc);
1454 #else
1455 HAL_MMC_RxCpltCallback(hmmc);
1456 #endif
1458 else
1460 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1461 hmmc->TxCpltCallback(hmmc);
1462 #else
1463 HAL_MMC_TxCpltCallback(hmmc);
1464 #endif
1467 else if((hmmc->Context & MMC_CONTEXT_DMA) != RESET)
1469 if((hmmc->Context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != RESET)
1471 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1472 if(errorstate != HAL_MMC_ERROR_NONE)
1474 hmmc->ErrorCode |= errorstate;
1475 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1476 hmmc->ErrorCallback(hmmc);
1477 #else
1478 HAL_MMC_ErrorCallback(hmmc);
1479 #endif
1482 if(((hmmc->Context & MMC_CONTEXT_READ_SINGLE_BLOCK) == RESET) && ((hmmc->Context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == RESET))
1484 /* Disable the DMA transfer for transmit request by setting the DMAEN bit
1485 in the MMC DCTRL register */
1486 hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
1488 hmmc->State = HAL_MMC_STATE_READY;
1490 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1491 hmmc->TxCpltCallback(hmmc);
1492 #else
1493 HAL_MMC_TxCpltCallback(hmmc);
1494 #endif
1499 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXFIFOHE) != RESET)
1501 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE);
1503 MMC_Write_IT(hmmc);
1506 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXFIFOHF) != RESET)
1508 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF);
1510 MMC_Read_IT(hmmc);
1513 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_TXUNDERR) != RESET)
1515 /* Set Error code */
1516 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL) != RESET)
1518 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
1520 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DTIMEOUT) != RESET)
1522 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
1524 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXOVERR) != RESET)
1526 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
1528 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXUNDERR) != RESET)
1530 hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
1533 /* Clear All flags */
1534 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1536 /* Disable all interrupts */
1537 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
1538 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
1540 if((hmmc->Context & MMC_CONTEXT_DMA) != RESET)
1542 /* Abort the MMC DMA Streams */
1543 if(hmmc->hdmatx != NULL)
1545 /* Set the DMA Tx abort callback */
1546 hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
1547 /* Abort DMA in IT mode */
1548 if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
1550 MMC_DMATxAbort(hmmc->hdmatx);
1553 else if(hmmc->hdmarx != NULL)
1555 /* Set the DMA Rx abort callback */
1556 hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
1557 /* Abort DMA in IT mode */
1558 if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
1560 MMC_DMARxAbort(hmmc->hdmarx);
1563 else
1565 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1566 hmmc->State = HAL_MMC_STATE_READY;
1567 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1568 hmmc->AbortCpltCallback(hmmc);
1569 #else
1570 HAL_MMC_AbortCallback(hmmc);
1571 #endif
1574 else if((hmmc->Context & MMC_CONTEXT_IT) != RESET)
1576 /* Set the MMC state to ready to be able to start again the process */
1577 hmmc->State = HAL_MMC_STATE_READY;
1578 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1579 hmmc->ErrorCallback(hmmc);
1580 #else
1581 HAL_MMC_ErrorCallback(hmmc);
1582 #endif
1588 * @brief return the MMC state
1589 * @param hmmc Pointer to mmc handle
1590 * @retval HAL state
1592 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
1594 return hmmc->State;
1598 * @brief Return the MMC error code
1599 * @param hmmc Pointer to a MMC_HandleTypeDef structure that contains
1600 * the configuration information.
1601 * @retval MMC Error Code
1603 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
1605 return hmmc->ErrorCode;
1609 * @brief Tx Transfer completed callbacks
1610 * @param hmmc Pointer to MMC handle
1611 * @retval None
1613 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
1615 /* Prevent unused argument(s) compilation warning */
1616 UNUSED(hmmc);
1618 /* NOTE : This function should not be modified, when the callback is needed,
1619 the HAL_MMC_TxCpltCallback can be implemented in the user file
1624 * @brief Rx Transfer completed callbacks
1625 * @param hmmc Pointer MMC handle
1626 * @retval None
1628 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
1630 /* Prevent unused argument(s) compilation warning */
1631 UNUSED(hmmc);
1633 /* NOTE : This function should not be modified, when the callback is needed,
1634 the HAL_MMC_RxCpltCallback can be implemented in the user file
1639 * @brief MMC error callbacks
1640 * @param hmmc Pointer MMC handle
1641 * @retval None
1643 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
1645 /* Prevent unused argument(s) compilation warning */
1646 UNUSED(hmmc);
1648 /* NOTE : This function should not be modified, when the callback is needed,
1649 the HAL_MMC_ErrorCallback can be implemented in the user file
1654 * @brief MMC Abort callbacks
1655 * @param hmmc Pointer MMC handle
1656 * @retval None
1658 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
1660 /* Prevent unused argument(s) compilation warning */
1661 UNUSED(hmmc);
1663 /* NOTE : This function should not be modified, when the callback is needed,
1664 the HAL_MMC_ErrorCallback can be implemented in the user file
1668 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
1670 * @brief Register a User MMC Callback
1671 * To be used instead of the weak (surcharged) predefined callback
1672 * @param hmmc : MMC handle
1673 * @param CallbackID : ID of the callback to be registered
1674 * This parameter can be one of the following values:
1675 * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
1676 * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
1677 * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
1678 * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
1679 * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
1680 * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1681 * @param pCallback : pointer to the Callback function
1682 * @retval status
1684 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
1686 HAL_StatusTypeDef status = HAL_OK;
1688 if(pCallback == NULL)
1690 /* Update the error code */
1691 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1692 return HAL_ERROR;
1695 /* Process locked */
1696 __HAL_LOCK(hmmc);
1698 if(hmmc->State == HAL_MMC_STATE_READY)
1700 switch (CallbackId)
1702 case HAL_MMC_TX_CPLT_CB_ID :
1703 hmmc->TxCpltCallback = pCallback;
1704 break;
1705 case HAL_MMC_RX_CPLT_CB_ID :
1706 hmmc->RxCpltCallback = pCallback;
1707 break;
1708 case HAL_MMC_ERROR_CB_ID :
1709 hmmc->ErrorCallback = pCallback;
1710 break;
1711 case HAL_MMC_ABORT_CB_ID :
1712 hmmc->AbortCpltCallback = pCallback;
1713 break;
1714 case HAL_MMC_MSP_INIT_CB_ID :
1715 hmmc->MspInitCallback = pCallback;
1716 break;
1717 case HAL_MMC_MSP_DEINIT_CB_ID :
1718 hmmc->MspDeInitCallback = pCallback;
1719 break;
1720 default :
1721 /* Update the error code */
1722 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1723 /* update return status */
1724 status = HAL_ERROR;
1725 break;
1728 else if (hmmc->State == HAL_MMC_STATE_RESET)
1730 switch (CallbackId)
1732 case HAL_MMC_MSP_INIT_CB_ID :
1733 hmmc->MspInitCallback = pCallback;
1734 break;
1735 case HAL_MMC_MSP_DEINIT_CB_ID :
1736 hmmc->MspDeInitCallback = pCallback;
1737 break;
1738 default :
1739 /* Update the error code */
1740 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1741 /* update return status */
1742 status = HAL_ERROR;
1743 break;
1746 else
1748 /* Update the error code */
1749 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1750 /* update return status */
1751 status = HAL_ERROR;
1754 /* Release Lock */
1755 __HAL_UNLOCK(hmmc);
1756 return status;
1760 * @brief Unregister a User MMC Callback
1761 * MMC Callback is redirected to the weak (surcharged) predefined callback
1762 * @param hmmc : MMC handle
1763 * @param CallbackID : ID of the callback to be unregistered
1764 * This parameter can be one of the following values:
1765 * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
1766 * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
1767 * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
1768 * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
1769 * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
1770 * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1771 * @retval status
1773 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
1775 HAL_StatusTypeDef status = HAL_OK;
1777 /* Process locked */
1778 __HAL_LOCK(hmmc);
1780 if(hmmc->State == HAL_MMC_STATE_READY)
1782 switch (CallbackId)
1784 case HAL_MMC_TX_CPLT_CB_ID :
1785 hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
1786 break;
1787 case HAL_MMC_RX_CPLT_CB_ID :
1788 hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
1789 break;
1790 case HAL_MMC_ERROR_CB_ID :
1791 hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
1792 break;
1793 case HAL_MMC_ABORT_CB_ID :
1794 hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
1795 break;
1796 case HAL_MMC_MSP_INIT_CB_ID :
1797 hmmc->MspInitCallback = HAL_MMC_MspInit;
1798 break;
1799 case HAL_MMC_MSP_DEINIT_CB_ID :
1800 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1801 break;
1802 default :
1803 /* Update the error code */
1804 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1805 /* update return status */
1806 status = HAL_ERROR;
1807 break;
1810 else if (hmmc->State == HAL_MMC_STATE_RESET)
1812 switch (CallbackId)
1814 case HAL_MMC_MSP_INIT_CB_ID :
1815 hmmc->MspInitCallback = HAL_MMC_MspInit;
1816 break;
1817 case HAL_MMC_MSP_DEINIT_CB_ID :
1818 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1819 break;
1820 default :
1821 /* Update the error code */
1822 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1823 /* update return status */
1824 status = HAL_ERROR;
1825 break;
1828 else
1830 /* Update the error code */
1831 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1832 /* update return status */
1833 status = HAL_ERROR;
1836 /* Release Lock */
1837 __HAL_UNLOCK(hmmc);
1838 return status;
1840 #endif
1844 * @}
1847 /** @addtogroup MMC_Exported_Functions_Group3
1848 * @brief management functions
1850 @verbatim
1851 ==============================================================================
1852 ##### Peripheral Control functions #####
1853 ==============================================================================
1854 [..]
1855 This subsection provides a set of functions allowing to control the MMC card
1856 operations and get the related information
1858 @endverbatim
1859 * @{
1863 * @brief Returns information the information of the card which are stored on
1864 * the CID register.
1865 * @param hmmc Pointer to MMC handle
1866 * @param pCID Pointer to a HAL_MMC_CIDTypedef structure that
1867 * contains all CID register parameters
1868 * @retval HAL status
1870 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
1872 uint32_t tmp = 0;
1874 /* Byte 0 */
1875 tmp = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24);
1876 pCID->ManufacturerID = tmp;
1878 /* Byte 1 */
1879 tmp = (uint8_t)((hmmc->CID[0] & 0x00FF0000) >> 16);
1880 pCID->OEM_AppliID = tmp << 8;
1882 /* Byte 2 */
1883 tmp = (uint8_t)((hmmc->CID[0] & 0x000000FF00) >> 8);
1884 pCID->OEM_AppliID |= tmp;
1886 /* Byte 3 */
1887 tmp = (uint8_t)(hmmc->CID[0] & 0x000000FF);
1888 pCID->ProdName1 = tmp << 24;
1890 /* Byte 4 */
1891 tmp = (uint8_t)((hmmc->CID[1] & 0xFF000000U) >> 24);
1892 pCID->ProdName1 |= tmp << 16;
1894 /* Byte 5 */
1895 tmp = (uint8_t)((hmmc->CID[1] & 0x00FF0000) >> 16);
1896 pCID->ProdName1 |= tmp << 8;
1898 /* Byte 6 */
1899 tmp = (uint8_t)((hmmc->CID[1] & 0x0000FF00) >> 8);
1900 pCID->ProdName1 |= tmp;
1902 /* Byte 7 */
1903 tmp = (uint8_t)(hmmc->CID[1] & 0x000000FF);
1904 pCID->ProdName2 = tmp;
1906 /* Byte 8 */
1907 tmp = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24);
1908 pCID->ProdRev = tmp;
1910 /* Byte 9 */
1911 tmp = (uint8_t)((hmmc->CID[2] & 0x00FF0000) >> 16);
1912 pCID->ProdSN = tmp << 24;
1914 /* Byte 10 */
1915 tmp = (uint8_t)((hmmc->CID[2] & 0x0000FF00) >> 8);
1916 pCID->ProdSN |= tmp << 16;
1918 /* Byte 11 */
1919 tmp = (uint8_t)(hmmc->CID[2] & 0x000000FF);
1920 pCID->ProdSN |= tmp << 8;
1922 /* Byte 12 */
1923 tmp = (uint8_t)((hmmc->CID[3] & 0xFF000000U) >> 24);
1924 pCID->ProdSN |= tmp;
1926 /* Byte 13 */
1927 tmp = (uint8_t)((hmmc->CID[3] & 0x00FF0000) >> 16);
1928 pCID->Reserved1 |= (tmp & 0xF0) >> 4;
1929 pCID->ManufactDate = (tmp & 0x0F) << 8;
1931 /* Byte 14 */
1932 tmp = (uint8_t)((hmmc->CID[3] & 0x0000FF00) >> 8);
1933 pCID->ManufactDate |= tmp;
1935 /* Byte 15 */
1936 tmp = (uint8_t)(hmmc->CID[3] & 0x000000FF);
1937 pCID->CID_CRC = (tmp & 0xFE) >> 1;
1938 pCID->Reserved2 = 1;
1940 return HAL_OK;
1944 * @brief Returns information the information of the card which are stored on
1945 * the CSD register.
1946 * @param hmmc Pointer to MMC handle
1947 * @param pCSD Pointer to a HAL_MMC_CardInfoTypeDef structure that
1948 * contains all CSD register parameters
1949 * @retval HAL status
1951 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
1953 uint32_t tmp = 0;
1955 /* Byte 0 */
1956 tmp = (hmmc->CSD[0] & 0xFF000000U) >> 24;
1957 pCSD->CSDStruct = (uint8_t)((tmp & 0xC0) >> 6);
1958 pCSD->SysSpecVersion = (uint8_t)((tmp & 0x3C) >> 2);
1959 pCSD->Reserved1 = tmp & 0x03;
1961 /* Byte 1 */
1962 tmp = (hmmc->CSD[0] & 0x00FF0000) >> 16;
1963 pCSD->TAAC = (uint8_t)tmp;
1965 /* Byte 2 */
1966 tmp = (hmmc->CSD[0] & 0x0000FF00) >> 8;
1967 pCSD->NSAC = (uint8_t)tmp;
1969 /* Byte 3 */
1970 tmp = hmmc->CSD[0] & 0x000000FF;
1971 pCSD->MaxBusClkFrec = (uint8_t)tmp;
1973 /* Byte 4 */
1974 tmp = (hmmc->CSD[1] & 0xFF000000U) >> 24;
1975 pCSD->CardComdClasses = (uint16_t)(tmp << 4);
1977 /* Byte 5 */
1978 tmp = (hmmc->CSD[1] & 0x00FF0000U) >> 16;
1979 pCSD->CardComdClasses |= (uint16_t)((tmp & 0xF0) >> 4);
1980 pCSD->RdBlockLen = (uint8_t)(tmp & 0x0F);
1982 /* Byte 6 */
1983 tmp = (hmmc->CSD[1] & 0x0000FF00U) >> 8;
1984 pCSD->PartBlockRead = (uint8_t)((tmp & 0x80) >> 7);
1985 pCSD->WrBlockMisalign = (uint8_t)((tmp & 0x40) >> 6);
1986 pCSD->RdBlockMisalign = (uint8_t)((tmp & 0x20) >> 5);
1987 pCSD->DSRImpl = (uint8_t)((tmp & 0x10) >> 4);
1988 pCSD->Reserved2 = 0; /*!< Reserved */
1990 pCSD->DeviceSize = (tmp & 0x03) << 10;
1992 /* Byte 7 */
1993 tmp = (uint8_t)(hmmc->CSD[1] & 0x000000FFU);
1994 pCSD->DeviceSize |= (tmp) << 2;
1996 /* Byte 8 */
1997 tmp = (uint8_t)((hmmc->CSD[2] & 0xFF000000U) >> 24);
1998 pCSD->DeviceSize |= (tmp & 0xC0) >> 6;
2000 pCSD->MaxRdCurrentVDDMin = (tmp & 0x38) >> 3;
2001 pCSD->MaxRdCurrentVDDMax = (tmp & 0x07);
2003 /* Byte 9 */
2004 tmp = (uint8_t)((hmmc->CSD[2] & 0x00FF0000U) >> 16);
2005 pCSD->MaxWrCurrentVDDMin = (tmp & 0xE0) >> 5;
2006 pCSD->MaxWrCurrentVDDMax = (tmp & 0x1C) >> 2;
2007 pCSD->DeviceSizeMul = (tmp & 0x03) << 1;
2008 /* Byte 10 */
2009 tmp = (uint8_t)((hmmc->CSD[2] & 0x0000FF00U) >> 8);
2010 pCSD->DeviceSizeMul |= (tmp & 0x80) >> 7;
2012 hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1) ;
2013 hmmc->MmcCard.BlockNbr *= (1 << (pCSD->DeviceSizeMul + 2));
2014 hmmc->MmcCard.BlockSize = 1 << (pCSD->RdBlockLen);
2016 hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512);
2017 hmmc->MmcCard.LogBlockSize = 512;
2019 pCSD->EraseGrSize = (tmp & 0x40) >> 6;
2020 pCSD->EraseGrMul = (tmp & 0x3F) << 1;
2022 /* Byte 11 */
2023 tmp = (uint8_t)(hmmc->CSD[2] & 0x000000FF);
2024 pCSD->EraseGrMul |= (tmp & 0x80) >> 7;
2025 pCSD->WrProtectGrSize = (tmp & 0x7F);
2027 /* Byte 12 */
2028 tmp = (uint8_t)((hmmc->CSD[3] & 0xFF000000U) >> 24);
2029 pCSD->WrProtectGrEnable = (tmp & 0x80) >> 7;
2030 pCSD->ManDeflECC = (tmp & 0x60) >> 5;
2031 pCSD->WrSpeedFact = (tmp & 0x1C) >> 2;
2032 pCSD->MaxWrBlockLen = (tmp & 0x03) << 2;
2034 /* Byte 13 */
2035 tmp = (uint8_t)((hmmc->CSD[3] & 0x00FF0000) >> 16);
2036 pCSD->MaxWrBlockLen |= (tmp & 0xC0) >> 6;
2037 pCSD->WriteBlockPaPartial = (tmp & 0x20) >> 5;
2038 pCSD->Reserved3 = 0;
2039 pCSD->ContentProtectAppli = (tmp & 0x01);
2041 /* Byte 14 */
2042 tmp = (uint8_t)((hmmc->CSD[3] & 0x0000FF00) >> 8);
2043 pCSD->FileFormatGrouop = (tmp & 0x80) >> 7;
2044 pCSD->CopyFlag = (tmp & 0x40) >> 6;
2045 pCSD->PermWrProtect = (tmp & 0x20) >> 5;
2046 pCSD->TempWrProtect = (tmp & 0x10) >> 4;
2047 pCSD->FileFormat = (tmp & 0x0C) >> 2;
2048 pCSD->ECC = (tmp & 0x03);
2050 /* Byte 15 */
2051 tmp = (uint8_t)(hmmc->CSD[3] & 0x000000FF);
2052 pCSD->CSD_CRC = (tmp & 0xFE) >> 1;
2053 pCSD->Reserved4 = 1;
2055 return HAL_OK;
2059 * @brief Gets the MMC card info.
2060 * @param hmmc Pointer to MMC handle
2061 * @param pCardInfo Pointer to the HAL_MMC_CardInfoTypeDef structure that
2062 * will contain the MMC card status information
2063 * @retval HAL status
2065 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
2067 pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType);
2068 pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class);
2069 pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd);
2070 pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr);
2071 pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize);
2072 pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
2073 pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
2075 return HAL_OK;
2079 * @brief Enables wide bus operation for the requested card if supported by
2080 * card.
2081 * @param hmmc Pointer to MMC handle
2082 * @param WideMode Specifies the MMC card wide bus mode
2083 * This parameter can be one of the following values:
2084 * @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
2085 * @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
2086 * @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
2087 * @retval HAL status
2089 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
2091 __IO uint32_t count = 0;
2092 SDMMC_InitTypeDef Init;
2093 uint32_t errorstate = HAL_MMC_ERROR_NONE;
2094 uint32_t response = 0, busy = 0;
2096 /* Check the parameters */
2097 assert_param(IS_SDMMC_BUS_WIDE(WideMode));
2099 /* Chnage Satte */
2100 hmmc->State = HAL_MMC_STATE_BUSY;
2102 /* Update Clock for Bus mode update */
2103 Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
2104 Init.ClockBypass = SDMMC_CLOCK_BYPASS_DISABLE;
2105 Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
2106 Init.BusWide = WideMode;
2107 Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
2108 Init.ClockDiv = SDMMC_INIT_CLK_DIV;
2109 /* Initialize SDMMC*/
2110 SDMMC_Init(hmmc->Instance, Init);
2112 if(WideMode == SDMMC_BUS_WIDE_8B)
2114 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200);
2115 if(errorstate != HAL_MMC_ERROR_NONE)
2117 hmmc->ErrorCode |= errorstate;
2120 else if(WideMode == SDMMC_BUS_WIDE_4B)
2122 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100);
2123 if(errorstate != HAL_MMC_ERROR_NONE)
2125 hmmc->ErrorCode |= errorstate;
2128 else if(WideMode == SDMMC_BUS_WIDE_1B)
2130 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000);
2131 if(errorstate != HAL_MMC_ERROR_NONE)
2133 hmmc->ErrorCode |= errorstate;
2136 else
2138 /* WideMode is not a valid argument*/
2139 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2142 /* Check for switch error and violation of the trial number of sending CMD 13 */
2143 while(busy == 0)
2145 if(count++ == SDMMC_MAX_TRIAL)
2147 hmmc->State = HAL_MMC_STATE_READY;
2148 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2149 return HAL_ERROR;
2152 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2153 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
2154 if(errorstate != HAL_MMC_ERROR_NONE)
2156 hmmc->ErrorCode |= errorstate;
2159 /* Get command response */
2160 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2162 /* Get operating voltage*/
2163 busy = (((response >> 7) == 1) ? 0 : 1);
2166 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2167 count = SDMMC_DATATIMEOUT;
2168 while((response & 0x00000100) == 0)
2170 if(count-- == 0)
2172 hmmc->State = HAL_MMC_STATE_READY;
2173 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2174 return HAL_ERROR;
2177 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2178 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
2179 if(errorstate != HAL_MMC_ERROR_NONE)
2181 hmmc->ErrorCode |= errorstate;
2184 /* Get command response */
2185 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2188 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2190 /* Clear all the static flags */
2191 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2192 hmmc->State = HAL_MMC_STATE_READY;
2193 return HAL_ERROR;
2195 else
2197 /* Configure the SDMMC peripheral */
2198 Init.ClockEdge = hmmc->Init.ClockEdge;
2199 Init.ClockBypass = hmmc->Init.ClockBypass;
2200 Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
2201 Init.BusWide = WideMode;
2202 Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
2203 Init.ClockDiv = hmmc->Init.ClockDiv;
2204 SDMMC_Init(hmmc->Instance, Init);
2207 /* Change State */
2208 hmmc->State = HAL_MMC_STATE_READY;
2210 return HAL_OK;
2215 * @brief Gets the current mmc card data state.
2216 * @param hmmc pointer to MMC handle
2217 * @retval Card state
2219 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
2221 HAL_MMC_CardStateTypeDef cardstate = HAL_MMC_CARD_TRANSFER;
2222 uint32_t errorstate = HAL_MMC_ERROR_NONE;
2223 uint32_t resp1 = 0;
2225 errorstate = MMC_SendStatus(hmmc, &resp1);
2226 if(errorstate != HAL_OK)
2228 hmmc->ErrorCode |= errorstate;
2231 cardstate = (HAL_MMC_CardStateTypeDef)((resp1 >> 9) & 0x0F);
2233 return cardstate;
2237 * @brief Abort the current transfer and disable the MMC.
2238 * @param hmmc pointer to a MMC_HandleTypeDef structure that contains
2239 * the configuration information for MMC module.
2240 * @retval HAL status
2242 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
2244 HAL_MMC_CardStateTypeDef CardState;
2246 /* DIsable All interrupts */
2247 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2248 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2250 /* Clear All flags */
2251 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2253 if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2255 /* Disable the MMC DMA request */
2256 hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
2258 /* Abort the MMC DMA Tx Stream */
2259 if(hmmc->hdmatx != NULL)
2261 HAL_DMA_Abort(hmmc->hdmatx);
2263 /* Abort the MMC DMA Rx Stream */
2264 if(hmmc->hdmarx != NULL)
2266 HAL_DMA_Abort(hmmc->hdmarx);
2270 hmmc->State = HAL_MMC_STATE_READY;
2271 CardState = HAL_MMC_GetCardState(hmmc);
2272 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2274 hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2276 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2278 return HAL_ERROR;
2280 return HAL_OK;
2284 * @brief Abort the current transfer and disable the MMC (IT mode).
2285 * @param hmmc pointer to a MMC_HandleTypeDef structure that contains
2286 * the configuration information for MMC module.
2287 * @retval HAL status
2289 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
2291 HAL_MMC_CardStateTypeDef CardState;
2293 /* DIsable All interrupts */
2294 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2295 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2297 /* Clear All flags */
2298 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2300 if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2302 /* Disable the MMC DMA request */
2303 hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
2305 /* Abort the MMC DMA Tx Stream */
2306 if(hmmc->hdmatx != NULL)
2308 hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
2309 if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
2311 hmmc->hdmatx = NULL;
2314 /* Abort the MMC DMA Rx Stream */
2315 if(hmmc->hdmarx != NULL)
2317 hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
2318 if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
2320 hmmc->hdmarx = NULL;
2325 /* No transfer ongoing on both DMA channels*/
2326 if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
2328 CardState = HAL_MMC_GetCardState(hmmc);
2329 hmmc->State = HAL_MMC_STATE_READY;
2330 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2332 hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2334 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2336 return HAL_ERROR;
2338 else
2340 HAL_MMC_AbortCallback(hmmc);
2344 return HAL_OK;
2348 * @}
2352 * @}
2355 /* Private function ----------------------------------------------------------*/
2356 /** @addtogroup MMC_Private_Functions
2357 * @{
2361 * @brief DMA MMC transmit process complete callback
2362 * @param hdma DMA handle
2363 * @retval None
2365 static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)
2367 MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2369 /* Enable DATAEND Interrupt */
2370 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DATAEND));
2374 * @brief DMA MMC receive process complete callback
2375 * @param hdma DMA handle
2376 * @retval None
2378 static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
2380 MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2381 uint32_t errorstate = HAL_MMC_ERROR_NONE;
2383 /* Send stop command in multiblock write */
2384 if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
2386 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
2387 if(errorstate != HAL_MMC_ERROR_NONE)
2389 hmmc->ErrorCode |= errorstate;
2390 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
2391 hmmc->ErrorCallback(hmmc);
2392 #else
2393 HAL_MMC_ErrorCallback(hmmc);
2394 #endif
2398 /* Disable the DMA transfer for transmit request by setting the DMAEN bit
2399 in the MMC DCTRL register */
2400 hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDMMC_DCTRL_DMAEN);
2402 /* Clear all the static flags */
2403 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2405 hmmc->State = HAL_MMC_STATE_READY;
2407 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
2408 hmmc->RxCpltCallback(hmmc);
2409 #else
2410 HAL_MMC_RxCpltCallback(hmmc);
2411 #endif
2415 * @brief DMA MMC communication error callback
2416 * @param hdma DMA handle
2417 * @retval None
2419 static void MMC_DMAError(DMA_HandleTypeDef *hdma)
2421 MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2422 HAL_MMC_CardStateTypeDef CardState;
2424 /* if DMA error is FIFO error ignore it */
2425 if(HAL_DMA_GetError(hdma) != HAL_DMA_ERROR_FE)
2427 if((hmmc->hdmarx->ErrorCode == HAL_DMA_ERROR_TE) || (hmmc->hdmatx->ErrorCode == HAL_DMA_ERROR_TE))
2429 /* Clear All flags */
2430 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2432 /* Disable All interrupts */
2433 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2434 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2436 hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2437 CardState = HAL_MMC_GetCardState(hmmc);
2438 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2440 hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2443 hmmc->State= HAL_MMC_STATE_READY;
2446 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
2447 hmmc->ErrorCallback(hmmc);
2448 #else
2449 HAL_MMC_ErrorCallback(hmmc);
2450 #endif
2456 * @brief DMA MMC Tx Abort callback
2457 * @param hdma DMA handle
2458 * @retval None
2460 static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)
2462 MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2463 HAL_MMC_CardStateTypeDef CardState;
2465 if(hmmc->hdmatx != NULL)
2467 hmmc->hdmatx = NULL;
2470 /* All DMA channels are aborted */
2471 if(hmmc->hdmarx == NULL)
2473 CardState = HAL_MMC_GetCardState(hmmc);
2474 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2475 hmmc->State = HAL_MMC_STATE_READY;
2476 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2478 hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2480 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2482 HAL_MMC_AbortCallback(hmmc);
2484 else
2486 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
2487 hmmc->ErrorCallback(hmmc);
2488 #else
2489 HAL_MMC_ErrorCallback(hmmc);
2490 #endif
2497 * @brief DMA MMC Rx Abort callback
2498 * @param hdma DMA handle
2499 * @retval None
2501 static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)
2503 MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2504 HAL_MMC_CardStateTypeDef CardState;
2506 if(hmmc->hdmarx != NULL)
2508 hmmc->hdmarx = NULL;
2511 /* All DMA channels are aborted */
2512 if(hmmc->hdmatx == NULL)
2514 CardState = HAL_MMC_GetCardState(hmmc);
2515 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2516 hmmc->State = HAL_MMC_STATE_READY;
2517 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2519 hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2521 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2523 HAL_MMC_AbortCallback(hmmc);
2525 else
2527 #if (USE_HAL_MMC_REGISTER_CALLBACKS == 1)
2528 hmmc->ErrorCallback(hmmc);
2529 #else
2530 HAL_MMC_ErrorCallback(hmmc);
2531 #endif
2539 * @brief Initializes the mmc card.
2540 * @param hmmc Pointer to MMC handle
2541 * @retval MMC Card error state
2543 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
2545 HAL_MMC_CardCSDTypeDef CSD;
2546 uint32_t errorstate = HAL_MMC_ERROR_NONE;
2547 uint16_t mmc_rca = 1;
2549 /* Check the power State */
2550 if(SDMMC_GetPowerState(hmmc->Instance) == 0)
2552 /* Power off */
2553 return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2556 /* Send CMD2 ALL_SEND_CID */
2557 errorstate = SDMMC_CmdSendCID(hmmc->Instance);
2558 if(errorstate != HAL_MMC_ERROR_NONE)
2560 return errorstate;
2562 else
2564 /* Get Card identification number data */
2565 hmmc->CID[0] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2566 hmmc->CID[1] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
2567 hmmc->CID[2] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
2568 hmmc->CID[3] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
2571 /* Send CMD3 SET_REL_ADDR with argument 0 */
2572 /* MMC Card publishes its RCA. */
2573 errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
2574 if(errorstate != HAL_MMC_ERROR_NONE)
2576 return errorstate;
2579 /* Get the MMC card RCA */
2580 hmmc->MmcCard.RelCardAdd = mmc_rca;
2582 /* Send CMD9 SEND_CSD with argument as card's RCA */
2583 errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2584 if(errorstate != HAL_MMC_ERROR_NONE)
2586 return errorstate;
2588 else
2590 /* Get Card Specific Data */
2591 hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2592 hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
2593 hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
2594 hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
2597 /* Get the Card Class */
2598 hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20);
2600 /* Get CSD parameters */
2601 HAL_MMC_GetCardCSD(hmmc, &CSD);
2603 /* Select the Card */
2604 errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
2605 if(errorstate != HAL_MMC_ERROR_NONE)
2607 return errorstate;
2610 /* Configure SDMMC peripheral interface */
2611 SDMMC_Init(hmmc->Instance, hmmc->Init);
2613 /* All cards are initialized */
2614 return HAL_MMC_ERROR_NONE;
2618 * @brief Enquires cards about their operating voltage and configures clock
2619 * controls and stores MMC information that will be needed in future
2620 * in the MMC handle.
2621 * @param hmmc Pointer to MMC handle
2622 * @retval error state
2624 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
2626 __IO uint32_t count = 0;
2627 uint32_t response = 0, validvoltage = 0;
2628 uint32_t errorstate = HAL_MMC_ERROR_NONE;
2630 /* CMD0: GO_IDLE_STATE */
2631 errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
2632 if(errorstate != HAL_MMC_ERROR_NONE)
2634 return errorstate;
2637 while(validvoltage == 0)
2639 if(count++ == SDMMC_MAX_VOLT_TRIAL)
2641 return HAL_MMC_ERROR_INVALID_VOLTRANGE;
2644 /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
2645 errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
2646 if(errorstate != HAL_MMC_ERROR_NONE)
2648 return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2651 /* Get command response */
2652 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2654 /* Get operating voltage*/
2655 validvoltage = (((response >> 31) == 1) ? 1 : 0);
2658 /* When power routine is finished and command returns valid voltage */
2659 if ((response & MMC_HIGH_VOLTAGE_RANGE) == MMC_HIGH_VOLTAGE_RANGE)
2661 /* When voltage range of the card is within 2.7V and 3.6V */
2662 hmmc->MmcCard.CardType = MMC_HIGH_VOLTAGE_CARD;
2664 else
2666 /* When voltage range of the card is within 1.65V and 1.95V or 2.7V and 3.6V */
2667 hmmc->MmcCard.CardType = MMC_DUAL_VOLTAGE_CARD;
2670 return HAL_MMC_ERROR_NONE;
2674 * @brief Turns the SDMMC output signals off.
2675 * @param hmmc Pointer to MMC handle
2676 * @retval HAL status
2678 static HAL_StatusTypeDef MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
2680 /* Set Power State to OFF */
2681 SDMMC_PowerState_OFF(hmmc->Instance);
2683 return HAL_OK;
2687 * @brief Returns the current card's status.
2688 * @param hmmc Pointer to MMC handle
2689 * @param pCardStatus pointer to the buffer that will contain the MMC card
2690 * status (Card Status register)
2691 * @retval error state
2693 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
2695 uint32_t errorstate = HAL_MMC_ERROR_NONE;
2697 if(pCardStatus == NULL)
2699 return HAL_MMC_ERROR_PARAM;
2702 /* Send Status command */
2703 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16));
2704 if(errorstate != HAL_OK)
2706 return errorstate;
2709 /* Get MMC card status */
2710 *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2712 return HAL_MMC_ERROR_NONE;
2716 * @brief Wrap up reading in non-blocking mode.
2717 * @param hmmc pointer to a MMC_HandleTypeDef structure that contains
2718 * the configuration information.
2719 * @retval HAL status
2721 static HAL_StatusTypeDef MMC_Read_IT(MMC_HandleTypeDef *hmmc)
2723 uint32_t count = 0;
2724 uint32_t* tmp;
2726 tmp = (uint32_t*)hmmc->pRxBuffPtr;
2728 /* Read data from SDMMC Rx FIFO */
2729 for(count = 0; count < 8; count++)
2731 *(tmp + count) = SDMMC_ReadFIFO(hmmc->Instance);
2734 hmmc->pRxBuffPtr += 8;
2736 return HAL_OK;
2740 * @brief Wrap up writing in non-blocking mode.
2741 * @param hmmc pointer to a MMC_HandleTypeDef structure that contains
2742 * the configuration information.
2743 * @retval HAL status
2745 static HAL_StatusTypeDef MMC_Write_IT(MMC_HandleTypeDef *hmmc)
2747 uint32_t count = 0;
2748 uint32_t* tmp;
2750 tmp = (uint32_t*)hmmc->pTxBuffPtr;
2752 /* Write data to SDMMC Tx FIFO */
2753 for(count = 0; count < 8; count++)
2755 SDMMC_WriteFIFO(hmmc->Instance, (tmp + count));
2758 hmmc->pTxBuffPtr += 8;
2760 return HAL_OK;
2764 * @}
2767 #endif /* HAL_MMC_MODULE_ENABLED */
2770 * @}
2774 * @}
2777 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/