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