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