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