1 /**
2   ******************************************************************************
3   * @file    stm32f4xx_ll_sdmmc.c
4   * @author  MCD Application Team
5   * @brief   SDMMC Low Layer HAL module driver.
6   *
7   *          This file provides firmware functions to manage the following
8   *          functionalities of the SDMMC peripheral:
9   *           + Initialization/de-initialization functions
10   *           + I/O operation functions
11   *           + Peripheral Control functions
12   *           + Peripheral State functions
13   *
14   ******************************************************************************
15   * @attention
16   *
17   * Copyright (c) 2016 STMicroelectronics.
18   * All rights reserved.
19   *
20   * This software is licensed under terms that can be found in the LICENSE file
21   * in the root directory of this software component.
22   * If no LICENSE file comes with this software, it is provided AS-IS.
23   *
24   ******************************************************************************
25   @verbatim
26   ==============================================================================
27                        ##### SDMMC peripheral features #####
28   ==============================================================================
29     [..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the AHB
30          peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA
31          devices.
32 
33     [..] The SDMMC features include the following:
34          (+) Full compliance with MultiMedia Card System Specification Version 4.2. Card support
35              for three different databus modes: 1-bit (default), 4-bit and 8-bit
36          (+) Full compatibility with previous versions of MultiMedia Cards (forward compatibility)
37          (+) Full compliance with SD Memory Card Specifications Version 2.0
38          (+) Full compliance with SD I/O Card Specification Version 2.0: card support for two
39              different data bus modes: 1-bit (default) and 4-bit
40          (+) Full support of the CE-ATA features (full compliance with CE-ATA digital protocol
41              Rev1.1)
42          (+) Data transfer up to 48 MHz for the 8 bit mode
43          (+) Data and command output enable signals to control external bidirectional drivers
44 
45                            ##### How to use this driver #####
46   ==============================================================================
47     [..]
48       This driver is a considered as a driver of service for external devices drivers
49       that interfaces with the SDMMC peripheral.
50       According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs
51       is used in the device's driver to perform SDMMC operations and functionalities.
52 
53       This driver is almost transparent for the final user, it is only used to implement other
54       functionalities of the external device.
55 
56     [..]
57       (+) The SDMMC clock (SDMMCCLK = 48 MHz) is coming from a specific output (MSI, PLLUSB1CLK,
58           PLLUSB2CLK). Before start working with SDMMC peripheral make sure that the
59           PLL is well configured.
60           The SDMMC peripheral uses two clock signals:
61           (++) SDMMC adapter clock (SDMMCCLK = 48 MHz)
62           (++) APB2 bus clock (PCLK2)
63 
64           -@@- PCLK2 and SDMMC_CK clock frequencies must respect the following condition:
65                Frequency(PCLK2) >= (3 / 8 x Frequency(SDMMC_CK))
66 
67       (+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC
68           peripheral.
69 
70       (+) Enable the Power ON State using the SDIO_PowerState_ON()
71           function and disable it using the function SDIO_PowerState_OFF().
72 
73       (+) Enable/Disable the clock using the __SDIO_ENABLE()/__SDIO_DISABLE() macros.
74 
75       (+) Enable/Disable the peripheral interrupts using the macros __SDIO_ENABLE_IT()
76           and __SDIO_DISABLE_IT() if you need to use interrupt mode.
77 
78       (+) When using the DMA mode
79           (++) Configure the DMA in the MSP layer of the external device
80           (++) Active the needed channel Request
81           (++) Enable the DMA using __SDIO_DMA_ENABLE() macro or Disable it using the macro
82                __SDIO_DMA_DISABLE().
83 
84       (+) To control the CPSM (Command Path State Machine) and send
85           commands to the card use the SDIO_SendCommand(),
86           SDIO_GetCommandResponse() and SDIO_GetResponse() functions. First, user has
87           to fill the command structure (pointer to SDIO_CmdInitTypeDef) according
88           to the selected command to be sent.
89           The parameters that should be filled are:
90            (++) Command Argument
91            (++) Command Index
92            (++) Command Response type
93            (++) Command Wait
94            (++) CPSM Status (Enable or Disable).
95 
96           -@@- To check if the command is well received, read the SDIO_CMDRESP
97               register using the SDIO_GetCommandResponse().
98               The SDMMC responses registers (SDIO_RESP1 to SDIO_RESP2), use the
99               SDIO_GetResponse() function.
100 
101       (+) To control the DPSM (Data Path State Machine) and send/receive
102            data to/from the card use the SDIO_DataConfig(), SDIO_GetDataCounter(),
103           SDIO_ReadFIFO(), SDIO_WriteFIFO() and SDIO_GetFIFOCount() functions.
104 
105     *** Read Operations ***
106     =======================
107     [..]
108       (#) First, user has to fill the data structure (pointer to
109           SDIO_DataInitTypeDef) according to the selected data type to be received.
110           The parameters that should be filled are:
111            (++) Data TimeOut
112            (++) Data Length
113            (++) Data Block size
114            (++) Data Transfer direction: should be from card (To SDMMC)
115            (++) Data Transfer mode
116            (++) DPSM Status (Enable or Disable)
117 
118       (#) Configure the SDMMC resources to receive the data from the card
119           according to selected transfer mode (Refer to Step 8, 9 and 10).
120 
121       (#) Send the selected Read command (refer to step 11).
122 
123       (#) Use the SDIO flags/interrupts to check the transfer status.
124 
125     *** Write Operations ***
126     ========================
127     [..]
128      (#) First, user has to fill the data structure (pointer to
129          SDIO_DataInitTypeDef) according to the selected data type to be received.
130          The parameters that should be filled are:
131           (++) Data TimeOut
132           (++) Data Length
133           (++) Data Block size
134           (++) Data Transfer direction:  should be to card (To CARD)
135           (++) Data Transfer mode
136           (++) DPSM Status (Enable or Disable)
137 
138      (#) Configure the SDMMC resources to send the data to the card according to
139          selected transfer mode.
140 
141      (#) Send the selected Write command.
142 
143      (#) Use the SDIO flags/interrupts to check the transfer status.
144 
145     *** Command management operations ***
146     =====================================
147     [..]
148      (#) The commands used for Read/Write/Erase operations are managed in
149          separate functions.
150          Each function allows to send the needed command with the related argument,
151          then check the response.
152          By the same approach, you could implement a command and check the response.
153 
154   @endverbatim
155   ******************************************************************************
156   */
157 
158 /* Includes ------------------------------------------------------------------*/
159 #include "stm32f4xx_hal.h"
160 
161 #if defined(SDIO)
162 
163 /** @addtogroup STM32F4xx_HAL_Driver
164   * @{
165   */
166 
167 /** @defgroup SDMMC_LL SDMMC Low Layer
168   * @brief Low layer module for SD
169   * @{
170   */
171 
172 #if defined(HAL_SD_MODULE_ENABLED) || defined(HAL_MMC_MODULE_ENABLED)
173 
174 /* Private typedef -----------------------------------------------------------*/
175 /* Private define ------------------------------------------------------------*/
176 /* Private macro -------------------------------------------------------------*/
177 /* Private variables ---------------------------------------------------------*/
178 /* Private function prototypes -----------------------------------------------*/
179 static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx);
180 
181 /* Exported functions --------------------------------------------------------*/
182 
183 /** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
184   * @{
185   */
186 
187 /** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
188  *  @brief    Initialization and Configuration functions
189  *
190 @verbatim
191  ===============================================================================
192               ##### Initialization/de-initialization functions #####
193  ===============================================================================
194     [..]  This section provides functions allowing to:
195 
196 @endverbatim
197   * @{
198   */
199 
200 /**
201   * @brief  Initializes the SDMMC according to the specified
202   *         parameters in the SDMMC_InitTypeDef and create the associated handle.
203   * @param  SDIOx: Pointer to SDMMC register base
204   * @param  Init: SDMMC initialization structure
205   * @retval HAL status
206   */
SDIO_Init(SDIO_TypeDef * SDIOx,SDIO_InitTypeDef Init)207 HAL_StatusTypeDef SDIO_Init(SDIO_TypeDef *SDIOx, SDIO_InitTypeDef Init)
208 {
209   uint32_t tmpreg = 0;
210 
211   /* Check the parameters */
212   assert_param(IS_SDIO_ALL_INSTANCE(SDIOx));
213   assert_param(IS_SDIO_CLOCK_EDGE(Init.ClockEdge));
214   assert_param(IS_SDIO_CLOCK_BYPASS(Init.ClockBypass));
215   assert_param(IS_SDIO_CLOCK_POWER_SAVE(Init.ClockPowerSave));
216   assert_param(IS_SDIO_BUS_WIDE(Init.BusWide));
217   assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
218   assert_param(IS_SDIO_CLKDIV(Init.ClockDiv));
219 
220   /* Set SDMMC configuration parameters */
221   tmpreg |= (Init.ClockEdge           |\
222              Init.ClockBypass         |\
223              Init.ClockPowerSave      |\
224              Init.BusWide             |\
225              Init.HardwareFlowControl |\
226              Init.ClockDiv
227              );
228 
229   /* Write to SDMMC CLKCR */
230   MODIFY_REG(SDIOx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
231 
232   return HAL_OK;
233 }
234 
235 
236 /**
237   * @}
238   */
239 
240 /** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
241  *  @brief   Data transfers functions
242  *
243 @verbatim
244  ===============================================================================
245                       ##### I/O operation functions #####
246  ===============================================================================
247     [..]
248     This subsection provides a set of functions allowing to manage the SDMMC data
249     transfers.
250 
251 @endverbatim
252   * @{
253   */
254 
255 /**
256   * @brief  Read data (word) from Rx FIFO in blocking mode (polling)
257   * @param  SDIOx: Pointer to SDMMC register base
258   * @retval HAL status
259   */
SDIO_ReadFIFO(SDIO_TypeDef * SDIOx)260 uint32_t SDIO_ReadFIFO(SDIO_TypeDef *SDIOx)
261 {
262   /* Read data from Rx FIFO */
263   return (SDIOx->FIFO);
264 }
265 
266 /**
267   * @brief  Write data (word) to Tx FIFO in blocking mode (polling)
268   * @param  SDIOx: Pointer to SDMMC register base
269   * @param  pWriteData: pointer to data to write
270   * @retval HAL status
271   */
SDIO_WriteFIFO(SDIO_TypeDef * SDIOx,uint32_t * pWriteData)272 HAL_StatusTypeDef SDIO_WriteFIFO(SDIO_TypeDef *SDIOx, uint32_t *pWriteData)
273 {
274   /* Write data to FIFO */
275   SDIOx->FIFO = *pWriteData;
276 
277   return HAL_OK;
278 }
279 
280 /**
281   * @}
282   */
283 
284 /** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
285  *  @brief   management functions
286  *
287 @verbatim
288  ===============================================================================
289                       ##### Peripheral Control functions #####
290  ===============================================================================
291     [..]
292     This subsection provides a set of functions allowing to control the SDMMC data
293     transfers.
294 
295 @endverbatim
296   * @{
297   */
298 
299 /**
300   * @brief  Set SDMMC Power state to ON.
301   * @param  SDIOx: Pointer to SDMMC register base
302   * @retval HAL status
303   */
SDIO_PowerState_ON(SDIO_TypeDef * SDIOx)304 HAL_StatusTypeDef SDIO_PowerState_ON(SDIO_TypeDef *SDIOx)
305 {
306   /* Set power state to ON */
307   SDIOx->POWER = SDIO_POWER_PWRCTRL;
308 
309   return HAL_OK;
310 }
311 
312 /**
313   * @brief  Set SDMMC Power state to OFF.
314   * @param  SDIOx: Pointer to SDMMC register base
315   * @retval HAL status
316   */
SDIO_PowerState_OFF(SDIO_TypeDef * SDIOx)317 HAL_StatusTypeDef SDIO_PowerState_OFF(SDIO_TypeDef *SDIOx)
318 {
319   /* Set power state to OFF */
320   SDIOx->POWER = (uint32_t)0x00000000;
321 
322   return HAL_OK;
323 }
324 
325 /**
326   * @brief  Get SDMMC Power state.
327   * @param  SDIOx: Pointer to SDMMC register base
328   * @retval Power status of the controller. The returned value can be one of the
329   *         following values:
330   *            - 0x00: Power OFF
331   *            - 0x02: Power UP
332   *            - 0x03: Power ON
333   */
SDIO_GetPowerState(SDIO_TypeDef * SDIOx)334 uint32_t SDIO_GetPowerState(SDIO_TypeDef *SDIOx)
335 {
336   return (SDIOx->POWER & SDIO_POWER_PWRCTRL);
337 }
338 
339 /**
340   * @brief  Configure the SDMMC command path according to the specified parameters in
341   *         SDIO_CmdInitTypeDef structure and send the command
342   * @param  SDIOx: Pointer to SDMMC register base
343   * @param  Command: pointer to a SDIO_CmdInitTypeDef structure that contains
344   *         the configuration information for the SDMMC command
345   * @retval HAL status
346   */
SDIO_SendCommand(SDIO_TypeDef * SDIOx,SDIO_CmdInitTypeDef * Command)347 HAL_StatusTypeDef SDIO_SendCommand(SDIO_TypeDef *SDIOx, SDIO_CmdInitTypeDef *Command)
348 {
349   uint32_t tmpreg = 0;
350 
351   /* Check the parameters */
352   assert_param(IS_SDIO_CMD_INDEX(Command->CmdIndex));
353   assert_param(IS_SDIO_RESPONSE(Command->Response));
354   assert_param(IS_SDIO_WAIT(Command->WaitForInterrupt));
355   assert_param(IS_SDIO_CPSM(Command->CPSM));
356 
357   /* Set the SDMMC Argument value */
358   SDIOx->ARG = Command->Argument;
359 
360   /* Set SDMMC command parameters */
361   tmpreg |= (uint32_t)(Command->CmdIndex         |\
362                        Command->Response         |\
363                        Command->WaitForInterrupt |\
364                        Command->CPSM);
365 
366   /* Write to SDMMC CMD register */
367   MODIFY_REG(SDIOx->CMD, CMD_CLEAR_MASK, tmpreg);
368 
369   return HAL_OK;
370 }
371 
372 /**
373   * @brief  Return the command index of last command for which response received
374   * @param  SDIOx: Pointer to SDMMC register base
375   * @retval Command index of the last command response received
376   */
SDIO_GetCommandResponse(SDIO_TypeDef * SDIOx)377 uint8_t SDIO_GetCommandResponse(SDIO_TypeDef *SDIOx)
378 {
379   return (uint8_t)(SDIOx->RESPCMD);
380 }
381 
382 
383 /**
384   * @brief  Return the response received from the card for the last command
385   * @param  SDIOx: Pointer to SDMMC register base
386   * @param  Response: Specifies the SDMMC response register.
387   *          This parameter can be one of the following values:
388   *            @arg SDIO_RESP1: Response Register 1
389   *            @arg SDIO_RESP2: Response Register 2
390   *            @arg SDIO_RESP3: Response Register 3
391   *            @arg SDIO_RESP4: Response Register 4
392   * @retval The Corresponding response register value
393   */
SDIO_GetResponse(SDIO_TypeDef * SDIOx,uint32_t Response)394 uint32_t SDIO_GetResponse(SDIO_TypeDef *SDIOx, uint32_t Response)
395 {
396   uint32_t tmp;
397 
398   /* Check the parameters */
399   assert_param(IS_SDIO_RESP(Response));
400 
401   /* Get the response */
402   tmp = (uint32_t)(&(SDIOx->RESP1)) + Response;
403 
404   return (*(__IO uint32_t *) tmp);
405 }
406 
407 /**
408   * @brief  Configure the SDMMC data path according to the specified
409   *         parameters in the SDIO_DataInitTypeDef.
410   * @param  SDIOx: Pointer to SDIO register base
411   * @param  Data : pointer to a SDIO_DataInitTypeDef structure
412   *         that contains the configuration information for the SDMMC data.
413   * @retval HAL status
414   */
SDIO_ConfigData(SDIO_TypeDef * SDIOx,SDIO_DataInitTypeDef * Data)415 HAL_StatusTypeDef SDIO_ConfigData(SDIO_TypeDef *SDIOx, SDIO_DataInitTypeDef* Data)
416 {
417   uint32_t tmpreg = 0;
418 
419   /* Check the parameters */
420   assert_param(IS_SDIO_DATA_LENGTH(Data->DataLength));
421   assert_param(IS_SDIO_BLOCK_SIZE(Data->DataBlockSize));
422   assert_param(IS_SDIO_TRANSFER_DIR(Data->TransferDir));
423   assert_param(IS_SDIO_TRANSFER_MODE(Data->TransferMode));
424   assert_param(IS_SDIO_DPSM(Data->DPSM));
425 
426   /* Set the SDMMC Data TimeOut value */
427   SDIOx->DTIMER = Data->DataTimeOut;
428 
429   /* Set the SDMMC DataLength value */
430   SDIOx->DLEN = Data->DataLength;
431 
432   /* Set the SDMMC data configuration parameters */
433   tmpreg |= (uint32_t)(Data->DataBlockSize |\
434                        Data->TransferDir   |\
435                        Data->TransferMode  |\
436                        Data->DPSM);
437 
438   /* Write to SDMMC DCTRL */
439   MODIFY_REG(SDIOx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
440 
441   return HAL_OK;
442 
443 }
444 
445 /**
446   * @brief  Returns number of remaining data bytes to be transferred.
447   * @param  SDIOx: Pointer to SDIO register base
448   * @retval Number of remaining data bytes to be transferred
449   */
SDIO_GetDataCounter(SDIO_TypeDef * SDIOx)450 uint32_t SDIO_GetDataCounter(SDIO_TypeDef *SDIOx)
451 {
452   return (SDIOx->DCOUNT);
453 }
454 
455 /**
456   * @brief  Get the FIFO data
457   * @param  SDIOx: Pointer to SDIO register base
458   * @retval Data received
459   */
SDIO_GetFIFOCount(SDIO_TypeDef * SDIOx)460 uint32_t SDIO_GetFIFOCount(SDIO_TypeDef *SDIOx)
461 {
462   return (SDIOx->FIFO);
463 }
464 
465 /**
466   * @brief  Sets one of the two options of inserting read wait interval.
467   * @param  SDIOx: Pointer to SDIO register base
468   * @param  SDIO_ReadWaitMode: SDMMC Read Wait operation mode.
469   *          This parameter can be:
470   *            @arg SDIO_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
471   *            @arg SDIO_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
472   * @retval None
473   */
SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef * SDIOx,uint32_t SDIO_ReadWaitMode)474 HAL_StatusTypeDef SDIO_SetSDMMCReadWaitMode(SDIO_TypeDef *SDIOx, uint32_t SDIO_ReadWaitMode)
475 {
476   /* Check the parameters */
477   assert_param(IS_SDIO_READWAIT_MODE(SDIO_ReadWaitMode));
478 
479   /* Set SDMMC read wait mode */
480   MODIFY_REG(SDIOx->DCTRL, SDIO_DCTRL_RWMOD, SDIO_ReadWaitMode);
481 
482   return HAL_OK;
483 }
484 
485 /**
486   * @}
487   */
488 
489 
490 /** @defgroup HAL_SDMMC_LL_Group4 Command management functions
491  *  @brief   Data transfers functions
492  *
493 @verbatim
494  ===============================================================================
495                    ##### Commands management functions #####
496  ===============================================================================
497     [..]
498     This subsection provides a set of functions allowing to manage the needed commands.
499 
500 @endverbatim
501   * @{
502   */
503 
504 /**
505   * @brief  Send the Data Block Length command and check the response
506   * @param  SDIOx: Pointer to SDIO register base
507   * @retval HAL status
508   */
SDMMC_CmdBlockLength(SDIO_TypeDef * SDIOx,uint32_t BlockSize)509 uint32_t SDMMC_CmdBlockLength(SDIO_TypeDef *SDIOx, uint32_t BlockSize)
510 {
511   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
512   uint32_t errorstate;
513 
514   /* Set Block Size for Card */
515   sdmmc_cmdinit.Argument         = (uint32_t)BlockSize;
516   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_BLOCKLEN;
517   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
518   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
519   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
520   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
521 
522   /* Check for error conditions */
523   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_BLOCKLEN, SDIO_CMDTIMEOUT);
524 
525   return errorstate;
526 }
527 
528 /**
529   * @brief  Send the Read Single Block command and check the response
530   * @param  SDIOx: Pointer to SDIO register base
531   * @retval HAL status
532   */
SDMMC_CmdReadSingleBlock(SDIO_TypeDef * SDIOx,uint32_t ReadAdd)533 uint32_t SDMMC_CmdReadSingleBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd)
534 {
535   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
536   uint32_t errorstate;
537 
538   /* Set Block Size for Card */
539   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
540   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_SINGLE_BLOCK;
541   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
542   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
543   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
544   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
545 
546   /* Check for error conditions */
547   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_SINGLE_BLOCK, SDIO_CMDTIMEOUT);
548 
549   return errorstate;
550 }
551 
552 /**
553   * @brief  Send the Read Multi Block command and check the response
554   * @param  SDIOx: Pointer to SDIO register base
555   * @retval HAL status
556   */
SDMMC_CmdReadMultiBlock(SDIO_TypeDef * SDIOx,uint32_t ReadAdd)557 uint32_t SDMMC_CmdReadMultiBlock(SDIO_TypeDef *SDIOx, uint32_t ReadAdd)
558 {
559   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
560   uint32_t errorstate;
561 
562   /* Set Block Size for Card */
563   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
564   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_MULT_BLOCK;
565   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
566   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
567   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
568   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
569 
570   /* Check for error conditions */
571   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_READ_MULT_BLOCK, SDIO_CMDTIMEOUT);
572 
573   return errorstate;
574 }
575 
576 /**
577   * @brief  Send the Write Single Block command and check the response
578   * @param  SDIOx: Pointer to SDIO register base
579   * @retval HAL status
580   */
SDMMC_CmdWriteSingleBlock(SDIO_TypeDef * SDIOx,uint32_t WriteAdd)581 uint32_t SDMMC_CmdWriteSingleBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd)
582 {
583   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
584   uint32_t errorstate;
585 
586   /* Set Block Size for Card */
587   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
588   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_SINGLE_BLOCK;
589   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
590   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
591   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
592   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
593 
594   /* Check for error conditions */
595   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDIO_CMDTIMEOUT);
596 
597   return errorstate;
598 }
599 
600 /**
601   * @brief  Send the Write Multi Block command and check the response
602   * @param  SDIOx: Pointer to SDIO register base
603   * @retval HAL status
604   */
SDMMC_CmdWriteMultiBlock(SDIO_TypeDef * SDIOx,uint32_t WriteAdd)605 uint32_t SDMMC_CmdWriteMultiBlock(SDIO_TypeDef *SDIOx, uint32_t WriteAdd)
606 {
607   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
608   uint32_t errorstate;
609 
610   /* Set Block Size for Card */
611   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
612   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_MULT_BLOCK;
613   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
614   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
615   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
616   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
617 
618   /* Check for error conditions */
619   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_WRITE_MULT_BLOCK, SDIO_CMDTIMEOUT);
620 
621   return errorstate;
622 }
623 
624 /**
625   * @brief  Send the Start Address Erase command for SD and check the response
626   * @param  SDIOx: Pointer to SDIO register base
627   * @retval HAL status
628   */
SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef * SDIOx,uint32_t StartAdd)629 uint32_t SDMMC_CmdSDEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd)
630 {
631   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
632   uint32_t errorstate;
633 
634   /* Set Block Size for Card */
635   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
636   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_START;
637   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
638   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
639   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
640   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
641 
642   /* Check for error conditions */
643   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_START, SDIO_CMDTIMEOUT);
644 
645   return errorstate;
646 }
647 
648 /**
649   * @brief  Send the End Address Erase command for SD and check the response
650   * @param  SDIOx: Pointer to SDIO register base
651   * @retval HAL status
652   */
SDMMC_CmdSDEraseEndAdd(SDIO_TypeDef * SDIOx,uint32_t EndAdd)653 uint32_t SDMMC_CmdSDEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd)
654 {
655   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
656   uint32_t errorstate;
657 
658   /* Set Block Size for Card */
659   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
660   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_END;
661   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
662   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
663   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
664   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
665 
666   /* Check for error conditions */
667   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_ERASE_GRP_END, SDIO_CMDTIMEOUT);
668 
669   return errorstate;
670 }
671 
672 /**
673   * @brief  Send the Start Address Erase command and check the response
674   * @param  SDIOx: Pointer to SDIO register base
675   * @retval HAL status
676   */
SDMMC_CmdEraseStartAdd(SDIO_TypeDef * SDIOx,uint32_t StartAdd)677 uint32_t SDMMC_CmdEraseStartAdd(SDIO_TypeDef *SDIOx, uint32_t StartAdd)
678 {
679   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
680   uint32_t errorstate;
681 
682   /* Set Block Size for Card */
683   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
684   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_START;
685   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
686   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
687   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
688   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
689 
690   /* Check for error conditions */
691   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_START, SDIO_CMDTIMEOUT);
692 
693   return errorstate;
694 }
695 
696 /**
697   * @brief  Send the End Address Erase command and check the response
698   * @param  SDIOx: Pointer to SDIO register base
699   * @retval HAL status
700   */
SDMMC_CmdEraseEndAdd(SDIO_TypeDef * SDIOx,uint32_t EndAdd)701 uint32_t SDMMC_CmdEraseEndAdd(SDIO_TypeDef *SDIOx, uint32_t EndAdd)
702 {
703   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
704   uint32_t errorstate;
705 
706   /* Set Block Size for Card */
707   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
708   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_END;
709   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
710   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
711   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
712   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
713 
714   /* Check for error conditions */
715   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE_GRP_END, SDIO_CMDTIMEOUT);
716 
717   return errorstate;
718 }
719 
720 /**
721   * @brief  Send the Erase command and check the response
722   * @param  SDIOx: Pointer to SDIO register base
723   * @retval HAL status
724   */
SDMMC_CmdErase(SDIO_TypeDef * SDIOx)725 uint32_t SDMMC_CmdErase(SDIO_TypeDef *SDIOx)
726 {
727   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
728   uint32_t errorstate;
729 
730   /* Set Block Size for Card */
731   sdmmc_cmdinit.Argument         = 0U;
732   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE;
733   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
734   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
735   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
736   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
737 
738   /* Check for error conditions */
739   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_ERASE, SDIO_MAXERASETIMEOUT);
740 
741   return errorstate;
742 }
743 
744 /**
745   * @brief  Send the Stop Transfer command and check the response.
746   * @param  SDIOx: Pointer to SDIO register base
747   * @retval HAL status
748   */
SDMMC_CmdStopTransfer(SDIO_TypeDef * SDIOx)749 uint32_t SDMMC_CmdStopTransfer(SDIO_TypeDef *SDIOx)
750 {
751   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
752   uint32_t errorstate;
753 
754   /* Send CMD12 STOP_TRANSMISSION  */
755   sdmmc_cmdinit.Argument         = 0U;
756   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_STOP_TRANSMISSION;
757   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
758   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
759   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
760   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
761 
762   /* Check for error conditions */
763   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_STOP_TRANSMISSION, SDIO_STOPTRANSFERTIMEOUT);
764 
765   return errorstate;
766 }
767 
768 /**
769   * @brief  Send the Select Deselect command and check the response.
770   * @param  SDIOx: Pointer to SDIO register base
771   * @param  addr: Address of the card to be selected
772   * @retval HAL status
773   */
SDMMC_CmdSelDesel(SDIO_TypeDef * SDIOx,uint64_t Addr)774 uint32_t SDMMC_CmdSelDesel(SDIO_TypeDef *SDIOx, uint64_t Addr)
775 {
776   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
777   uint32_t errorstate;
778 
779   /* Send CMD7 SDMMC_SEL_DESEL_CARD */
780   sdmmc_cmdinit.Argument         = (uint32_t)Addr;
781   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEL_DESEL_CARD;
782   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
783   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
784   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
785   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
786 
787   /* Check for error conditions */
788   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEL_DESEL_CARD, SDIO_CMDTIMEOUT);
789 
790   return errorstate;
791 }
792 
793 /**
794   * @brief  Send the Go Idle State command and check the response.
795   * @param  SDIOx: Pointer to SDIO register base
796   * @retval HAL status
797   */
SDMMC_CmdGoIdleState(SDIO_TypeDef * SDIOx)798 uint32_t SDMMC_CmdGoIdleState(SDIO_TypeDef *SDIOx)
799 {
800   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
801   uint32_t errorstate;
802 
803   sdmmc_cmdinit.Argument         = 0U;
804   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_GO_IDLE_STATE;
805   sdmmc_cmdinit.Response         = SDIO_RESPONSE_NO;
806   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
807   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
808   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
809 
810   /* Check for error conditions */
811   errorstate = SDMMC_GetCmdError(SDIOx);
812 
813   return errorstate;
814 }
815 
816 /**
817   * @brief  Send the Operating Condition command and check the response.
818   * @param  SDIOx: Pointer to SDIO register base
819   * @retval HAL status
820   */
SDMMC_CmdOperCond(SDIO_TypeDef * SDIOx)821 uint32_t SDMMC_CmdOperCond(SDIO_TypeDef *SDIOx)
822 {
823   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
824   uint32_t errorstate;
825 
826   /* Send CMD8 to verify SD card interface operating condition */
827   /* Argument: - [31:12]: Reserved (shall be set to '0')
828   - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
829   - [7:0]: Check Pattern (recommended 0xAA) */
830   /* CMD Response: R7 */
831   sdmmc_cmdinit.Argument         = SDMMC_CHECK_PATTERN;
832   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
833   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
834   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
835   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
836   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
837 
838   /* Check for error conditions */
839   errorstate = SDMMC_GetCmdResp7(SDIOx);
840 
841   return errorstate;
842 }
843 
844 /**
845   * @brief  Send the Application command to verify that that the next command
846   *         is an application specific com-mand rather than a standard command
847   *         and check the response.
848   * @param  SDIOx: Pointer to SDIO register base
849   * @param  Argument: Command Argument
850   * @retval HAL status
851   */
SDMMC_CmdAppCommand(SDIO_TypeDef * SDIOx,uint32_t Argument)852 uint32_t SDMMC_CmdAppCommand(SDIO_TypeDef *SDIOx, uint32_t Argument)
853 {
854   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
855   uint32_t errorstate;
856 
857   sdmmc_cmdinit.Argument         = (uint32_t)Argument;
858   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_CMD;
859   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
860   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
861   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
862   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
863 
864   /* Check for error conditions */
865   /* If there is a HAL_ERROR, it is a MMC card, else
866   it is a SD card: SD card 2.0 (voltage range mismatch)
867      or SD card 1.x */
868   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_CMD, SDIO_CMDTIMEOUT);
869 
870   return errorstate;
871 }
872 
873 /**
874   * @brief  Send the command asking the accessed card to send its operating
875   *         condition register (OCR)
876   * @param  SDIOx: Pointer to SDIO register base
877   * @param  Argument: Command Argument
878   * @retval HAL status
879   */
SDMMC_CmdAppOperCommand(SDIO_TypeDef * SDIOx,uint32_t Argument)880 uint32_t SDMMC_CmdAppOperCommand(SDIO_TypeDef *SDIOx, uint32_t Argument)
881 {
882   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
883   uint32_t errorstate;
884 
885   sdmmc_cmdinit.Argument         = SDMMC_VOLTAGE_WINDOW_SD | Argument;
886   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_OP_COND;
887   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
888   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
889   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
890   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
891 
892   /* Check for error conditions */
893   errorstate = SDMMC_GetCmdResp3(SDIOx);
894 
895   return errorstate;
896 }
897 
898 /**
899   * @brief  Send the Bus Width command and check the response.
900   * @param  SDIOx: Pointer to SDIO register base
901   * @param  BusWidth: BusWidth
902   * @retval HAL status
903   */
SDMMC_CmdBusWidth(SDIO_TypeDef * SDIOx,uint32_t BusWidth)904 uint32_t SDMMC_CmdBusWidth(SDIO_TypeDef *SDIOx, uint32_t BusWidth)
905 {
906   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
907   uint32_t errorstate;
908 
909   sdmmc_cmdinit.Argument         = (uint32_t)BusWidth;
910   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
911   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
912   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
913   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
914   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
915 
916   /* Check for error conditions */
917   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDIO_CMDTIMEOUT);
918 
919   return errorstate;
920 }
921 
922 /**
923   * @brief  Send the Send SCR command and check the response.
924   * @param  SDIOx: Pointer to SDIO register base
925   * @retval HAL status
926   */
SDMMC_CmdSendSCR(SDIO_TypeDef * SDIOx)927 uint32_t SDMMC_CmdSendSCR(SDIO_TypeDef *SDIOx)
928 {
929   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
930   uint32_t errorstate;
931 
932   /* Send CMD51 SD_APP_SEND_SCR */
933   sdmmc_cmdinit.Argument         = 0U;
934   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_SEND_SCR;
935   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
936   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
937   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
938   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
939 
940   /* Check for error conditions */
941   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_SEND_SCR, SDIO_CMDTIMEOUT);
942 
943   return errorstate;
944 }
945 
946 /**
947   * @brief  Send the Send CID command and check the response.
948   * @param  SDIOx: Pointer to SDIO register base
949   * @retval HAL status
950   */
SDMMC_CmdSendCID(SDIO_TypeDef * SDIOx)951 uint32_t SDMMC_CmdSendCID(SDIO_TypeDef *SDIOx)
952 {
953   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
954   uint32_t errorstate;
955 
956   /* Send CMD2 ALL_SEND_CID */
957   sdmmc_cmdinit.Argument         = 0U;
958   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ALL_SEND_CID;
959   sdmmc_cmdinit.Response         = SDIO_RESPONSE_LONG;
960   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
961   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
962   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
963 
964   /* Check for error conditions */
965   errorstate = SDMMC_GetCmdResp2(SDIOx);
966 
967   return errorstate;
968 }
969 
970 /**
971   * @brief  Send the Send CSD command and check the response.
972   * @param  SDIOx: Pointer to SDIO register base
973   * @param  Argument: Command Argument
974   * @retval HAL status
975   */
SDMMC_CmdSendCSD(SDIO_TypeDef * SDIOx,uint32_t Argument)976 uint32_t SDMMC_CmdSendCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
977 {
978   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
979   uint32_t errorstate;
980 
981   /* Send CMD9 SEND_CSD */
982   sdmmc_cmdinit.Argument         = Argument;
983   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_CSD;
984   sdmmc_cmdinit.Response         = SDIO_RESPONSE_LONG;
985   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
986   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
987   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
988 
989   /* Check for error conditions */
990   errorstate = SDMMC_GetCmdResp2(SDIOx);
991 
992   return errorstate;
993 }
994 
995 /**
996   * @brief  Send the Send CSD command and check the response.
997   * @param  SDIOx: Pointer to SDIO register base
998   * @param  pRCA: Card RCA
999   * @retval HAL status
1000   */
SDMMC_CmdSetRelAdd(SDIO_TypeDef * SDIOx,uint16_t * pRCA)1001 uint32_t SDMMC_CmdSetRelAdd(SDIO_TypeDef *SDIOx, uint16_t *pRCA)
1002 {
1003   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1004   uint32_t errorstate;
1005 
1006   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1007   sdmmc_cmdinit.Argument         = 0U;
1008   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1009   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1010   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1011   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1012   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1013 
1014   /* Check for error conditions */
1015   errorstate = SDMMC_GetCmdResp6(SDIOx, SDMMC_CMD_SET_REL_ADDR, pRCA);
1016 
1017   return errorstate;
1018 }
1019 
1020 /**
1021   * @brief  Send the Set Relative Address command to MMC card (not SD card).
1022   * @param  SDIOx Pointer to SDIO register base
1023   * @param  RCA Card RCA
1024   * @retval HAL status
1025   */
SDMMC_CmdSetRelAddMmc(SDIO_TypeDef * SDIOx,uint16_t RCA)1026 uint32_t SDMMC_CmdSetRelAddMmc(SDIO_TypeDef *SDIOx, uint16_t RCA)
1027 {
1028   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1029   uint32_t errorstate;
1030 
1031   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1032   sdmmc_cmdinit.Argument         = ((uint32_t)RCA << 16U);
1033   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1034   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1035   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1036   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1037   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1038 
1039   /* Check for error conditions */
1040   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SET_REL_ADDR, SDIO_CMDTIMEOUT);
1041 
1042   return errorstate;
1043 }
1044 
1045 /**
1046   * @brief  Send the Status command and check the response.
1047   * @param  SDIOx: Pointer to SDIO register base
1048   * @param  Argument: Command Argument
1049   * @retval HAL status
1050   */
SDMMC_CmdSendStatus(SDIO_TypeDef * SDIOx,uint32_t Argument)1051 uint32_t SDMMC_CmdSendStatus(SDIO_TypeDef *SDIOx, uint32_t Argument)
1052 {
1053   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1054   uint32_t errorstate;
1055 
1056   sdmmc_cmdinit.Argument         = Argument;
1057   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_STATUS;
1058   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1059   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1060   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1061   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1062 
1063   /* Check for error conditions */
1064   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SEND_STATUS, SDIO_CMDTIMEOUT);
1065 
1066   return errorstate;
1067 }
1068 
1069 /**
1070   * @brief  Send the Status register command and check the response.
1071   * @param  SDIOx: Pointer to SDIO register base
1072   * @retval HAL status
1073   */
SDMMC_CmdStatusRegister(SDIO_TypeDef * SDIOx)1074 uint32_t SDMMC_CmdStatusRegister(SDIO_TypeDef *SDIOx)
1075 {
1076   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1077   uint32_t errorstate;
1078 
1079   sdmmc_cmdinit.Argument         = 0U;
1080   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_STATUS;
1081   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1082   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1083   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1084   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1085 
1086   /* Check for error conditions */
1087   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_SD_APP_STATUS, SDIO_CMDTIMEOUT);
1088 
1089   return errorstate;
1090 }
1091 
1092 /**
1093   * @brief  Sends host capacity support information and activates the card's
1094   *         initialization process. Send SDMMC_CMD_SEND_OP_COND command
1095   * @param  SDIOx: Pointer to SDIO register base
1096   * @parame Argument: Argument used for the command
1097   * @retval HAL status
1098   */
SDMMC_CmdOpCondition(SDIO_TypeDef * SDIOx,uint32_t Argument)1099 uint32_t SDMMC_CmdOpCondition(SDIO_TypeDef *SDIOx, uint32_t Argument)
1100 {
1101   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1102   uint32_t errorstate;
1103 
1104   sdmmc_cmdinit.Argument         = Argument;
1105   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_OP_COND;
1106   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1107   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1108   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1109   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1110 
1111   /* Check for error conditions */
1112   errorstate = SDMMC_GetCmdResp3(SDIOx);
1113 
1114   return errorstate;
1115 }
1116 
1117 /**
1118   * @brief  Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
1119   * @param  SDIOx: Pointer to SDIO register base
1120   * @parame Argument: Argument used for the command
1121   * @retval HAL status
1122   */
SDMMC_CmdSwitch(SDIO_TypeDef * SDIOx,uint32_t Argument)1123 uint32_t SDMMC_CmdSwitch(SDIO_TypeDef *SDIOx, uint32_t Argument)
1124 {
1125   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1126   uint32_t errorstate;
1127 
1128   /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
1129   /* CMD Response: R1 */
1130   sdmmc_cmdinit.Argument         = Argument; /* SDMMC_SDR25_SWITCH_PATTERN */
1131   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SWITCH;
1132   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1133   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1134   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1135   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1136 
1137   /* Check for error conditions */
1138   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SWITCH, SDIO_CMDTIMEOUT);
1139 
1140   return errorstate;
1141 }
1142 
1143 /**
1144   * @brief  Send the Send EXT_CSD command and check the response.
1145   * @param  SDIOx Pointer to SDMMC register base
1146   * @param  Argument Command Argument
1147   * @retval HAL status
1148   */
SDMMC_CmdSendEXTCSD(SDIO_TypeDef * SDIOx,uint32_t Argument)1149 uint32_t SDMMC_CmdSendEXTCSD(SDIO_TypeDef *SDIOx, uint32_t Argument)
1150 {
1151   SDIO_CmdInitTypeDef  sdmmc_cmdinit;
1152   uint32_t errorstate;
1153 
1154   /* Send CMD9 SEND_CSD */
1155   sdmmc_cmdinit.Argument         = Argument;
1156   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
1157   sdmmc_cmdinit.Response         = SDIO_RESPONSE_SHORT;
1158   sdmmc_cmdinit.WaitForInterrupt = SDIO_WAIT_NO;
1159   sdmmc_cmdinit.CPSM             = SDIO_CPSM_ENABLE;
1160   (void)SDIO_SendCommand(SDIOx, &sdmmc_cmdinit);
1161 
1162   /* Check for error conditions */
1163   errorstate = SDMMC_GetCmdResp1(SDIOx, SDMMC_CMD_HS_SEND_EXT_CSD,SDIO_CMDTIMEOUT);
1164 
1165   return errorstate;
1166 }
1167 
1168 /**
1169   * @}
1170   */
1171 
1172 /** @defgroup HAL_SDMMC_LL_Group5 Responses management functions
1173  *  @brief   Responses functions
1174  *
1175 @verbatim
1176  ===============================================================================
1177                    ##### Responses management functions #####
1178  ===============================================================================
1179     [..]
1180     This subsection provides a set of functions allowing to manage the needed responses.
1181 
1182 @endverbatim
1183   * @{
1184   */
1185 /**
1186   * @brief  Checks for error conditions for R1 response.
1187   * @param  SDIOx Pointer to SDMMC register base
1188   * @param  SD_CMD: The sent command index
1189   * @retval SD Card error state
1190   */
SDMMC_GetCmdResp1(SDIO_TypeDef * SDIOx,uint8_t SD_CMD,uint32_t Timeout)1191 uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout)
1192 {
1193   uint32_t response_r1;
1194   uint32_t sta_reg;
1195 
1196   /* 8 is the number of required instructions cycles for the below loop statement.
1197   The Timeout is expressed in ms */
1198   uint32_t count = Timeout * (SystemCoreClock / 8U /1000U);
1199 
1200   do
1201   {
1202     if (count-- == 0U)
1203     {
1204       return SDMMC_ERROR_TIMEOUT;
1205     }
1206     sta_reg = SDIOx->STA;
1207   }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
1208          ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
1209 
1210   if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
1211   {
1212     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
1213 
1214     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1215   }
1216   else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
1217   {
1218     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
1219 
1220     return SDMMC_ERROR_CMD_CRC_FAIL;
1221   }
1222   else
1223   {
1224     /* Nothing to do */
1225   }
1226 
1227   /* Clear all the static flags */
1228   __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
1229 
1230   /* Check response received is of desired command */
1231   if(SDIO_GetCommandResponse(SDIOx) != SD_CMD)
1232   {
1233     return SDMMC_ERROR_CMD_CRC_FAIL;
1234   }
1235 
1236   /* We have received response, retrieve it for analysis  */
1237   response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);
1238 
1239   if((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
1240   {
1241     return SDMMC_ERROR_NONE;
1242   }
1243   else if((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
1244   {
1245     return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
1246   }
1247   else if((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
1248   {
1249     return SDMMC_ERROR_ADDR_MISALIGNED;
1250   }
1251   else if((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
1252   {
1253     return SDMMC_ERROR_BLOCK_LEN_ERR;
1254   }
1255   else if((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
1256   {
1257     return SDMMC_ERROR_ERASE_SEQ_ERR;
1258   }
1259   else if((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
1260   {
1261     return SDMMC_ERROR_BAD_ERASE_PARAM;
1262   }
1263   else if((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
1264   {
1265     return SDMMC_ERROR_WRITE_PROT_VIOLATION;
1266   }
1267   else if((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
1268   {
1269     return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
1270   }
1271   else if((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
1272   {
1273     return SDMMC_ERROR_COM_CRC_FAILED;
1274   }
1275   else if((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
1276   {
1277     return SDMMC_ERROR_ILLEGAL_CMD;
1278   }
1279   else if((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
1280   {
1281     return SDMMC_ERROR_CARD_ECC_FAILED;
1282   }
1283   else if((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
1284   {
1285     return SDMMC_ERROR_CC_ERR;
1286   }
1287   else if((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
1288   {
1289     return SDMMC_ERROR_STREAM_READ_UNDERRUN;
1290   }
1291   else if((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
1292   {
1293     return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
1294   }
1295   else if((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
1296   {
1297     return SDMMC_ERROR_CID_CSD_OVERWRITE;
1298   }
1299   else if((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
1300   {
1301     return SDMMC_ERROR_WP_ERASE_SKIP;
1302   }
1303   else if((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
1304   {
1305     return SDMMC_ERROR_CARD_ECC_DISABLED;
1306   }
1307   else if((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
1308   {
1309     return SDMMC_ERROR_ERASE_RESET;
1310   }
1311   else if((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
1312   {
1313     return SDMMC_ERROR_AKE_SEQ_ERR;
1314   }
1315   else
1316   {
1317     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1318   }
1319 }
1320 
1321 /**
1322   * @brief  Checks for error conditions for R2 (CID or CSD) response.
1323   * @param  SDIOx Pointer to SDMMC register base
1324   * @retval SD Card error state
1325   */
SDMMC_GetCmdResp2(SDIO_TypeDef * SDIOx)1326 uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx)
1327 {
1328   uint32_t sta_reg;
1329   /* 8 is the number of required instructions cycles for the below loop statement.
1330   The SDIO_CMDTIMEOUT is expressed in ms */
1331   uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
1332 
1333   do
1334   {
1335     if (count-- == 0U)
1336     {
1337       return SDMMC_ERROR_TIMEOUT;
1338     }
1339     sta_reg = SDIOx->STA;
1340   }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
1341          ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
1342 
1343   if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
1344   {
1345     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
1346 
1347     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1348   }
1349   else if (__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
1350   {
1351     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
1352 
1353     return SDMMC_ERROR_CMD_CRC_FAIL;
1354   }
1355   else
1356   {
1357     /* No error flag set */
1358     /* Clear all the static flags */
1359     __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
1360   }
1361 
1362   return SDMMC_ERROR_NONE;
1363 }
1364 
1365 /**
1366   * @brief  Checks for error conditions for R3 (OCR) response.
1367   * @param  SDIOx Pointer to SDMMC register base
1368   * @retval SD Card error state
1369   */
SDMMC_GetCmdResp3(SDIO_TypeDef * SDIOx)1370 uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx)
1371 {
1372   uint32_t sta_reg;
1373   /* 8 is the number of required instructions cycles for the below loop statement.
1374   The SDIO_CMDTIMEOUT is expressed in ms */
1375   uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
1376 
1377   do
1378   {
1379     if (count-- == 0U)
1380     {
1381       return SDMMC_ERROR_TIMEOUT;
1382     }
1383     sta_reg = SDIOx->STA;
1384   }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
1385          ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
1386 
1387   if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
1388   {
1389     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
1390 
1391     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1392   }
1393   else
1394   {
1395     /* Clear all the static flags */
1396     __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
1397   }
1398 
1399   return SDMMC_ERROR_NONE;
1400 }
1401 
1402 /**
1403   * @brief  Checks for error conditions for R6 (RCA) response.
1404   * @param  SDIOx Pointer to SDMMC register base
1405   * @param  SD_CMD: The sent command index
1406   * @param  pRCA: Pointer to the variable that will contain the SD card relative
1407   *         address RCA
1408   * @retval SD Card error state
1409   */
SDMMC_GetCmdResp6(SDIO_TypeDef * SDIOx,uint8_t SD_CMD,uint16_t * pRCA)1410 uint32_t SDMMC_GetCmdResp6(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint16_t *pRCA)
1411 {
1412   uint32_t response_r1;
1413   uint32_t sta_reg;
1414 
1415   /* 8 is the number of required instructions cycles for the below loop statement.
1416   The SDIO_CMDTIMEOUT is expressed in ms */
1417   uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
1418 
1419   do
1420   {
1421     if (count-- == 0U)
1422     {
1423       return SDMMC_ERROR_TIMEOUT;
1424     }
1425     sta_reg = SDIOx->STA;
1426   }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
1427          ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
1428 
1429   if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
1430   {
1431     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
1432 
1433     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1434   }
1435   else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
1436   {
1437     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
1438 
1439     return SDMMC_ERROR_CMD_CRC_FAIL;
1440   }
1441   else
1442   {
1443     /* Nothing to do */
1444   }
1445 
1446   /* Check response received is of desired command */
1447   if(SDIO_GetCommandResponse(SDIOx) != SD_CMD)
1448   {
1449     return SDMMC_ERROR_CMD_CRC_FAIL;
1450   }
1451 
1452   /* Clear all the static flags */
1453   __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
1454 
1455   /* We have received response, retrieve it.  */
1456   response_r1 = SDIO_GetResponse(SDIOx, SDIO_RESP1);
1457 
1458   if((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD | SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
1459   {
1460     *pRCA = (uint16_t) (response_r1 >> 16);
1461 
1462     return SDMMC_ERROR_NONE;
1463   }
1464   else if((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
1465   {
1466     return SDMMC_ERROR_ILLEGAL_CMD;
1467   }
1468   else if((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
1469   {
1470     return SDMMC_ERROR_COM_CRC_FAILED;
1471   }
1472   else
1473   {
1474     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1475   }
1476 }
1477 
1478 /**
1479   * @brief  Checks for error conditions for R7 response.
1480   * @param  SDIOx Pointer to SDMMC register base
1481   * @retval SD Card error state
1482   */
SDMMC_GetCmdResp7(SDIO_TypeDef * SDIOx)1483 uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx)
1484 {
1485   uint32_t sta_reg;
1486   /* 8 is the number of required instructions cycles for the below loop statement.
1487   The SDIO_CMDTIMEOUT is expressed in ms */
1488   uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
1489 
1490   do
1491   {
1492     if (count-- == 0U)
1493     {
1494       return SDMMC_ERROR_TIMEOUT;
1495     }
1496     sta_reg = SDIOx->STA;
1497   }while(((sta_reg & (SDIO_FLAG_CCRCFAIL | SDIO_FLAG_CMDREND | SDIO_FLAG_CTIMEOUT)) == 0U) ||
1498          ((sta_reg & SDIO_FLAG_CMDACT) != 0U ));
1499 
1500   if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT))
1501   {
1502     /* Card is SD V2.0 compliant */
1503     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CTIMEOUT);
1504 
1505     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1506   }
1507   else if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL))
1508   {
1509     /* Card is SD V2.0 compliant */
1510     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CCRCFAIL);
1511 
1512     return SDMMC_ERROR_CMD_CRC_FAIL;
1513   }
1514   else
1515   {
1516     /* Nothing to do */
1517   }
1518 
1519   if(__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDREND))
1520   {
1521     /* Card is SD V2.0 compliant */
1522     __SDIO_CLEAR_FLAG(SDIOx, SDIO_FLAG_CMDREND);
1523   }
1524 
1525   return SDMMC_ERROR_NONE;
1526 
1527 }
1528 
1529 /**
1530   * @}
1531   */
1532 
1533 /* Private function ----------------------------------------------------------*/
1534 /** @addtogroup SD_Private_Functions
1535   * @{
1536   */
1537 
1538 /**
1539   * @brief  Checks for error conditions for CMD0.
1540   * @param  SDIOx Pointer to SDMMC register base
1541   * @retval SD Card error state
1542   */
SDMMC_GetCmdError(SDIO_TypeDef * SDIOx)1543 static uint32_t SDMMC_GetCmdError(SDIO_TypeDef *SDIOx)
1544 {
1545   /* 8 is the number of required instructions cycles for the below loop statement.
1546   The SDIO_CMDTIMEOUT is expressed in ms */
1547   uint32_t count = SDIO_CMDTIMEOUT * (SystemCoreClock / 8U /1000U);
1548 
1549   do
1550   {
1551     if (count-- == 0U)
1552     {
1553       return SDMMC_ERROR_TIMEOUT;
1554     }
1555 
1556   }while(!__SDIO_GET_FLAG(SDIOx, SDIO_FLAG_CMDSENT));
1557 
1558   /* Clear all the static flags */
1559   __SDIO_CLEAR_FLAG(SDIOx, SDIO_STATIC_CMD_FLAGS);
1560 
1561   return SDMMC_ERROR_NONE;
1562 }
1563 
1564 
1565 /**
1566   * @}
1567   */
1568 
1569 #endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
1570 /**
1571   * @}
1572   */
1573 
1574 /**
1575   * @}
1576   */
1577 
1578 #endif /* SDIO */
1579