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