Updated and Validated
[betaflight.git] / lib / main / STM32H7 / Drivers / STM32H7xx_HAL_Driver / Src / stm32h7xx_hal_mmc.c
blobad6933434c865715062827782c81b01d2d9505cd
1 /**
2 ******************************************************************************
3 * @file stm32h7xx_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 (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
37 and HAL_MMC_WriteBlocks_IT() APIs).
38 (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
39 (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
40 (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
41 and __HAL_MMC_DISABLE_IT() inside the communication process.
42 (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
43 and __HAL_MMC_CLEAR_IT()
44 (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used.
46 (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
49 *** MMC Card Initialization and configuration ***
50 ================================================
51 [..]
52 To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
53 SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
54 This function provide the following operations:
56 (#) Initialize the SDMMC peripheral interface with defaullt configuration.
57 The initialization process is done at 400KHz. You can change or adapt
58 this frequency by adjusting the "ClockDiv" field.
59 The MMC Card frequency (SDMMC_CK) is computed as follows:
61 SDMMC_CK = SDMMCCLK / (2 * ClockDiv)
63 In initialization mode and according to the MMC Card standard,
64 make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
66 This phase of initialization is done through SDMMC_Init() and
67 SDMMC_PowerState_ON() SDMMC low level APIs.
69 (#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
70 This phase allows the card initialization and identification
71 and check the MMC Card type (Standard Capacity or High Capacity)
72 The initialization flow is compatible with MMC standard.
74 This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
75 of plug-off plug-in.
77 (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
78 frequency by adjusting the "ClockDiv" field.
79 In transfer mode and according to the MMC Card standard, make sure that the
80 SDMMC_CK frequency doesn't exceed 25MHz and 100MHz in High-speed mode switch.
82 (#) Select the corresponding MMC Card according to the address read with the step 2.
84 (#) Configure the MMC Card in wide bus mode: 4-bits data.
86 *** MMC Card Read operation ***
87 ==============================
88 [..]
89 (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
90 This function support only 512-bytes block length (the block size should be
91 chosen as 512 bytes).
92 You can choose either one block read operation or multiple block read operation
93 by adjusting the "NumberOfBlocks" parameter.
94 After this, you have to ensure that the transfer is done correctly. The check is done
95 through HAL_MMC_GetCardState() function for MMC card state.
97 (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
98 This function support only 512-bytes block length (the block size should be
99 chosen as 512 bytes).
100 You can choose either one block read operation or multiple block read operation
101 by adjusting the "NumberOfBlocks" parameter.
102 After this, you have to ensure that the transfer is done correctly. The check is done
103 through HAL_MMC_GetCardState() function for MMC card state.
104 You could also check the DMA transfer process through the MMC Rx interrupt event.
106 (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
107 This function allows the read of 512 bytes blocks.
108 You can choose either one block read operation or multiple block read operation
109 by adjusting the "NumberOfBlocks" parameter.
110 After this, you have to ensure that the transfer is done correctly. The check is done
111 through HAL_MMC_GetCardState() function for MMC card state.
112 You could also check the IT transfer process through the MMC Rx interrupt event.
114 *** MMC Card Write operation ***
115 ===============================
116 [..]
117 (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
118 This function support only 512-bytes block length (the block size should be
119 chosen as 512 bytes).
120 You can choose either one block read operation or multiple block read operation
121 by adjusting the "NumberOfBlocks" parameter.
122 After this, you have to ensure that the transfer is done correctly. The check is done
123 through HAL_MMC_GetCardState() function for MMC card state.
125 (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
126 This function support only 512-bytes block length (the block size should be
127 chosen as 512 byte).
128 You can choose either one block read operation or multiple block read operation
129 by adjusting the "NumberOfBlocks" parameter.
130 After this, you have to ensure that the transfer is done correctly. The check is done
131 through HAL_MMC_GetCardState() function for MMC card state.
132 You could also check the DMA transfer process through the MMC Tx interrupt event.
134 (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
135 This function allows the read of 512 bytes blocks.
136 You can choose either one block read operation or multiple block read operation
137 by adjusting the "NumberOfBlocks" parameter.
138 After this, you have to ensure that the transfer is done correctly. The check is done
139 through HAL_MMC_GetCardState() function for MMC card state.
140 You could also check the IT transfer process through the MMC Tx interrupt event.
142 *** MMC card information ***
143 ===========================
144 [..]
145 (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
146 It returns useful information about the MMC card such as block size, card type,
147 block number ...
149 *** MMC card CSD register ***
150 ============================
151 [..]
152 (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
153 Some of the CSD parameters are useful for card initialization and identification.
155 *** MMC card CID register ***
156 ============================
157 [..]
158 (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
159 Some of the CID parameters are useful for card initialization and identification.
161 *** MMC HAL driver macros list ***
162 ==================================
163 [..]
164 Below the list of most used macros in MMC HAL driver.
166 (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
167 (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
168 (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
169 (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
171 [..]
172 (@) You can refer to the MMC HAL driver header file for more useful macros
174 *** Callback registration ***
175 =============================================
176 [..]
177 The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
178 allows the user to configure dynamically the driver callbacks.
180 Use Functions @ref HAL_MMC_RegisterCallback() to register a user callback,
181 it allows to register following callbacks:
182 (+) TxCpltCallback : callback when a transmission transfer is completed.
183 (+) RxCpltCallback : callback when a reception transfer is completed.
184 (+) ErrorCallback : callback when error occurs.
185 (+) AbortCpltCallback : callback when abort is completed.
186 (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
187 (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
188 (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
189 (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
190 (+) MspInitCallback : MMC MspInit.
191 (+) MspDeInitCallback : MMC MspDeInit.
192 This function takes as parameters the HAL peripheral handle, the Callback ID
193 and a pointer to the user callback function.
195 Use function @ref HAL_MMC_UnRegisterCallback() to reset a callback to the default
196 weak (surcharged) function. It allows to reset 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 (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed.
202 (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed.
203 (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed.
204 (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed.
205 (+) MspInitCallback : MMC MspInit.
206 (+) MspDeInitCallback : MMC MspDeInit.
207 This function) takes as parameters the HAL peripheral handle and the Callback ID.
209 By default, after the @ref HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
210 all callbacks are reset to the corresponding legacy weak (surcharged) functions.
211 Exception done for MspInit and MspDeInit callbacks that are respectively
212 reset to the legacy weak (surcharged) functions in the @ref HAL_MMC_Init
213 and @ref HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
214 If not, MspInit or MspDeInit are not null, the @ref HAL_MMC_Init and @ref HAL_MMC_DeInit
215 keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
217 Callbacks can be registered/unregistered in READY state only.
218 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
219 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
220 during the Init/DeInit.
221 In that case first register the MspInit/MspDeInit user callbacks
222 using @ref HAL_MMC_RegisterCallback before calling @ref HAL_MMC_DeInit
223 or @ref HAL_MMC_Init function.
225 When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
226 not defined, the callback registering feature is not available
227 and weak (surcharged) callbacks are used.
229 @endverbatim
230 ******************************************************************************
231 * @attention
233 * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
234 * All rights reserved.</center></h2>
236 * This software component is licensed by ST under BSD 3-Clause license,
237 * the "License"; You may not use this file except in compliance with the
238 * License. You may obtain a copy of the License at:
239 * opensource.org/licenses/BSD-3-Clause
241 ******************************************************************************
244 /* Includes ------------------------------------------------------------------*/
245 #include "stm32h7xx_hal.h"
247 /** @addtogroup STM32H7xx_HAL_Driver
248 * @{
251 /** @defgroup MMC MMC
252 * @brief MMC HAL module driver
253 * @{
256 #ifdef HAL_MMC_MODULE_ENABLED
258 /* Private typedef -----------------------------------------------------------*/
259 /* Private define ------------------------------------------------------------*/
260 /** @addtogroup MMC_Private_Defines
261 * @{
265 * @}
268 /* Private macro -------------------------------------------------------------*/
269 /* Private variables ---------------------------------------------------------*/
270 /* Private function prototypes -----------------------------------------------*/
271 /* Private functions ---------------------------------------------------------*/
272 /** @defgroup MMC_Private_Functions MMC Private Functions
273 * @{
275 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
276 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
277 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
278 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
279 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc);
280 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc);
281 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state);
282 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state);
283 HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout);
287 * @}
289 /* Exported functions --------------------------------------------------------*/
290 /** @addtogroup MMC_Exported_Functions
291 * @{
294 /** @addtogroup MMC_Exported_Functions_Group1
295 * @brief Initialization and de-initialization functions
297 @verbatim
298 ==============================================================================
299 ##### Initialization and de-initialization functions #####
300 ==============================================================================
301 [..]
302 This section provides functions allowing to initialize/de-initialize the MMC
303 card device to be ready for use.
305 @endverbatim
306 * @{
310 * @brief Initializes the MMC according to the specified parameters in the
311 MMC_HandleTypeDef and create the associated handle.
312 * @param hmmc: Pointer to the MMC handle
313 * @retval HAL status
315 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
317 /* Check the MMC handle allocation */
318 if(hmmc == NULL)
320 return HAL_ERROR;
323 /* Check the parameters */
324 assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
325 assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge));
326 assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
327 assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide));
328 assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
329 assert_param(IS_SDMMC_CLKDIV(hmmc->Init.ClockDiv));
331 if(hmmc->State == HAL_MMC_STATE_RESET)
333 /* Allocate lock resource and initialize it */
334 hmmc->Lock = HAL_UNLOCKED;
335 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
336 /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
337 hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
338 hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
339 hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
340 hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
341 hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback;
342 hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback;
343 hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback;
344 hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback;
346 if(hmmc->MspInitCallback == NULL)
348 hmmc->MspInitCallback = HAL_MMC_MspInit;
351 /* Init the low level hardware */
352 hmmc->MspInitCallback(hmmc);
353 #else
354 /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
355 HAL_MMC_MspInit(hmmc);
356 #endif
359 hmmc->State = HAL_MMC_STATE_BUSY;
361 /* Initialize the Card parameters */
362 if(HAL_MMC_InitCard(hmmc) == HAL_ERROR)
364 return HAL_ERROR;
367 /* Initialize the error code */
368 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
370 /* Initialize the MMC operation */
371 hmmc->Context = MMC_CONTEXT_NONE;
373 /* Initialize the MMC state */
374 hmmc->State = HAL_MMC_STATE_READY;
376 return HAL_OK;
380 * @brief Initializes the MMC Card.
381 * @param hmmc: Pointer to MMC handle
382 * @note This function initializes the MMC card. It could be used when a card
383 re-initialization is needed.
384 * @retval HAL status
386 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
388 uint32_t errorstate;
389 MMC_InitTypeDef Init;
390 uint32_t sdmmc_clk;
392 /* Default SDMMC peripheral configuration for MMC card initialization */
393 Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING;
394 Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE;
395 Init.BusWide = SDMMC_BUS_WIDE_1B;
396 Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE;
398 /* Init Clock should be less or equal to 400Khz*/
399 sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC);
400 Init.ClockDiv = sdmmc_clk/(2U*400000U);
402 /* Initialize SDMMC peripheral interface with default configuration */
403 (void)SDMMC_Init(hmmc->Instance, Init);
405 /* Set Power State to ON */
406 (void)SDMMC_PowerState_ON(hmmc->Instance);
408 /* wait 74 Cycles: required power up waiting time before starting
409 the MMC initialization sequence */
410 sdmmc_clk = sdmmc_clk/(2U*Init.ClockDiv);
412 if(sdmmc_clk != 0U)
414 HAL_Delay(1U+ (74U*1000U/(sdmmc_clk)));
416 else
418 HAL_Delay(2U);
421 /* Identify card operating voltage */
422 errorstate = MMC_PowerON(hmmc);
423 if(errorstate != HAL_MMC_ERROR_NONE)
425 hmmc->State = HAL_MMC_STATE_READY;
426 hmmc->ErrorCode |= errorstate;
427 return HAL_ERROR;
430 /* Card initialization */
431 errorstate = MMC_InitCard(hmmc);
432 if(errorstate != HAL_MMC_ERROR_NONE)
434 hmmc->State = HAL_MMC_STATE_READY;
435 hmmc->ErrorCode |= errorstate;
436 return HAL_ERROR;
439 /* Set Block Size for Card */
440 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
441 if(errorstate != HAL_MMC_ERROR_NONE)
443 /* Clear all the static flags */
444 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
445 hmmc->ErrorCode |= errorstate;
446 hmmc->State = HAL_MMC_STATE_READY;
447 return HAL_ERROR;
450 return HAL_OK;
454 * @brief De-Initializes the MMC card.
455 * @param hmmc: Pointer to MMC handle
456 * @retval HAL status
458 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
460 /* Check the MMC handle allocation */
461 if(hmmc == NULL)
463 return HAL_ERROR;
466 /* Check the parameters */
467 assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance));
469 hmmc->State = HAL_MMC_STATE_BUSY;
471 /* Set MMC power state to off */
472 MMC_PowerOFF(hmmc);
474 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
475 if(hmmc->MspDeInitCallback == NULL)
477 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
480 /* DeInit the low level hardware */
481 hmmc->MspDeInitCallback(hmmc);
482 #else
483 /* De-Initialize the MSP layer */
484 HAL_MMC_MspDeInit(hmmc);
485 #endif
487 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
488 hmmc->State = HAL_MMC_STATE_RESET;
490 return HAL_OK;
495 * @brief Initializes the MMC MSP.
496 * @param hmmc: Pointer to MMC handle
497 * @retval None
499 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
501 /* Prevent unused argument(s) compilation warning */
502 UNUSED(hmmc);
504 /* NOTE : This function Should not be modified, when the callback is needed,
505 the HAL_MMC_MspInit could be implemented in the user file
510 * @brief De-Initialize MMC MSP.
511 * @param hmmc: Pointer to MMC handle
512 * @retval None
514 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
516 /* Prevent unused argument(s) compilation warning */
517 UNUSED(hmmc);
519 /* NOTE : This function Should not be modified, when the callback is needed,
520 the HAL_MMC_MspDeInit could be implemented in the user file
525 * @}
528 /** @addtogroup MMC_Exported_Functions_Group2
529 * @brief Data transfer functions
531 @verbatim
532 ==============================================================================
533 ##### IO operation functions #####
534 ==============================================================================
535 [..]
536 This subsection provides a set of functions allowing to manage the data
537 transfer from/to MMC card.
539 @endverbatim
540 * @{
544 * @brief Reads block(s) from a specified address in a card. The Data transfer
545 * is managed by polling mode.
546 * @note This API should be followed by a check on the card state through
547 * HAL_MMC_GetCardState().
548 * @param hmmc: Pointer to MMC handle
549 * @param pData: pointer to the buffer that will contain the received data
550 * @param BlockAdd: Block Address from where data is to be read
551 * @param NumberOfBlocks: Number of MMC blocks to read
552 * @param Timeout: Specify timeout value
553 * @retval HAL status
555 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
557 SDMMC_DataInitTypeDef config;
558 uint32_t errorstate;
559 uint32_t tickstart = HAL_GetTick();
560 uint32_t count, data, dataremaining;
561 uint32_t add = BlockAdd;
562 uint8_t *tempbuff = pData;
564 if(NULL == pData)
566 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
567 return HAL_ERROR;
570 if(hmmc->State == HAL_MMC_STATE_READY)
572 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
574 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
576 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
577 return HAL_ERROR;
580 hmmc->State = HAL_MMC_STATE_BUSY;
582 /* Initialize data control register */
583 hmmc->Instance->DCTRL = 0U;
585 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
587 add *= 512U;
590 /* Configure the MMC DPSM (Data Path State Machine) */
591 config.DataTimeOut = SDMMC_DATATIMEOUT;
592 config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
593 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
594 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
595 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
596 config.DPSM = SDMMC_DPSM_DISABLE;
597 (void)SDMMC_ConfigData(hmmc->Instance, &config);
598 __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
600 /* Read block(s) in polling mode */
601 if(NumberOfBlocks > 1U)
603 hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
605 /* Read Multi Block command */
606 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
608 else
610 hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
612 /* Read Single Block command */
613 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
615 if(errorstate != HAL_MMC_ERROR_NONE)
617 /* Clear all the static flags */
618 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
619 hmmc->ErrorCode |= errorstate;
620 hmmc->State = HAL_MMC_STATE_READY;
621 return HAL_ERROR;
624 /* Poll on SDMMC flags */
625 dataremaining = config.DataLength;
626 while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
628 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U))
630 /* Read data from SDMMC Rx FIFO */
631 for(count = 0U; count < 8U; count++)
633 data = SDMMC_ReadFIFO(hmmc->Instance);
634 *tempbuff = (uint8_t)(data & 0xFFU);
635 tempbuff++;
636 *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
637 tempbuff++;
638 *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
639 tempbuff++;
640 *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
641 tempbuff++;
643 dataremaining -= 32U;
646 if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
648 /* Clear all the static flags */
649 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
650 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
651 hmmc->State= HAL_MMC_STATE_READY;
652 return HAL_TIMEOUT;
655 __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
657 /* Send stop transmission command in case of multiblock read */
658 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
660 /* Send stop transmission command */
661 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
662 if(errorstate != HAL_MMC_ERROR_NONE)
664 /* Clear all the static flags */
665 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
666 hmmc->ErrorCode |= errorstate;
667 hmmc->State = HAL_MMC_STATE_READY;
668 return HAL_ERROR;
672 /* Get error state */
673 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
675 /* Clear all the static flags */
676 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
677 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
678 hmmc->State = HAL_MMC_STATE_READY;
679 return HAL_ERROR;
681 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
683 /* Clear all the static flags */
684 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
685 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
686 hmmc->State = HAL_MMC_STATE_READY;
687 return HAL_ERROR;
689 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR))
691 /* Clear all the static flags */
692 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
693 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
694 hmmc->State = HAL_MMC_STATE_READY;
695 return HAL_ERROR;
697 else
699 /* Nothing to do */
702 /* Clear all the static flags */
703 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
705 hmmc->State = HAL_MMC_STATE_READY;
707 return HAL_OK;
709 else
711 hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
712 return HAL_ERROR;
717 * @brief Allows to write block(s) to a specified address in a card. The Data
718 * transfer is managed by polling mode.
719 * @note This API should be followed by a check on the card state through
720 * HAL_MMC_GetCardState().
721 * @param hmmc: Pointer to MMC handle
722 * @param pData: pointer to the buffer that will contain the data to transmit
723 * @param BlockAdd: Block Address where data will be written
724 * @param NumberOfBlocks: Number of MMC blocks to write
725 * @param Timeout: Specify timeout value
726 * @retval HAL status
728 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
730 SDMMC_DataInitTypeDef config;
731 uint32_t errorstate;
732 uint32_t tickstart = HAL_GetTick();
733 uint32_t count, data, dataremaining;
734 uint32_t add = BlockAdd;
735 uint8_t *tempbuff = pData;
737 if(NULL == pData)
739 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
740 return HAL_ERROR;
743 if(hmmc->State == HAL_MMC_STATE_READY)
745 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
747 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
749 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
750 return HAL_ERROR;
753 hmmc->State = HAL_MMC_STATE_BUSY;
755 /* Initialize data control register */
756 hmmc->Instance->DCTRL = 0U;
758 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
760 add *= 512U;
763 /* Configure the MMC DPSM (Data Path State Machine) */
764 config.DataTimeOut = SDMMC_DATATIMEOUT;
765 config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
766 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
767 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
768 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
769 config.DPSM = SDMMC_DPSM_DISABLE;
770 (void)SDMMC_ConfigData(hmmc->Instance, &config);
771 __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
773 /* Write Blocks in Polling mode */
774 if(NumberOfBlocks > 1U)
776 hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
778 /* Write Multi Block command */
779 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
781 else
783 hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
785 /* Write Single Block command */
786 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
788 if(errorstate != HAL_MMC_ERROR_NONE)
790 /* Clear all the static flags */
791 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
792 hmmc->ErrorCode |= errorstate;
793 hmmc->State = HAL_MMC_STATE_READY;
794 return HAL_ERROR;
797 /* Write block(s) in polling mode */
798 dataremaining = config.DataLength;
799 while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
801 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U))
803 /* Write data to SDMMC Tx FIFO */
804 for(count = 0U; count < 8U; count++)
806 data = (uint32_t)(*tempbuff);
807 tempbuff++;
808 data |= ((uint32_t)(*tempbuff) << 8U);
809 tempbuff++;
810 data |= ((uint32_t)(*tempbuff) << 16U);
811 tempbuff++;
812 data |= ((uint32_t)(*tempbuff) << 24U);
813 tempbuff++;
814 (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
816 dataremaining -= 32U;
819 if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
821 /* Clear all the static flags */
822 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
823 hmmc->ErrorCode |= errorstate;
824 hmmc->State = HAL_MMC_STATE_READY;
825 return HAL_TIMEOUT;
828 __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
830 /* Send stop transmission command in case of multiblock write */
831 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U))
833 /* Send stop transmission command */
834 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
835 if(errorstate != HAL_MMC_ERROR_NONE)
837 /* Clear all the static flags */
838 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
839 hmmc->ErrorCode |= errorstate;
840 hmmc->State = HAL_MMC_STATE_READY;
841 return HAL_ERROR;
845 /* Get error state */
846 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT))
848 /* Clear all the static flags */
849 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
850 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
851 hmmc->State = HAL_MMC_STATE_READY;
852 return HAL_ERROR;
854 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL))
856 /* Clear all the static flags */
857 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
858 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
859 hmmc->State = HAL_MMC_STATE_READY;
860 return HAL_ERROR;
862 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR))
864 /* Clear all the static flags */
865 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
866 hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
867 hmmc->State = HAL_MMC_STATE_READY;
868 return HAL_ERROR;
870 else
872 /* Nothing to do */
875 /* Clear all the static flags */
876 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
878 hmmc->State = HAL_MMC_STATE_READY;
880 return HAL_OK;
882 else
884 hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
885 return HAL_ERROR;
890 * @brief Reads block(s) from a specified address in a card. The Data transfer
891 * is managed in interrupt mode.
892 * @note This API should be followed by a check on the card state through
893 * HAL_MMC_GetCardState().
894 * @note You could also check the IT transfer process through the MMC Rx
895 * interrupt event.
896 * @param hmmc: Pointer to MMC handle
897 * @param pData: Pointer to the buffer that will contain the received data
898 * @param BlockAdd: Block Address from where data is to be read
899 * @param NumberOfBlocks: Number of blocks to read.
900 * @retval HAL status
902 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
904 SDMMC_DataInitTypeDef config;
905 uint32_t errorstate;
906 uint32_t add = BlockAdd;
908 if(NULL == pData)
910 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
911 return HAL_ERROR;
914 if(hmmc->State == HAL_MMC_STATE_READY)
916 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
918 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
920 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
921 return HAL_ERROR;
924 hmmc->State = HAL_MMC_STATE_BUSY;
926 /* Initialize data control register */
927 hmmc->Instance->DCTRL = 0U;
929 hmmc->pRxBuffPtr = pData;
930 hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
932 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
934 add *= 512U;
937 /* Configure the MMC DPSM (Data Path State Machine) */
938 config.DataTimeOut = SDMMC_DATATIMEOUT;
939 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
940 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
941 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
942 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
943 config.DPSM = SDMMC_DPSM_DISABLE;
944 (void)SDMMC_ConfigData(hmmc->Instance, &config);
945 __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
947 /* Read Blocks in IT mode */
948 if(NumberOfBlocks > 1U)
950 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
952 /* Read Multi Block command */
953 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
955 else
957 hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
959 /* Read Single Block command */
960 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
963 if(errorstate != HAL_MMC_ERROR_NONE)
965 /* Clear all the static flags */
966 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
967 hmmc->ErrorCode |= errorstate;
968 hmmc->State = HAL_MMC_STATE_READY;
969 return HAL_ERROR;
972 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_FLAG_RXFIFOHF));
974 return HAL_OK;
976 else
978 return HAL_BUSY;
983 * @brief Writes block(s) to a specified address in a card. The Data transfer
984 * is managed in interrupt mode.
985 * @note This API should be followed by a check on the card state through
986 * HAL_MMC_GetCardState().
987 * @note You could also check the IT transfer process through the MMC Tx
988 * interrupt event.
989 * @param hmmc: Pointer to MMC handle
990 * @param pData: Pointer to the buffer that will contain the data to transmit
991 * @param BlockAdd: Block Address where data will be written
992 * @param NumberOfBlocks: Number of blocks to write
993 * @retval HAL status
995 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
997 SDMMC_DataInitTypeDef config;
998 uint32_t errorstate;
999 uint32_t add = BlockAdd;
1001 if(NULL == pData)
1003 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1004 return HAL_ERROR;
1007 if(hmmc->State == HAL_MMC_STATE_READY)
1009 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1011 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1013 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1014 return HAL_ERROR;
1017 hmmc->State = HAL_MMC_STATE_BUSY;
1019 /* Initialize data control register */
1020 hmmc->Instance->DCTRL = 0U;
1022 hmmc->pTxBuffPtr = pData;
1023 hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1025 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1027 add *= 512U;
1030 /* Configure the MMC DPSM (Data Path State Machine) */
1031 config.DataTimeOut = SDMMC_DATATIMEOUT;
1032 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
1033 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1034 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
1035 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
1036 config.DPSM = SDMMC_DPSM_DISABLE;
1037 (void)SDMMC_ConfigData(hmmc->Instance, &config);
1039 __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
1041 /* Write Blocks in Polling mode */
1042 if(NumberOfBlocks > 1U)
1044 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
1046 /* Write Multi Block command */
1047 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
1049 else
1051 hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
1053 /* Write Single Block command */
1054 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
1056 if(errorstate != HAL_MMC_ERROR_NONE)
1058 /* Clear all the static flags */
1059 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1060 hmmc->ErrorCode |= errorstate;
1061 hmmc->State = HAL_MMC_STATE_READY;
1062 return HAL_ERROR;
1065 /* Enable transfer interrupts */
1066 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_FLAG_TXFIFOHE));
1068 return HAL_OK;
1070 else
1072 return HAL_BUSY;
1077 * @brief Reads block(s) from a specified address in a card. The Data transfer
1078 * is managed by DMA mode.
1079 * @note This API should be followed by a check on the card state through
1080 * HAL_MMC_GetCardState().
1081 * @note You could also check the DMA transfer process through the MMC Rx
1082 * interrupt event.
1083 * @param hmmc: Pointer MMC handle
1084 * @param pData: Pointer to the buffer that will contain the received data
1085 * @param BlockAdd: Block Address from where data is to be read
1086 * @param NumberOfBlocks: Number of blocks to read.
1087 * @retval HAL status
1089 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1091 SDMMC_DataInitTypeDef config;
1092 uint32_t errorstate;
1093 uint32_t add = BlockAdd;
1095 if(NULL == pData)
1097 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1098 return HAL_ERROR;
1101 if(hmmc->State == HAL_MMC_STATE_READY)
1103 hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
1105 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1107 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1108 return HAL_ERROR;
1111 hmmc->State = HAL_MMC_STATE_BUSY;
1113 /* Initialize data control register */
1114 hmmc->Instance->DCTRL = 0U;
1116 hmmc->pRxBuffPtr = pData;
1117 hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1119 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1121 add *= 512U;
1124 /* Configure the MMC DPSM (Data Path State Machine) */
1125 config.DataTimeOut = SDMMC_DATATIMEOUT;
1126 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
1127 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1128 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
1129 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
1130 config.DPSM = SDMMC_DPSM_DISABLE;
1131 (void)SDMMC_ConfigData(hmmc->Instance, &config);
1133 __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
1134 hmmc->Instance->IDMABASE0 = (uint32_t) pData ;
1135 hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
1137 /* Read Blocks in DMA mode */
1138 if(NumberOfBlocks > 1U)
1140 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1142 /* Read Multi Block command */
1143 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
1145 else
1147 hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1149 /* Read Single Block command */
1150 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
1152 if(errorstate != HAL_MMC_ERROR_NONE)
1154 /* Clear all the static flags */
1155 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1156 hmmc->ErrorCode = errorstate;
1157 hmmc->State = HAL_MMC_STATE_READY;
1158 return HAL_ERROR;
1161 /* Enable transfer interrupts */
1162 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND));
1164 return HAL_OK;
1166 else
1168 return HAL_BUSY;
1173 * @brief Writes block(s) to a specified address in a card. The Data transfer
1174 * is managed by DMA mode.
1175 * @note This API should be followed by a check on the card state through
1176 * HAL_MMC_GetCardState().
1177 * @note You could also check the DMA transfer process through the MMC Tx
1178 * interrupt event.
1179 * @param hmmc: Pointer to MMC handle
1180 * @param pData: Pointer to the buffer that will contain the data to transmit
1181 * @param BlockAdd: Block Address where data will be written
1182 * @param NumberOfBlocks: Number of blocks to write
1183 * @retval HAL status
1185 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1187 SDMMC_DataInitTypeDef config;
1188 uint32_t errorstate;
1189 uint32_t add = BlockAdd;
1191 if(NULL == pData)
1193 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1194 return HAL_ERROR;
1197 if(hmmc->State == HAL_MMC_STATE_READY)
1199 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1201 if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1203 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1204 return HAL_ERROR;
1207 hmmc->State = HAL_MMC_STATE_BUSY;
1209 /* Initialize data control register */
1210 hmmc->Instance->DCTRL = 0U;
1212 hmmc->pTxBuffPtr = pData;
1213 hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1215 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1217 add *= 512U;
1220 /* Configure the MMC DPSM (Data Path State Machine) */
1221 config.DataTimeOut = SDMMC_DATATIMEOUT;
1222 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
1223 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
1224 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
1225 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
1226 config.DPSM = SDMMC_DPSM_DISABLE;
1227 (void)SDMMC_ConfigData(hmmc->Instance, &config);
1229 __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
1231 hmmc->Instance->IDMABASE0 = (uint32_t) pData ;
1232 hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF;
1234 /* Write Blocks in Polling mode */
1235 if(NumberOfBlocks > 1U)
1237 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1239 /* Write Multi Block command */
1240 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
1242 else
1244 hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1246 /* Write Single Block command */
1247 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
1249 if(errorstate != HAL_MMC_ERROR_NONE)
1251 /* Clear all the static flags */
1252 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1253 hmmc->ErrorCode |= errorstate;
1254 hmmc->State = HAL_MMC_STATE_READY;
1255 return HAL_ERROR;
1258 /* Enable transfer interrupts */
1259 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND));
1261 return HAL_OK;
1263 else
1265 return HAL_BUSY;
1270 * @brief Erases the specified memory area of the given MMC card.
1271 * @note This API should be followed by a check on the card state through
1272 * HAL_MMC_GetCardState().
1273 * @param hmmc: Pointer to MMC handle
1274 * @param BlockStartAdd: Start Block address
1275 * @param BlockEndAdd: End Block address
1276 * @retval HAL status
1278 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
1280 uint32_t errorstate;
1281 uint32_t start_add = BlockStartAdd;
1282 uint32_t end_add = BlockEndAdd;
1284 if(hmmc->State == HAL_MMC_STATE_READY)
1286 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1288 if(end_add < start_add)
1290 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1291 return HAL_ERROR;
1294 if(end_add > (hmmc->MmcCard.LogBlockNbr))
1296 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1297 return HAL_ERROR;
1300 hmmc->State = HAL_MMC_STATE_BUSY;
1302 /* Check if the card command class supports erase command */
1303 if(((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
1305 /* Clear all the static flags */
1306 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1307 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
1308 hmmc->State = HAL_MMC_STATE_READY;
1309 return HAL_ERROR;
1312 if((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
1314 /* Clear all the static flags */
1315 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1316 hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
1317 hmmc->State = HAL_MMC_STATE_READY;
1318 return HAL_ERROR;
1321 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
1323 start_add *= 512U;
1324 end_add *= 512U;
1327 /* Send CMD35 MMC_ERASE_GRP_START with argument as addr */
1328 errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
1329 if(errorstate != HAL_MMC_ERROR_NONE)
1331 /* Clear all the static flags */
1332 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1333 hmmc->ErrorCode |= errorstate;
1334 hmmc->State = HAL_MMC_STATE_READY;
1335 return HAL_ERROR;
1338 /* Send CMD36 MMC_ERASE_GRP_END with argument as addr */
1339 errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
1340 if(errorstate != HAL_MMC_ERROR_NONE)
1342 /* Clear all the static flags */
1343 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1344 hmmc->ErrorCode |= errorstate;
1345 hmmc->State = HAL_MMC_STATE_READY;
1346 return HAL_ERROR;
1349 /* Send CMD38 ERASE */
1350 errorstate = SDMMC_CmdErase(hmmc->Instance, 0UL);
1351 if(errorstate != HAL_MMC_ERROR_NONE)
1353 /* Clear all the static flags */
1354 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
1355 hmmc->ErrorCode |= errorstate;
1356 hmmc->State = HAL_MMC_STATE_READY;
1357 return HAL_ERROR;
1360 hmmc->State = HAL_MMC_STATE_READY;
1362 return HAL_OK;
1364 else
1366 return HAL_BUSY;
1371 * @brief This function handles MMC card interrupt request.
1372 * @param hmmc: Pointer to MMC handle
1373 * @retval None
1375 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
1377 uint32_t errorstate;
1378 uint32_t context = hmmc->Context;
1380 /* Check for SDMMC interrupt flags */
1381 if((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1383 MMC_Read_IT(hmmc);
1386 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) != RESET)
1388 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND);
1390 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT |\
1391 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR | SDMMC_IT_TXFIFOHE |\
1392 SDMMC_IT_RXFIFOHF);
1394 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
1395 __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
1397 if((context & MMC_CONTEXT_DMA) != 0U)
1399 hmmc->Instance->DLEN = 0;
1400 hmmc->Instance->DCTRL = 0;
1401 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA ;
1403 /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1404 if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1406 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1407 if(errorstate != HAL_MMC_ERROR_NONE)
1409 hmmc->ErrorCode |= errorstate;
1410 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1411 hmmc->ErrorCallback(hmmc);
1412 #else
1413 HAL_MMC_ErrorCallback(hmmc);
1414 #endif
1418 /* Clear all the static flags */
1419 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1421 hmmc->State = HAL_MMC_STATE_READY;
1422 if(((context & MMC_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1424 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1425 hmmc->TxCpltCallback(hmmc);
1426 #else
1427 HAL_MMC_TxCpltCallback(hmmc);
1428 #endif
1430 if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1432 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1433 hmmc->RxCpltCallback(hmmc);
1434 #else
1435 HAL_MMC_RxCpltCallback(hmmc);
1436 #endif
1439 else if((context & MMC_CONTEXT_IT) != 0U)
1441 /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1442 if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
1444 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1445 if(errorstate != HAL_MMC_ERROR_NONE)
1447 hmmc->ErrorCode |= errorstate;
1448 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1449 hmmc->ErrorCallback(hmmc);
1450 #else
1451 HAL_MMC_ErrorCallback(hmmc);
1452 #endif
1456 /* Clear all the static flags */
1457 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1459 hmmc->State = HAL_MMC_STATE_READY;
1460 if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
1462 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1463 hmmc->RxCpltCallback(hmmc);
1464 #else
1465 HAL_MMC_RxCpltCallback(hmmc);
1466 #endif
1468 else
1470 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1471 hmmc->TxCpltCallback(hmmc);
1472 #else
1473 HAL_MMC_TxCpltCallback(hmmc);
1474 #endif
1477 else
1479 /* Nothing to do */
1483 else if((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
1485 MMC_Write_IT(hmmc);
1488 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL| SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET)
1490 /* Set Error code */
1491 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL) != RESET)
1493 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
1495 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DTIMEOUT) != RESET)
1497 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
1499 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXOVERR) != RESET)
1501 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
1503 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXUNDERR) != RESET)
1505 hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
1508 /* Clear All flags */
1509 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
1511 /* Disable all interrupts */
1512 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
1513 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
1515 __SDMMC_CMDTRANS_DISABLE( hmmc->Instance);
1516 hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
1517 hmmc->Instance->CMD |= SDMMC_CMD_CMDSTOP;
1518 hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
1519 hmmc->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP);
1520 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DABORT);
1522 if((context & MMC_CONTEXT_IT) != 0U)
1524 /* Set the MMC state to ready to be able to start again the process */
1525 hmmc->State = HAL_MMC_STATE_READY;
1526 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1527 hmmc->ErrorCallback(hmmc);
1528 #else
1529 HAL_MMC_ErrorCallback(hmmc);
1530 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1532 else if((context & MMC_CONTEXT_DMA) != 0U)
1534 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
1536 /* Disable Internal DMA */
1537 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC);
1538 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
1540 /* Set the MMC state to ready to be able to start again the process */
1541 hmmc->State = HAL_MMC_STATE_READY;
1542 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1543 hmmc->ErrorCallback(hmmc);
1544 #else
1545 HAL_MMC_ErrorCallback(hmmc);
1546 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
1549 else
1551 /* Nothing to do */
1555 else if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_IDMABTC) != RESET)
1557 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_IT_IDMABTC);
1558 if(READ_BIT(hmmc->Instance->IDMACTRL, SDMMC_IDMA_IDMABACT) == 0U)
1560 /* Current buffer is buffer0, Transfer complete for buffer1 */
1561 if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
1563 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1564 hmmc->Write_DMADblBuf1CpltCallback(hmmc);
1565 #else
1566 HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(hmmc);
1567 #endif
1569 else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
1571 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1572 hmmc->Read_DMADblBuf1CpltCallback(hmmc);
1573 #else
1574 HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(hmmc);
1575 #endif
1578 else /* MMC_DMA_BUFFER1 */
1580 /* Current buffer is buffer1, Transfer complete for buffer0 */
1581 if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
1583 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1584 hmmc->Write_DMADblBuf0CpltCallback(hmmc);
1585 #else
1586 HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(hmmc);
1587 #endif
1589 else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */
1591 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1592 hmmc->Read_DMADblBuf0CpltCallback(hmmc);
1593 #else
1594 HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(hmmc);
1595 #endif
1600 else
1602 /* Nothing to do */
1607 * @brief return the MMC state
1608 * @param hmmc: Pointer to mmc handle
1609 * @retval HAL state
1611 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
1613 return hmmc->State;
1617 * @brief Return the MMC error code
1618 * @param hmmc : Pointer to a MMC_HandleTypeDef structure that contains
1619 * the configuration information.
1620 * @retval MMC Error Code
1622 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
1624 return hmmc->ErrorCode;
1628 * @brief Tx Transfer completed callbacks
1629 * @param hmmc: Pointer to MMC handle
1630 * @retval None
1632 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
1634 /* Prevent unused argument(s) compilation warning */
1635 UNUSED(hmmc);
1637 /* NOTE : This function should not be modified, when the callback is needed,
1638 the HAL_MMC_TxCpltCallback can be implemented in the user file
1643 * @brief Rx Transfer completed callbacks
1644 * @param hmmc: Pointer MMC handle
1645 * @retval None
1647 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
1649 /* Prevent unused argument(s) compilation warning */
1650 UNUSED(hmmc);
1652 /* NOTE : This function should not be modified, when the callback is needed,
1653 the HAL_MMC_RxCpltCallback can be implemented in the user file
1658 * @brief MMC error callbacks
1659 * @param hmmc: Pointer MMC handle
1660 * @retval None
1662 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
1664 /* Prevent unused argument(s) compilation warning */
1665 UNUSED(hmmc);
1667 /* NOTE : This function should not be modified, when the callback is needed,
1668 the HAL_MMC_ErrorCallback can be implemented in the user file
1673 * @brief MMC Abort callbacks
1674 * @param hmmc: Pointer MMC handle
1675 * @retval None
1677 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
1679 /* Prevent unused argument(s) compilation warning */
1680 UNUSED(hmmc);
1682 /* NOTE : This function should not be modified, when the callback is needed,
1683 the HAL_MMC_AbortCallback can be implemented in the user file
1687 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1689 * @brief Register a User MMC Callback
1690 * To be used instead of the weak (surcharged) predefined callback
1691 * @param hmmc : MMC handle
1692 * @param CallbackId : ID of the callback to be registered
1693 * This parameter can be one of the following values:
1694 * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
1695 * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
1696 * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
1697 * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
1698 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Rx Double buffer 0 Callback ID
1699 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Rx Double buffer 1 Callback ID
1700 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID
1701 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID
1702 * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
1703 * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1704 * @param pCallback : pointer to the Callback function
1705 * @retval status
1707 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
1709 HAL_StatusTypeDef status = HAL_OK;
1711 if(pCallback == NULL)
1713 /* Update the error code */
1714 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1715 return HAL_ERROR;
1718 /* Process locked */
1719 __HAL_LOCK(hmmc);
1721 if(hmmc->State == HAL_MMC_STATE_READY)
1723 switch (CallbackId)
1725 case HAL_MMC_TX_CPLT_CB_ID :
1726 hmmc->TxCpltCallback = pCallback;
1727 break;
1728 case HAL_MMC_RX_CPLT_CB_ID :
1729 hmmc->RxCpltCallback = pCallback;
1730 break;
1731 case HAL_MMC_ERROR_CB_ID :
1732 hmmc->ErrorCallback = pCallback;
1733 break;
1734 case HAL_MMC_ABORT_CB_ID :
1735 hmmc->AbortCpltCallback = pCallback;
1736 break;
1737 case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID :
1738 hmmc->Read_DMADblBuf0CpltCallback = pCallback;
1739 break;
1740 case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID :
1741 hmmc->Read_DMADblBuf1CpltCallback = pCallback;
1742 break;
1743 case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
1744 hmmc->Write_DMADblBuf0CpltCallback = pCallback;
1745 break;
1746 case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
1747 hmmc->Write_DMADblBuf1CpltCallback = pCallback;
1748 break;
1749 case HAL_MMC_MSP_INIT_CB_ID :
1750 hmmc->MspInitCallback = pCallback;
1751 break;
1752 case HAL_MMC_MSP_DEINIT_CB_ID :
1753 hmmc->MspDeInitCallback = pCallback;
1754 break;
1755 default :
1756 /* Update the error code */
1757 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1758 /* update return status */
1759 status = HAL_ERROR;
1760 break;
1763 else if (hmmc->State == HAL_MMC_STATE_RESET)
1765 switch (CallbackId)
1767 case HAL_MMC_MSP_INIT_CB_ID :
1768 hmmc->MspInitCallback = pCallback;
1769 break;
1770 case HAL_MMC_MSP_DEINIT_CB_ID :
1771 hmmc->MspDeInitCallback = pCallback;
1772 break;
1773 default :
1774 /* Update the error code */
1775 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1776 /* update return status */
1777 status = HAL_ERROR;
1778 break;
1781 else
1783 /* Update the error code */
1784 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1785 /* update return status */
1786 status = HAL_ERROR;
1789 /* Release Lock */
1790 __HAL_UNLOCK(hmmc);
1791 return status;
1795 * @brief Unregister a User MMC Callback
1796 * MMC Callback is redirected to the weak (surcharged) predefined callback
1797 * @param hmmc : MMC handle
1798 * @param CallbackId : ID of the callback to be unregistered
1799 * This parameter can be one of the following values:
1800 * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
1801 * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
1802 * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
1803 * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
1804 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Rx Double buffer 0 Callback ID
1805 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Rx Double buffer 1 Callback ID
1806 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID
1807 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID
1808 * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
1809 * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1810 * @retval status
1812 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
1814 HAL_StatusTypeDef status = HAL_OK;
1816 /* Process locked */
1817 __HAL_LOCK(hmmc);
1819 if(hmmc->State == HAL_MMC_STATE_READY)
1821 switch (CallbackId)
1823 case HAL_MMC_TX_CPLT_CB_ID :
1824 hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
1825 break;
1826 case HAL_MMC_RX_CPLT_CB_ID :
1827 hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
1828 break;
1829 case HAL_MMC_ERROR_CB_ID :
1830 hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
1831 break;
1832 case HAL_MMC_ABORT_CB_ID :
1833 hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
1834 break;
1835 case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID :
1836 hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback;
1837 break;
1838 case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID :
1839 hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback;
1840 break;
1841 case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID :
1842 hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback;
1843 break;
1844 case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID :
1845 hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback;
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;
1861 else if (hmmc->State == HAL_MMC_STATE_RESET)
1863 switch (CallbackId)
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;
1879 else
1881 /* Update the error code */
1882 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1883 /* update return status */
1884 status = HAL_ERROR;
1887 /* Release Lock */
1888 __HAL_UNLOCK(hmmc);
1889 return status;
1891 #endif
1894 * @}
1897 /** @addtogroup MMC_Exported_Functions_Group3
1898 * @brief management functions
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
1908 @endverbatim
1909 * @{
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
1920 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
1922 pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
1924 pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
1926 pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
1928 pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
1930 pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
1932 pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
1934 pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
1936 pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
1938 pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
1940 pCID->Reserved2 = 1U;
1942 return HAL_OK;
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
1953 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
1955 uint32_t block_nbr = 0;
1957 pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
1959 pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
1961 pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
1963 pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
1965 pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
1967 pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
1969 pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
1971 pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
1973 pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
1975 pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
1977 pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
1979 pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
1981 pCSD->Reserved2 = 0U; /*!< Reserved */
1983 if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
1985 return HAL_ERROR;
1988 if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
1990 pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
1992 pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
1994 pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
1996 pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
1998 pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
2000 pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
2002 hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
2003 hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
2004 hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
2006 hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
2007 hmmc->MmcCard.LogBlockSize = 512U;
2009 else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
2011 hmmc->MmcCard.BlockNbr = block_nbr;
2012 hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
2013 hmmc->MmcCard.BlockSize = 512U;
2014 hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
2016 else
2018 /* Clear all the static flags */
2019 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2020 hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2021 hmmc->State = HAL_MMC_STATE_READY;
2022 return HAL_ERROR;
2025 pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
2027 pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
2029 pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
2031 pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
2033 pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
2035 pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
2037 pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
2039 pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
2041 pCSD->Reserved3 = 0;
2043 pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
2045 pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
2047 pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
2049 pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
2051 pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
2053 pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
2055 pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
2057 pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
2059 pCSD->Reserved4 = 1;
2061 return HAL_OK;
2065 * @brief Gets the MMC card info.
2066 * @param hmmc: Pointer to MMC handle
2067 * @param pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
2068 * will contain the MMC card status information
2069 * @retval HAL status
2071 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
2073 pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType);
2074 pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class);
2075 pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd);
2076 pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr);
2077 pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize);
2078 pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
2079 pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
2081 return HAL_OK;
2085 * @brief Enables wide bus operation for the requested card if supported by
2086 * card.
2087 * @param hmmc: Pointer to MMC handle
2088 * @param WideMode: Specifies the MMC card wide bus mode
2089 * This parameter can be one of the following values:
2090 * @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer
2091 * @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer
2092 * @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer
2093 * @retval HAL status
2095 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
2097 uint32_t count;
2098 SDMMC_InitTypeDef Init;
2099 uint32_t errorstate;
2100 uint32_t response = 0U;
2102 /* Check the parameters */
2103 assert_param(IS_SDMMC_BUS_WIDE(WideMode));
2105 /* Chnage Satte */
2106 hmmc->State = HAL_MMC_STATE_BUSY;
2108 if(WideMode == SDMMC_BUS_WIDE_8B)
2110 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
2112 else if(WideMode == SDMMC_BUS_WIDE_4B)
2114 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
2116 else if(WideMode == SDMMC_BUS_WIDE_1B)
2118 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
2120 else
2122 /* WideMode is not a valid argument*/
2123 errorstate = HAL_MMC_ERROR_PARAM;
2126 /* Check for switch error and violation of the trial number of sending CMD 13 */
2127 if(errorstate == HAL_MMC_ERROR_NONE)
2129 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2130 count = SDMMC_MAX_TRIAL;
2133 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2134 if(errorstate != HAL_MMC_ERROR_NONE)
2136 break;
2139 /* Get command response */
2140 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2141 count--;
2142 }while(((response & 0x100U) == 0U) && (count != 0U));
2144 /* Check the status after the switch command execution */
2145 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
2147 /* Check the bit SWITCH_ERROR of the device status */
2148 if ((response & 0x80U) != 0U)
2150 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
2152 else
2154 /* Configure the SDMMC peripheral */
2155 Init.ClockEdge = hmmc->Init.ClockEdge;
2156 Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
2157 Init.BusWide = WideMode;
2158 Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
2159 Init.ClockDiv = hmmc->Init.ClockDiv;
2160 (void)SDMMC_Init(hmmc->Instance, Init);
2163 else if (count == 0U)
2165 errorstate = SDMMC_ERROR_TIMEOUT;
2167 else
2169 /* Nothing to do */
2173 /* Change State */
2174 hmmc->State = HAL_MMC_STATE_READY;
2176 if(errorstate != HAL_MMC_ERROR_NONE)
2178 /* Clear all the static flags */
2179 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2180 hmmc->ErrorCode |= errorstate;
2181 return HAL_ERROR;
2184 return HAL_OK;
2188 * @brief Configure the speed bus mode
2189 * @param hmmc: Pointer to the MMC handle
2190 * @param SpeedMode: Specifies the MMC card speed bus mode
2191 * This parameter can be one of the following values:
2192 * @arg SDMMC_SPEED_MODE_AUTO: Max speed mode supported by the card
2193 * @arg SDMMC_SPEED_MODE_DEFAULT: Default Speed (MMC @ 26MHz)
2194 * @arg SDMMC_SPEED_MODE_HIGH: High Speed (MMC @ 52 MHz)
2195 * @arg SDMMC_SPEED_MODE_DDR: High Speed DDR (MMC DDR @ 52 MHz)
2196 * @retval HAL status
2199 HAL_StatusTypeDef HAL_MMC_ConfigSpeedBusOperation(MMC_HandleTypeDef *hmmc, uint32_t SpeedMode)
2201 uint32_t tickstart;
2202 HAL_StatusTypeDef status = HAL_OK;
2203 uint32_t device_type;
2204 uint32_t errorstate;
2206 /* Check the parameters */
2207 assert_param(IS_SDMMC_SPEED_MODE(SpeedMode));
2208 /* Change State */
2209 hmmc->State = HAL_MMC_STATE_BUSY;
2211 if(MMC_ReadExtCSD(hmmc, &device_type, 196, 0x0FFFFFFFU) != HAL_OK) /* Field DEVICE_TYPE [196] */
2213 return HAL_ERROR;
2216 switch (SpeedMode)
2218 case SDMMC_SPEED_MODE_AUTO:
2220 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
2222 /* High Speed DDR mode allowed */
2223 errorstate = MMC_HighSpeed(hmmc, ENABLE);
2224 if(errorstate != HAL_MMC_ERROR_NONE)
2226 hmmc->ErrorCode |= errorstate;
2228 else
2230 errorstate = MMC_DDR_Mode(hmmc, ENABLE);
2231 if(errorstate != HAL_MMC_ERROR_NONE)
2233 hmmc->ErrorCode |= errorstate;
2237 else if ((device_type & 0x02U) != 0U)
2239 /* High Speed mode allowed */
2240 errorstate = MMC_HighSpeed(hmmc, ENABLE);
2241 if(errorstate != HAL_MMC_ERROR_NONE)
2243 hmmc->ErrorCode |= errorstate;
2246 else
2248 /* Nothing to do : keep current speed */
2250 break;
2252 case SDMMC_SPEED_MODE_DDR:
2254 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U))
2256 /* High Speed DDR mode allowed */
2257 errorstate = MMC_HighSpeed(hmmc, ENABLE);
2258 if(errorstate != HAL_MMC_ERROR_NONE)
2260 hmmc->ErrorCode |= errorstate;
2262 else
2264 errorstate = MMC_DDR_Mode(hmmc, ENABLE);
2265 if(errorstate != HAL_MMC_ERROR_NONE)
2267 hmmc->ErrorCode |= errorstate;
2271 else
2273 /* High Speed DDR mode not allowed */
2274 hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2275 status = HAL_ERROR;
2277 break;
2279 case SDMMC_SPEED_MODE_HIGH:
2281 if ((device_type & 0x02U) != 0U)
2283 /* High Speed mode allowed */
2284 errorstate = MMC_HighSpeed(hmmc, ENABLE);
2285 if(errorstate != HAL_MMC_ERROR_NONE)
2287 hmmc->ErrorCode |= errorstate;
2290 else
2292 /* High Speed mode not allowed */
2293 hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2294 status = HAL_ERROR;
2296 break;
2298 case SDMMC_SPEED_MODE_DEFAULT:
2300 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U)
2302 /* High Speed DDR mode activated */
2303 errorstate = MMC_DDR_Mode(hmmc, DISABLE);
2304 if(errorstate != HAL_MMC_ERROR_NONE)
2306 hmmc->ErrorCode |= errorstate;
2309 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U)
2311 /* High Speed mode activated */
2312 errorstate = MMC_HighSpeed(hmmc, DISABLE);
2313 if(errorstate != HAL_MMC_ERROR_NONE)
2315 hmmc->ErrorCode |= errorstate;
2318 break;
2320 default:
2321 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2322 status = HAL_ERROR;
2323 break;
2326 /* Verify that MMC card is ready to use after Speed mode switch*/
2327 tickstart = HAL_GetTick();
2328 while ((HAL_MMC_GetCardState(hmmc) != HAL_MMC_CARD_TRANSFER))
2330 if ((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT)
2332 hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT;
2333 hmmc->State = HAL_MMC_STATE_READY;
2334 return HAL_TIMEOUT;
2338 /* Change State */
2339 hmmc->State = HAL_MMC_STATE_READY;
2340 return status;
2344 * @brief Gets the current mmc card data state.
2345 * @param hmmc: pointer to MMC handle
2346 * @retval Card state
2348 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
2350 uint32_t cardstate;
2351 uint32_t errorstate;
2352 uint32_t resp1 = 0U;
2354 errorstate = MMC_SendStatus(hmmc, &resp1);
2355 if(errorstate != HAL_MMC_ERROR_NONE)
2357 hmmc->ErrorCode |= errorstate;
2360 cardstate = ((resp1 >> 9U) & 0x0FU);
2362 return (HAL_MMC_CardStateTypeDef)cardstate;
2366 * @brief Abort the current transfer and disable the MMC.
2367 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
2368 * the configuration information for MMC module.
2369 * @retval HAL status
2371 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
2373 HAL_MMC_CardStateTypeDef CardState;
2375 /* DIsable All interrupts */
2376 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2377 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2379 /* Clear All flags */
2380 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2382 /* If IDMA Context, disable Internal DMA */
2383 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
2385 hmmc->State = HAL_MMC_STATE_READY;
2387 /* Initialize the MMC operation */
2388 hmmc->Context = MMC_CONTEXT_NONE;
2390 CardState = HAL_MMC_GetCardState(hmmc);
2391 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2393 hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2395 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2397 return HAL_ERROR;
2399 return HAL_OK;
2403 * @brief Abort the current transfer and disable the MMC (IT mode).
2404 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
2405 * the configuration information for MMC module.
2406 * @retval HAL status
2408 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
2410 HAL_MMC_CardStateTypeDef CardState;
2412 /* DIsable All interrupts */
2413 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT|\
2414 SDMMC_IT_TXUNDERR| SDMMC_IT_RXOVERR);
2416 /* If IDMA Context, disable Internal DMA */
2417 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA;
2419 /* Clear All flags */
2420 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
2422 CardState = HAL_MMC_GetCardState(hmmc);
2423 hmmc->State = HAL_MMC_STATE_READY;
2425 if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2427 hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2429 if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2431 return HAL_ERROR;
2433 else
2435 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2436 hmmc->AbortCpltCallback(hmmc);
2437 #else
2438 HAL_MMC_AbortCallback(hmmc);
2439 #endif
2442 return HAL_OK;
2446 * @brief Perform specific commands sequence for the different type of erase.
2447 * @note This API should be followed by a check on the card state through
2448 * HAL_MMC_GetCardState().
2449 * @param hmmc Pointer to MMC handle
2450 * @param EraseType Specifies the type of erase to be performed
2451 * This parameter can be one of the following values:
2452 * @arg HAL_MMC_ERASE Erase the erase groups identified by CMD35 & 36
2453 * @arg HAL_MMC_TRIM Erase the write blocks identified by CMD35 & 36
2454 * @arg HAL_MMC_DISCARD Discard the write blocks identified by CMD35 & 36
2455 * @arg HAL_MMC_SECURE_ERASE Perform a secure purge according SRT on the erase groups identified by CMD35 & 36
2456 * @arg HAL_MMC_SECURE_TRIM_STEP1 Mark the write blocks identified by CMD35 & 36 for secure erase
2457 * @arg HAL_MMC_SECURE_TRIM_STEP2 Perform a secure purge according SRT on the write blocks previously identified
2458 * @param BlockStartAdd Start Block address
2459 * @param BlockEndAdd End Block address
2460 * @retval HAL status
2462 HAL_StatusTypeDef HAL_MMC_EraseSequence(MMC_HandleTypeDef *hmmc, uint32_t EraseType, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
2464 uint32_t errorstate;
2465 uint32_t start_add = BlockStartAdd;
2466 uint32_t end_add = BlockEndAdd;
2467 uint32_t tickstart = HAL_GetTick();
2469 /* Check the erase type value is correct */
2470 assert_param(IS_MMC_ERASE_TYPE(EraseType));
2472 /* Check the coherence between start and end address */
2473 if(end_add < start_add)
2475 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2476 return HAL_ERROR;
2479 /* Check that the end address is not out of range of device memory */
2480 if(end_add > (hmmc->MmcCard.LogBlockNbr))
2482 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
2483 return HAL_ERROR;
2486 /* Check if the card command class supports erase command */
2487 if(((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U)
2489 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2490 return HAL_ERROR;
2493 /* Check the state of the driver */
2494 if(hmmc->State == HAL_MMC_STATE_READY)
2496 /* Change State */
2497 hmmc->State = HAL_MMC_STATE_BUSY;
2499 /* Check that the card is not locked */
2500 if((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
2502 hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
2503 hmmc->State = HAL_MMC_STATE_READY;
2504 return HAL_ERROR;
2507 /* In case of low capacity card, the address is not block number but bytes */
2508 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2510 start_add *= 512U;
2511 end_add *= 512U;
2514 /* Send CMD35 MMC_ERASE_GRP_START with start address as argument */
2515 errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
2516 if(errorstate == HAL_MMC_ERROR_NONE)
2518 /* Send CMD36 MMC_ERASE_GRP_END with end address as argument */
2519 errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
2520 if(errorstate == HAL_MMC_ERROR_NONE)
2522 /* Send CMD38 ERASE with erase type as argument */
2523 errorstate = SDMMC_CmdErase(hmmc->Instance, EraseType);
2524 if(errorstate == HAL_MMC_ERROR_NONE)
2526 if ((EraseType == HAL_MMC_SECURE_ERASE) || (EraseType == HAL_MMC_SECURE_TRIM_STEP2))
2528 /* Wait that the device is ready by checking the D0 line */
2529 while((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
2531 if((HAL_GetTick()-tickstart) >= SDMMC_MAXERASETIMEOUT)
2533 errorstate = HAL_MMC_ERROR_TIMEOUT;
2537 /* Clear the flag corresponding to end D0 bus line */
2538 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
2544 /* Change State */
2545 hmmc->State = HAL_MMC_STATE_READY;
2547 /* Manage errors */
2548 if(errorstate != HAL_MMC_ERROR_NONE)
2550 /* Clear all the static flags */
2551 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2552 hmmc->ErrorCode |= errorstate;
2554 if(errorstate != HAL_MMC_ERROR_TIMEOUT)
2556 return HAL_ERROR;
2558 else
2560 return HAL_TIMEOUT;
2563 else
2565 return HAL_OK;
2568 else
2570 return HAL_BUSY;
2575 * @brief Perform sanitize operation on the device.
2576 * @note This API should be followed by a check on the card state through
2577 * HAL_MMC_GetCardState().
2578 * @param hmmc Pointer to MMC handle
2579 * @retval HAL status
2581 HAL_StatusTypeDef HAL_MMC_Sanitize(MMC_HandleTypeDef *hmmc)
2583 uint32_t errorstate, response = 0U, count;
2584 uint32_t tickstart = HAL_GetTick();
2586 /* Check the state of the driver */
2587 if(hmmc->State == HAL_MMC_STATE_READY)
2589 /* Change State */
2590 hmmc->State = HAL_MMC_STATE_BUSY;
2592 /* Index : 165 - Value : 0x01 */
2593 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03A50100U);
2594 if(errorstate == HAL_MMC_ERROR_NONE)
2596 /* Wait that the device is ready by checking the D0 line */
2597 while((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE))
2599 if((HAL_GetTick()-tickstart) >= SDMMC_MAXERASETIMEOUT)
2601 errorstate = HAL_MMC_ERROR_TIMEOUT;
2605 /* Clear the flag corresponding to end D0 bus line */
2606 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END);
2608 if(errorstate == HAL_MMC_ERROR_NONE)
2610 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2611 count = SDMMC_MAX_TRIAL;
2614 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2615 if(errorstate != HAL_MMC_ERROR_NONE)
2617 break;
2620 /* Get command response */
2621 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2622 count--;
2623 }while(((response & 0x100U) == 0U) && (count != 0U));
2625 /* Check the status after the switch command execution */
2626 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
2628 /* Check the bit SWITCH_ERROR of the device status */
2629 if ((response & 0x80U) != 0U)
2631 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
2634 else if (count == 0U)
2636 errorstate = SDMMC_ERROR_TIMEOUT;
2638 else
2640 /* Nothing to do */
2645 /* Change State */
2646 hmmc->State = HAL_MMC_STATE_READY;
2648 /* Manage errors */
2649 if(errorstate != HAL_MMC_ERROR_NONE)
2651 /* Clear all the static flags */
2652 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2653 hmmc->ErrorCode |= errorstate;
2655 if(errorstate != HAL_MMC_ERROR_TIMEOUT)
2657 return HAL_ERROR;
2659 else
2661 return HAL_TIMEOUT;
2664 else
2666 return HAL_OK;
2669 else
2671 return HAL_BUSY;
2676 * @brief Configure the Secure Removal Type (SRT) in the Extended CSD register.
2677 * @note This API should be followed by a check on the card state through
2678 * HAL_MMC_GetCardState().
2679 * @param hmmc Pointer to MMC handle
2680 * @param SRTMode Specifies the type of erase to be performed
2681 * This parameter can be one of the following values:
2682 * @arg HAL_MMC_SRT_ERASE Information removed by an erase
2683 * @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character followed by an erase
2684 * @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character, its complement then a random character
2685 * @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined
2686 * @retval HAL status
2688 HAL_StatusTypeDef HAL_MMC_ConfigSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t SRTMode)
2690 uint32_t srt, errorstate, response = 0U, count;
2692 /* Check the erase type value is correct */
2693 assert_param(IS_MMC_SRT_TYPE(SRTMode));
2695 /* Check the state of the driver */
2696 if(hmmc->State == HAL_MMC_STATE_READY)
2698 /* Get the supported values by the device */
2699 if(HAL_MMC_GetSupportedSecRemovalType(hmmc, &srt) == HAL_OK)
2701 /* Change State */
2702 hmmc->State = HAL_MMC_STATE_BUSY;
2704 /* Check the value passed as parameter is supported by the device */
2705 if((SRTMode & srt) != 0U)
2707 /* Index : 16 - Value : SRTMode */
2708 srt |= ((POSITION_VAL(SRTMode)) << 4U);
2709 errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03100000U | (srt << 8U)));
2710 if(errorstate == HAL_MMC_ERROR_NONE)
2712 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2713 count = SDMMC_MAX_TRIAL;
2716 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2717 if(errorstate != HAL_MMC_ERROR_NONE)
2719 break;
2722 /* Get command response */
2723 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2724 count--;
2725 }while(((response & 0x100U) == 0U) && (count != 0U));
2727 /* Check the status after the switch command execution */
2728 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
2730 /* Check the bit SWITCH_ERROR of the device status */
2731 if ((response & 0x80U) != 0U)
2733 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
2736 else if (count == 0U)
2738 errorstate = SDMMC_ERROR_TIMEOUT;
2740 else
2742 /* Nothing to do */
2746 else
2748 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
2751 /* Change State */
2752 hmmc->State = HAL_MMC_STATE_READY;
2754 else
2756 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
2759 /* Manage errors */
2760 if(errorstate != HAL_MMC_ERROR_NONE)
2762 /* Clear all the static flags */
2763 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2764 hmmc->ErrorCode |= errorstate;
2765 return HAL_ERROR;
2767 else
2769 return HAL_OK;
2772 else
2774 return HAL_BUSY;
2779 * @brief Gets the supported values of the the Secure Removal Type (SRT).
2780 * @param hmmc pointer to MMC handle
2781 * @param SupportedSRT pointer for supported SRT value
2782 * This parameter is a bit field of the following values:
2783 * @arg HAL_MMC_SRT_ERASE Information removed by an erase
2784 * @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character followed by an erase
2785 * @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character, its complement then a random character
2786 * @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined
2787 * @retval HAL status
2789 HAL_StatusTypeDef HAL_MMC_GetSupportedSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t *SupportedSRT)
2791 uint32_t srt = 0U;
2792 uint32_t errorstate = SDMMC_ERROR_NONE;
2794 /* Check the state of the driver */
2795 if(hmmc->State == HAL_MMC_STATE_READY)
2797 /* Change State */
2798 hmmc->State = HAL_MMC_STATE_BUSY;
2800 /* Read the Extended CSD register and get expected value */
2801 if(MMC_ReadExtCSD(hmmc, &srt, 16, 0x0FFFFFFFU) == HAL_OK) /* Field SECURE_REMOVAL_TYPE [16] */
2803 *SupportedSRT = (srt & 0x0000000FU); /* Bits [3:0] of field 16 */
2805 else
2807 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
2810 /* Change State */
2811 hmmc->State = HAL_MMC_STATE_READY;
2813 /* Manage errors */
2814 if(errorstate != HAL_MMC_ERROR_NONE)
2816 /* Clear all the static flags */
2817 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
2818 hmmc->ErrorCode |= errorstate;
2819 return HAL_ERROR;
2821 else
2823 return HAL_OK;
2826 else
2828 return HAL_BUSY;
2833 * @}
2837 * @}
2840 /* Private function ----------------------------------------------------------*/
2841 /** @addtogroup MMC_Private_Functions
2842 * @{
2847 * @brief Initializes the mmc card.
2848 * @param hmmc: Pointer to MMC handle
2849 * @retval MMC Card error state
2851 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
2853 HAL_MMC_CardCSDTypeDef CSD;
2854 uint32_t errorstate;
2855 uint16_t mmc_rca = 1U;
2856 MMC_InitTypeDef Init;
2858 /* Check the power State */
2859 if(SDMMC_GetPowerState(hmmc->Instance) == 0U)
2861 /* Power off */
2862 return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2865 /* Send CMD2 ALL_SEND_CID */
2866 errorstate = SDMMC_CmdSendCID(hmmc->Instance);
2867 if(errorstate != HAL_MMC_ERROR_NONE)
2869 return errorstate;
2871 else
2873 /* Get Card identification number data */
2874 hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2875 hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
2876 hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
2877 hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
2880 /* Send CMD3 SET_REL_ADDR with argument 0 */
2881 /* MMC Card publishes its RCA. */
2882 errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
2883 if(errorstate != HAL_MMC_ERROR_NONE)
2885 return errorstate;
2888 /* Get the MMC card RCA */
2889 hmmc->MmcCard.RelCardAdd = mmc_rca;
2891 /* Send CMD9 SEND_CSD with argument as card's RCA */
2892 errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2893 if(errorstate != HAL_MMC_ERROR_NONE)
2895 return errorstate;
2897 else
2899 /* Get Card Specific Data */
2900 hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2901 hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2);
2902 hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3);
2903 hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4);
2906 /* Get the Card Class */
2907 hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U);
2909 /* Select the Card */
2910 errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2911 if(errorstate != HAL_MMC_ERROR_NONE)
2913 return errorstate;
2916 /* Get CSD parameters */
2917 if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
2919 return hmmc->ErrorCode;
2922 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2923 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2924 if(errorstate != HAL_MMC_ERROR_NONE)
2926 hmmc->ErrorCode |= errorstate;
2929 /* Configure the SDMMC peripheral */
2930 Init.ClockEdge = hmmc->Init.ClockEdge;
2931 Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
2932 Init.BusWide = SDMMC_BUS_WIDE_1B;
2933 Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
2934 Init.ClockDiv = hmmc->Init.ClockDiv;
2935 (void)SDMMC_Init(hmmc->Instance, Init);
2937 /* All cards are initialized */
2938 return HAL_MMC_ERROR_NONE;
2942 * @brief Enquires cards about their operating voltage and configures clock
2943 * controls and stores MMC information that will be needed in future
2944 * in the MMC handle.
2945 * @param hmmc: Pointer to MMC handle
2946 * @retval error state
2948 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
2950 __IO uint32_t count = 0U;
2951 uint32_t response = 0U, validvoltage = 0U;
2952 uint32_t errorstate;
2954 /* CMD0: GO_IDLE_STATE */
2955 errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
2956 if(errorstate != HAL_MMC_ERROR_NONE)
2958 return errorstate;
2961 while(validvoltage == 0U)
2963 if(count++ == SDMMC_MAX_VOLT_TRIAL)
2965 return HAL_MMC_ERROR_INVALID_VOLTRANGE;
2968 /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
2969 errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
2970 if(errorstate != HAL_MMC_ERROR_NONE)
2972 return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2975 /* Get command response */
2976 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
2978 /* Get operating voltage*/
2979 validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
2982 /* When power routine is finished and command returns valid voltage */
2983 if (((response & (0xFF000000U)) >> 24) == 0xC0U)
2985 hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
2987 else
2989 hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
2992 return HAL_MMC_ERROR_NONE;
2996 * @brief Turns the SDMMC output signals off.
2997 * @param hmmc: Pointer to MMC handle
2998 * @retval None
3000 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
3002 /* Set Power State to OFF */
3003 (void)SDMMC_PowerState_OFF(hmmc->Instance);
3007 * @brief Returns the current card's status.
3008 * @param hmmc: Pointer to MMC handle
3009 * @param pCardStatus: pointer to the buffer that will contain the MMC card
3010 * status (Card Status register)
3011 * @retval error state
3013 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
3015 uint32_t errorstate;
3017 if(pCardStatus == NULL)
3019 return HAL_MMC_ERROR_PARAM;
3022 /* Send Status command */
3023 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
3024 if(errorstate != HAL_MMC_ERROR_NONE)
3026 return errorstate;
3029 /* Get MMC card status */
3030 *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3032 return HAL_MMC_ERROR_NONE;
3036 * @brief Reads extended CSD register to get the sectors number of the device
3037 * @param hmmc: Pointer to MMC handle
3038 * @param pFieldData: Pointer to the read buffer
3039 * @param FieldIndex: Index of the field to be read
3040 * @param Timeout: Specify timeout value
3041 * @retval HAL status
3043 HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout)
3045 SDMMC_DataInitTypeDef config;
3046 uint32_t errorstate;
3047 uint32_t tickstart = HAL_GetTick();
3048 uint32_t count;
3049 uint32_t i = 0;
3050 uint32_t tmp_data;
3052 hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
3054 /* Initialize data control register */
3055 hmmc->Instance->DCTRL = 0;
3057 /* Configure the MMC DPSM (Data Path State Machine) */
3058 config.DataTimeOut = SDMMC_DATATIMEOUT;
3059 config.DataLength = 512;
3060 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
3061 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC;
3062 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
3063 config.DPSM = SDMMC_DPSM_ENABLE;
3064 (void)SDMMC_ConfigData(hmmc->Instance, &config);
3066 /* Set Block Size for Card */
3067 errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
3068 if(errorstate != HAL_MMC_ERROR_NONE)
3070 /* Clear all the static flags */
3071 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3072 hmmc->ErrorCode |= errorstate;
3073 hmmc->State = HAL_MMC_STATE_READY;
3074 return HAL_ERROR;
3077 /* Poll on SDMMC flags */
3078 while(!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND))
3080 if(__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF))
3082 /* Read data from SDMMC Rx FIFO */
3083 for(count = 0U; count < 8U; count++)
3085 tmp_data = SDMMC_ReadFIFO(hmmc->Instance);
3086 /* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */
3087 /* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
3088 if ((i + count) == ((uint32_t)FieldIndex/4U))
3090 *pFieldData = tmp_data;
3093 i += 8U;
3096 if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
3098 /* Clear all the static flags */
3099 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS);
3100 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
3101 hmmc->State= HAL_MMC_STATE_READY;
3102 return HAL_TIMEOUT;
3106 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3107 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
3108 if(errorstate != HAL_MMC_ERROR_NONE)
3110 hmmc->ErrorCode |= errorstate;
3113 /* Clear all the static flags */
3114 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS);
3116 hmmc->State = HAL_MMC_STATE_READY;
3118 return HAL_OK;
3122 * @brief Wrap up reading in non-blocking mode.
3123 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
3124 * the configuration information.
3125 * @retval None
3127 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
3129 uint32_t count, data;
3130 uint8_t* tmp;
3132 tmp = hmmc->pRxBuffPtr;
3134 if (hmmc->RxXferSize >= 32U)
3136 /* Read data from SDMMC Rx FIFO */
3137 for(count = 0U; count < 8U; count++)
3139 data = SDMMC_ReadFIFO(hmmc->Instance);
3140 *tmp = (uint8_t)(data & 0xFFU);
3141 tmp++;
3142 *tmp = (uint8_t)((data >> 8U) & 0xFFU);
3143 tmp++;
3144 *tmp = (uint8_t)((data >> 16U) & 0xFFU);
3145 tmp++;
3146 *tmp = (uint8_t)((data >> 24U) & 0xFFU);
3147 tmp++;
3150 hmmc->pRxBuffPtr = tmp;
3151 hmmc->RxXferSize -= 32U;
3156 * @brief Wrap up writing in non-blocking mode.
3157 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
3158 * the configuration information.
3159 * @retval None
3161 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
3163 uint32_t count, data;
3164 uint8_t* tmp;
3166 tmp = hmmc->pTxBuffPtr;
3168 if (hmmc->TxXferSize >= 32U)
3170 /* Write data to SDMMC Tx FIFO */
3171 for(count = 0U; count < 8U; count++)
3173 data = (uint32_t)(*tmp);
3174 tmp++;
3175 data |= ((uint32_t)(*tmp) << 8U);
3176 tmp++;
3177 data |= ((uint32_t)(*tmp) << 16U);
3178 tmp++;
3179 data |= ((uint32_t)(*tmp) << 24U);
3180 tmp++;
3181 (void)SDMMC_WriteFIFO(hmmc->Instance, &data);
3184 hmmc->pTxBuffPtr = tmp;
3185 hmmc->TxXferSize -= 32U;
3190 * @brief Switches the MMC card to high speed mode.
3191 * @param hmmc: MMC handle
3192 * @param state: State of high speed mode
3193 * @retval MMC Card error state
3195 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state)
3197 uint32_t errorstate = HAL_MMC_ERROR_NONE;
3198 uint32_t response = 0U, count;
3199 SDMMC_InitTypeDef Init;
3201 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) && (state == DISABLE))
3203 /* Index : 185 - Value : 0 */
3204 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90000U);
3207 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) == 0U) && (state != DISABLE))
3209 /* Index : 185 - Value : 1 */
3210 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90100U);
3213 if(errorstate == HAL_MMC_ERROR_NONE)
3215 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3216 count = SDMMC_MAX_TRIAL;
3219 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3220 if(errorstate != HAL_MMC_ERROR_NONE)
3222 break;
3225 /* Get command response */
3226 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3227 count--;
3228 }while(((response & 0x100U) == 0U) && (count != 0U));
3230 /* Check the status after the switch command execution */
3231 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
3233 /* Check the bit SWITCH_ERROR of the device status */
3234 if ((response & 0x80U) != 0U)
3236 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3238 else
3240 /* Configure high speed */
3241 Init.ClockEdge = hmmc->Init.ClockEdge;
3242 Init.ClockPowerSave = hmmc->Init.ClockPowerSave;
3243 Init.BusWide = (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS);
3244 Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
3246 if (state == DISABLE)
3248 Init.ClockDiv = hmmc->Init.ClockDiv;
3249 (void)SDMMC_Init(hmmc->Instance, Init);
3251 CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
3253 else
3255 Init.ClockDiv = SDMMC_HSpeed_CLK_DIV;
3256 (void)SDMMC_Init(hmmc->Instance, Init);
3258 SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED);
3262 else if (count == 0U)
3264 errorstate = SDMMC_ERROR_TIMEOUT;
3266 else
3268 /* Nothing to do */
3272 return errorstate;
3276 * @brief Switches the MMC card to Double Data Rate (DDR) mode.
3277 * @param hmmc: MMC handle
3278 * @param state: State of DDR mode
3279 * @retval MMC Card error state
3281 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state)
3283 uint32_t errorstate = HAL_MMC_ERROR_NONE;
3284 uint32_t response = 0U, count;
3286 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) && (state == DISABLE))
3288 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
3290 /* Index : 183 - Value : 1 */
3291 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
3293 else
3295 /* Index : 183 - Value : 2 */
3296 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
3300 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) == 0U) && (state != DISABLE))
3302 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U)
3304 /* Index : 183 - Value : 5 */
3305 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70500U);
3307 else
3309 /* Index : 183 - Value : 6 */
3310 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70600U);
3314 if(errorstate == HAL_MMC_ERROR_NONE)
3316 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
3317 count = SDMMC_MAX_TRIAL;
3320 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
3321 if(errorstate != HAL_MMC_ERROR_NONE)
3323 break;
3326 /* Get command response */
3327 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1);
3328 count--;
3329 }while(((response & 0x100U) == 0U) && (count != 0U));
3331 /* Check the status after the switch command execution */
3332 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
3334 /* Check the bit SWITCH_ERROR of the device status */
3335 if ((response & 0x80U) != 0U)
3337 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
3339 else
3341 /* Configure DDR mode */
3342 if (state == DISABLE)
3344 CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
3346 else
3348 SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR);
3352 else if (count == 0U)
3354 errorstate = SDMMC_ERROR_TIMEOUT;
3356 else
3358 /* Nothing to do */
3362 return errorstate;
3366 * @brief Read DMA Buffer 0 Transfer completed callbacks
3367 * @param hmmc: MMC handle
3368 * @retval None
3370 __weak void HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc)
3372 /* Prevent unused argument(s) compilation warning */
3373 UNUSED(hmmc);
3375 /* NOTE : This function should not be modified, when the callback is needed,
3376 the HAL_MMCEx_Read_DMADoubleBuf0CpltCallback can be implemented in the user file
3381 * @brief Read DMA Buffer 1 Transfer completed callbacks
3382 * @param hmmc: MMC handle
3383 * @retval None
3385 __weak void HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc)
3387 /* Prevent unused argument(s) compilation warning */
3388 UNUSED(hmmc);
3390 /* NOTE : This function should not be modified, when the callback is needed,
3391 the HAL_MMCEx_Read_DMADoubleBuf1CpltCallback can be implemented in the user file
3396 * @brief Write DMA Buffer 0 Transfer completed callbacks
3397 * @param hmmc: MMC handle
3398 * @retval None
3400 __weak void HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc)
3402 /* Prevent unused argument(s) compilation warning */
3403 UNUSED(hmmc);
3405 /* NOTE : This function should not be modified, when the callback is needed,
3406 the HAL_MMCEx_Write_DMADoubleBuf0CpltCallback can be implemented in the user file
3411 * @brief Write DMA Buffer 1 Transfer completed callbacks
3412 * @param hmmc: MMC handle
3413 * @retval None
3415 __weak void HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc)
3417 /* Prevent unused argument(s) compilation warning */
3418 UNUSED(hmmc);
3420 /* NOTE : This function should not be modified, when the callback is needed,
3421 the HAL_MMCEx_Write_DMADoubleBuf1CpltCallback can be implemented in the user file
3426 * @}
3429 #endif /* HAL_MMC_MODULE_ENABLED */
3432 * @}
3436 * @}
3439 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/