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