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