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