1 /**
2 ******************************************************************************
3 * @file stm32f2xx_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 "stm32f2xx_hal.h"
160
161 #if defined(SDIO)
162
163 /** @addtogroup STM32F2xx_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