Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:10

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_ll_sdmmc.c
0004   * @author  MCD Application Team
0005   * @brief   SDMMC Low Layer HAL module driver.
0006   *
0007   *          This file provides firmware functions to manage the following
0008   *          functionalities of the SDMMC peripheral:
0009   *           + Initialization/de-initialization functions
0010   *           + I/O operation functions
0011   *           + Peripheral Control functions
0012   *           + Peripheral State functions
0013   *
0014   ******************************************************************************
0015   * @attention
0016   *
0017   * Copyright (c) 2017 STMicroelectronics.
0018   * All rights reserved.
0019   *
0020   * This software is licensed under terms that can be found in the LICENSE file
0021   * in the root directory of this software component.
0022   * If no LICENSE file comes with this software, it is provided AS-IS.
0023   *
0024   ******************************************************************************
0025   @verbatim
0026   ==============================================================================
0027                        ##### SDMMC peripheral features #####
0028   ==============================================================================
0029     [..] The SD/SDMMC MMC card host interface (SDMMC) provides an interface between the AHB
0030          peripheral bus and MultiMedia cards (MMCs), SD memory cards, SDMMC cards and CE-ATA
0031          devices.
0032 
0033     [..] The SDMMC features include the following:
0034          (+) Full compliance with MultiMediaCard System Specification Version 4.51. Card support
0035              for three different databus modes: 1-bit (default), 4-bit and 8-bit.
0036          (+) Full compatibility with previous versions of MultiMediaCards (backward compatibility).
0037          (+) Full compliance with SD memory card specifications version 4.1.
0038              (SDR104 SDMMC_CK speed limited to maximum allowed IO speed, SPI mode and
0039               UHS-II mode not supported).
0040          (+) Full compliance with SDIO card specification version 4.0. Card support
0041              for two different databus modes: 1-bit (default) and 4-bit.
0042              (SDR104 SDMMC_CK speed limited to maximum allowed IO speed, SPI mode and
0043               UHS-II mode not supported).
0044          (+) Data transfer up to 208 Mbyte/s for the 8 bit mode. (depending maximum allowed IO speed).
0045          (+) Data and command output enable signals to control external bidirectional drivers
0046 
0047                            ##### How to use this driver #####
0048   ==============================================================================
0049     [..]
0050       This driver is a considered as a driver of service for external devices drivers
0051       that interfaces with the SDMMC peripheral.
0052       According to the device used (SD card/ MMC card / SDMMC card ...), a set of APIs
0053       is used in the device's driver to perform SDMMC operations and functionalities.
0054 
0055       This driver is almost transparent for the final user, it is only used to implement other
0056       functionalities of the external device.
0057 
0058     [..]
0059       (+) The SDMMC clock is coming from output of PLL1_Q or PLL2_R.
0060        Before start working with SDMMC peripheral make sure that the PLL is well configured.
0061           The SDMMC peripheral uses two clock signals:
0062           (++) PLL1_Q bus clock (default after reset)
0063           (++) PLL2_R bus clock
0064 
0065       (+) Enable/Disable peripheral clock using RCC peripheral macros related to SDMMC
0066           peripheral.
0067 
0068       (+) Enable the Power ON State using the SDMMC_PowerState_ON(SDMMCx)
0069           function and disable it using the function SDMMC_PowerState_OFF(SDMMCx).
0070 
0071       (+) Enable/Disable the peripheral interrupts using the macros __SDMMC_ENABLE_IT(hSDMMC, IT)
0072           and __SDMMC_DISABLE_IT(hSDMMC, IT) if you need to use interrupt mode.
0073 
0074       (+) When using the DMA mode
0075           (++) Configure the IDMA mode (Single buffer or double)
0076           (++) Configure the buffer address
0077           (++) Configure Data Path State Machine
0078 
0079       (+) To control the CPSM (Command Path State Machine) and send
0080           commands to the card use the SDMMC_SendCommand(SDMMCx),
0081           SDMMC_GetCommandResponse() and SDMMC_GetResponse() functions. First, user has
0082           to fill the command structure (pointer to SDMMC_CmdInitTypeDef) according
0083           to the selected command to be sent.
0084           The parameters that should be filled are:
0085            (++) Command Argument
0086            (++) Command Index
0087            (++) Command Response type
0088            (++) Command Wait
0089            (++) CPSM Status (Enable or Disable).
0090 
0091           -@@- To check if the command is well received, read the SDMMC_CMDRESP
0092               register using the SDMMC_GetCommandResponse().
0093               The SDMMC responses registers (SDMMC_RESP1 to SDMMC_RESP2), use the
0094               SDMMC_GetResponse() function.
0095 
0096       (+) To control the DPSM (Data Path State Machine) and send/receive
0097            data to/from the card use the SDMMC_DataConfig(), SDMMC_GetDataCounter(),
0098           SDMMC_ReadFIFO(), SDMMC_WriteFIFO() and SDMMC_GetFIFOCount() functions.
0099 
0100     *** Read Operations ***
0101     =======================
0102     [..]
0103       (#) First, user has to fill the data structure (pointer to
0104           SDMMC_DataInitTypeDef) according to the selected data type to be received.
0105           The parameters that should be filled are:
0106            (++) Data TimeOut
0107            (++) Data Length
0108            (++) Data Block size
0109            (++) Data Transfer direction: should be from card (To SDMMC)
0110            (++) Data Transfer mode
0111            (++) DPSM Status (Enable or Disable)
0112 
0113       (#) Configure the SDMMC resources to receive the data from the card
0114           according to selected transfer mode (Refer to Step 8, 9 and 10).
0115 
0116       (#) Send the selected Read command (refer to step 11).
0117 
0118       (#) Use the SDMMC flags/interrupts to check the transfer status.
0119 
0120     *** Write Operations ***
0121     ========================
0122     [..]
0123      (#) First, user has to fill the data structure (pointer to
0124          SDMMC_DataInitTypeDef) according to the selected data type to be received.
0125          The parameters that should be filled are:
0126           (++) Data TimeOut
0127           (++) Data Length
0128           (++) Data Block size
0129           (++) Data Transfer direction:  should be to card (To CARD)
0130           (++) Data Transfer mode
0131           (++) DPSM Status (Enable or Disable)
0132 
0133      (#) Configure the SDMMC resources to send the data to the card according to
0134          selected transfer mode.
0135 
0136      (#) Send the selected Write command.
0137 
0138      (#) Use the SDMMC flags/interrupts to check the transfer status.
0139 
0140     *** Command management operations ***
0141     =====================================
0142     [..]
0143      (#) The commands used for Read/Write/Erase operations are managed in
0144          separate functions.
0145          Each function allows to send the needed command with the related argument,
0146          then check the response.
0147          By the same approach, you could implement a command and check the response.
0148 
0149   @endverbatim
0150   ******************************************************************************
0151   */
0152 
0153 /* Includes ------------------------------------------------------------------*/
0154 #include "stm32h7xx_hal.h"
0155 
0156 /** @addtogroup STM32H7xx_HAL_Driver
0157   * @{
0158   */
0159 
0160 /** @defgroup SDMMC_LL SDMMC Low Layer
0161   * @ingroup RTEMSBSPsARMSTM32H7
0162   * @brief Low layer module for SD
0163   * @{
0164   */
0165 
0166 #if defined (HAL_SD_MODULE_ENABLED) || defined (HAL_MMC_MODULE_ENABLED)
0167 
0168 /* Private typedef -----------------------------------------------------------*/
0169 /* Private define ------------------------------------------------------------*/
0170 /* Private macro -------------------------------------------------------------*/
0171 /* Private variables ---------------------------------------------------------*/
0172 /* Private function prototypes -----------------------------------------------*/
0173 static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx);
0174 
0175 /* Exported functions --------------------------------------------------------*/
0176 
0177 /** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
0178   * @ingroup RTEMSBSPsARMSTM32H7
0179   * @{
0180   */
0181 
0182 /** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
0183   * @ingroup RTEMSBSPsARMSTM32H7
0184   *  @brief    Initialization and Configuration functions
0185   *
0186 @verbatim
0187  ===============================================================================
0188               ##### Initialization/de-initialization functions #####
0189  ===============================================================================
0190     [..]  This section provides functions allowing to:
0191 
0192 @endverbatim
0193   * @{
0194   */
0195 
0196 /**
0197   * @brief  Initializes the SDMMC according to the specified
0198   *         parameters in the SDMMC_InitTypeDef and create the associated handle.
0199   * @param  SDMMCx: Pointer to SDMMC register base
0200   * @param  Init: SDMMC initialization structure
0201   * @retval HAL status
0202   */
0203 HAL_StatusTypeDef SDMMC_Init(SDMMC_TypeDef *SDMMCx, SDMMC_InitTypeDef Init)
0204 {
0205   uint32_t tmpreg = 0;
0206 
0207   /* Check the parameters */
0208   assert_param(IS_SDMMC_ALL_INSTANCE(SDMMCx));
0209   assert_param(IS_SDMMC_CLOCK_EDGE(Init.ClockEdge));
0210   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(Init.ClockPowerSave));
0211   assert_param(IS_SDMMC_BUS_WIDE(Init.BusWide));
0212   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
0213   assert_param(IS_SDMMC_CLKDIV(Init.ClockDiv));
0214 
0215   /* Set SDMMC configuration parameters */
0216   tmpreg |= (Init.ClockEdge           | \
0217              Init.ClockPowerSave      | \
0218              Init.BusWide             | \
0219              Init.HardwareFlowControl | \
0220              Init.ClockDiv
0221             );
0222 
0223   /* Write to SDMMC CLKCR */
0224   MODIFY_REG(SDMMCx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
0225 
0226   return HAL_OK;
0227 }
0228 
0229 
0230 /**
0231   * @}
0232   */
0233 
0234 /** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
0235   * @ingroup RTEMSBSPsARMSTM32H7
0236   *  @brief   Data transfers functions
0237   *
0238 @verbatim
0239  ===============================================================================
0240                       ##### I/O operation functions #####
0241  ===============================================================================
0242     [..]
0243     This subsection provides a set of functions allowing to manage the SDMMC data
0244     transfers.
0245 
0246 @endverbatim
0247   * @{
0248   */
0249 
0250 /**
0251   * @brief  Read data (word) from Rx FIFO in blocking mode (polling)
0252   * @param  SDMMCx: Pointer to SDMMC register base
0253   * @retval HAL status
0254   */
0255 uint32_t SDMMC_ReadFIFO(SDMMC_TypeDef *SDMMCx)
0256 {
0257   /* Read data from Rx FIFO */
0258   return (SDMMCx->FIFO);
0259 }
0260 
0261 /**
0262   * @brief  Write data (word) to Tx FIFO in blocking mode (polling)
0263   * @param  SDMMCx: Pointer to SDMMC register base
0264   * @param  pWriteData: pointer to data to write
0265   * @retval HAL status
0266   */
0267 HAL_StatusTypeDef SDMMC_WriteFIFO(SDMMC_TypeDef *SDMMCx, uint32_t *pWriteData)
0268 {
0269   /* Write data to FIFO */
0270   SDMMCx->FIFO = *pWriteData;
0271 
0272   return HAL_OK;
0273 }
0274 
0275 /**
0276   * @}
0277   */
0278 
0279 /** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
0280   * @ingroup RTEMSBSPsARMSTM32H7
0281   *  @brief   management functions
0282   *
0283 @verbatim
0284  ===============================================================================
0285                       ##### Peripheral Control functions #####
0286  ===============================================================================
0287     [..]
0288     This subsection provides a set of functions allowing to control the SDMMC data
0289     transfers.
0290 
0291 @endverbatim
0292   * @{
0293   */
0294 
0295 /**
0296   * @brief  Set SDMMC Power state to ON.
0297   * @param  SDMMCx: Pointer to SDMMC register base
0298   * @retval HAL status
0299   */
0300 HAL_StatusTypeDef SDMMC_PowerState_ON(SDMMC_TypeDef *SDMMCx)
0301 {
0302   /* Set power state to ON */
0303   SDMMCx->POWER |= SDMMC_POWER_PWRCTRL;
0304 
0305   return HAL_OK;
0306 }
0307 
0308 /**
0309   * @brief  Set SDMMC Power state to Power-Cycle.
0310   * @param  SDMMCx: Pointer to SDMMC register base
0311   * @retval HAL status
0312   */
0313 HAL_StatusTypeDef SDMMC_PowerState_Cycle(SDMMC_TypeDef *SDMMCx)
0314 {
0315   /* Set power state to Power Cycle*/
0316   SDMMCx->POWER |= SDMMC_POWER_PWRCTRL_1;
0317 
0318   return HAL_OK;
0319 }
0320 
0321 /**
0322   * @brief  Set SDMMC Power state to OFF.
0323   * @param  SDMMCx: Pointer to SDMMC register base
0324   * @retval HAL status
0325   */
0326 HAL_StatusTypeDef SDMMC_PowerState_OFF(SDMMC_TypeDef *SDMMCx)
0327 {
0328   /* Set power state to OFF */
0329   SDMMCx->POWER &= ~(SDMMC_POWER_PWRCTRL);
0330 
0331   return HAL_OK;
0332 }
0333 
0334 /**
0335   * @brief  Get SDMMC Power state.
0336   * @param  SDMMCx: Pointer to SDMMC register base
0337   * @retval Power status of the controller. The returned value can be one of the
0338   *         following values:
0339   *            - 0x00: Power OFF
0340   *            - 0x02: Power UP
0341   *            - 0x03: Power ON
0342   */
0343 uint32_t SDMMC_GetPowerState(SDMMC_TypeDef *SDMMCx)
0344 {
0345   return (SDMMCx->POWER & SDMMC_POWER_PWRCTRL);
0346 }
0347 
0348 /**
0349   * @brief  Configure the SDMMC command path according to the specified parameters in
0350   *         SDMMC_CmdInitTypeDef structure and send the command
0351   * @param  SDMMCx: Pointer to SDMMC register base
0352   * @param  Command: pointer to a SDMMC_CmdInitTypeDef structure that contains
0353   *         the configuration information for the SDMMC command
0354   * @retval HAL status
0355   */
0356 HAL_StatusTypeDef SDMMC_SendCommand(SDMMC_TypeDef *SDMMCx, SDMMC_CmdInitTypeDef *Command)
0357 {
0358   uint32_t tmpreg = 0;
0359 
0360   /* Check the parameters */
0361   assert_param(IS_SDMMC_CMD_INDEX(Command->CmdIndex));
0362   assert_param(IS_SDMMC_RESPONSE(Command->Response));
0363   assert_param(IS_SDMMC_WAIT(Command->WaitForInterrupt));
0364   assert_param(IS_SDMMC_CPSM(Command->CPSM));
0365 
0366   /* Set the SDMMC Argument value */
0367   SDMMCx->ARG = Command->Argument;
0368 
0369   /* Set SDMMC command parameters */
0370   tmpreg |= (uint32_t)(Command->CmdIndex         | \
0371                        Command->Response         | \
0372                        Command->WaitForInterrupt | \
0373                        Command->CPSM);
0374 
0375   /* Write to SDMMC CMD register */
0376   MODIFY_REG(SDMMCx->CMD, CMD_CLEAR_MASK, tmpreg);
0377 
0378   return HAL_OK;
0379 }
0380 
0381 /**
0382   * @brief  Return the command index of last command for which response received
0383   * @param  SDMMCx: Pointer to SDMMC register base
0384   * @retval Command index of the last command response received
0385   */
0386 uint8_t SDMMC_GetCommandResponse(SDMMC_TypeDef *SDMMCx)
0387 {
0388   return (uint8_t)(SDMMCx->RESPCMD);
0389 }
0390 
0391 
0392 /**
0393   * @brief  Return the response received from the card for the last command
0394   * @param  SDMMCx: Pointer to SDMMC register base
0395   * @param  Response: Specifies the SDMMC response register.
0396   *          This parameter can be one of the following values:
0397   *            @arg SDMMC_RESP1: Response Register 1
0398   *            @arg SDMMC_RESP2: Response Register 2
0399   *            @arg SDMMC_RESP3: Response Register 3
0400   *            @arg SDMMC_RESP4: Response Register 4
0401   * @retval The Corresponding response register value
0402   */
0403 uint32_t SDMMC_GetResponse(SDMMC_TypeDef *SDMMCx, uint32_t Response)
0404 {
0405   uint32_t tmp;
0406 
0407   /* Check the parameters */
0408   assert_param(IS_SDMMC_RESP(Response));
0409 
0410   /* Get the response */
0411   tmp = (uint32_t)(&(SDMMCx->RESP1)) + Response;
0412 
0413   return (*(__IO uint32_t *) tmp);
0414 }
0415 
0416 /**
0417   * @brief  Configure the SDMMC data path according to the specified
0418   *         parameters in the SDMMC_DataInitTypeDef.
0419   * @param  SDMMCx: Pointer to SDMMC register base
0420   * @param  Data : pointer to a SDMMC_DataInitTypeDef structure
0421   *         that contains the configuration information for the SDMMC data.
0422   * @retval HAL status
0423   */
0424 HAL_StatusTypeDef SDMMC_ConfigData(SDMMC_TypeDef *SDMMCx, SDMMC_DataInitTypeDef *Data)
0425 {
0426   uint32_t tmpreg = 0;
0427 
0428   /* Check the parameters */
0429   assert_param(IS_SDMMC_DATA_LENGTH(Data->DataLength));
0430   assert_param(IS_SDMMC_BLOCK_SIZE(Data->DataBlockSize));
0431   assert_param(IS_SDMMC_TRANSFER_DIR(Data->TransferDir));
0432   assert_param(IS_SDMMC_TRANSFER_MODE(Data->TransferMode));
0433   assert_param(IS_SDMMC_DPSM(Data->DPSM));
0434 
0435   /* Set the SDMMC Data TimeOut value */
0436   SDMMCx->DTIMER = Data->DataTimeOut;
0437 
0438   /* Set the SDMMC DataLength value */
0439   SDMMCx->DLEN = Data->DataLength;
0440 
0441   /* Set the SDMMC data configuration parameters */
0442   tmpreg |= (uint32_t)(Data->DataBlockSize | \
0443                        Data->TransferDir   | \
0444                        Data->TransferMode  | \
0445                        Data->DPSM);
0446 
0447   /* Write to SDMMC DCTRL */
0448   MODIFY_REG(SDMMCx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
0449 
0450   return HAL_OK;
0451 
0452 }
0453 
0454 /**
0455   * @brief  Returns number of remaining data bytes to be transferred.
0456   * @param  SDMMCx: Pointer to SDMMC register base
0457   * @retval Number of remaining data bytes to be transferred
0458   */
0459 uint32_t SDMMC_GetDataCounter(SDMMC_TypeDef *SDMMCx)
0460 {
0461   return (SDMMCx->DCOUNT);
0462 }
0463 
0464 /**
0465   * @brief  Get the FIFO data
0466   * @param  SDMMCx: Pointer to SDMMC register base
0467   * @retval Data received
0468   */
0469 uint32_t SDMMC_GetFIFOCount(SDMMC_TypeDef *SDMMCx)
0470 {
0471   return (SDMMCx->FIFO);
0472 }
0473 
0474 /**
0475   * @brief  Sets one of the two options of inserting read wait interval.
0476   * @param  SDMMCx: Pointer to SDMMC register base
0477   * @param  SDMMC_ReadWaitMode: SDMMC Read Wait operation mode.
0478   *          This parameter can be:
0479   *            @arg SDMMC_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
0480   *            @arg SDMMC_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
0481   * @retval None
0482   */
0483 HAL_StatusTypeDef SDMMC_SetSDMMCReadWaitMode(SDMMC_TypeDef *SDMMCx, uint32_t SDMMC_ReadWaitMode)
0484 {
0485   /* Check the parameters */
0486   assert_param(IS_SDMMC_READWAIT_MODE(SDMMC_ReadWaitMode));
0487 
0488   /* Set SDMMC read wait mode */
0489   MODIFY_REG(SDMMCx->DCTRL, SDMMC_DCTRL_RWMOD, SDMMC_ReadWaitMode);
0490 
0491   return HAL_OK;
0492 }
0493 
0494 /**
0495   * @}
0496   */
0497 
0498 
0499 /** @defgroup HAL_SDMMC_LL_Group4 Command management functions
0500   * @ingroup RTEMSBSPsARMSTM32H7
0501   *  @brief   Data transfers functions
0502   *
0503 @verbatim
0504  ===============================================================================
0505                    ##### Commands management functions #####
0506  ===============================================================================
0507     [..]
0508     This subsection provides a set of functions allowing to manage the needed commands.
0509 
0510 @endverbatim
0511   * @{
0512   */
0513 
0514 /**
0515   * @brief  Send the Data Block Length command and check the response
0516   * @param  SDMMCx: Pointer to SDMMC register base
0517   * @retval HAL status
0518   */
0519 uint32_t SDMMC_CmdBlockLength(SDMMC_TypeDef *SDMMCx, uint32_t BlockSize)
0520 {
0521   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0522   uint32_t errorstate;
0523 
0524   /* Set Block Size for Card */
0525   sdmmc_cmdinit.Argument         = (uint32_t)BlockSize;
0526   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_BLOCKLEN;
0527   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0528   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0529   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0530   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0531 
0532   /* Check for error conditions */
0533   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SET_BLOCKLEN, SDMMC_CMDTIMEOUT);
0534 
0535   return errorstate;
0536 }
0537 
0538 /**
0539   * @brief  Send the Read Single Block command and check the response
0540   * @param  SDMMCx: Pointer to SDMMC register base
0541   * @retval HAL status
0542   */
0543 uint32_t SDMMC_CmdReadSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
0544 {
0545   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0546   uint32_t errorstate;
0547 
0548   /* Set Block Size for Card */
0549   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
0550   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_SINGLE_BLOCK;
0551   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0552   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0553   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0554   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0555 
0556   /* Check for error conditions */
0557   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
0558 
0559   return errorstate;
0560 }
0561 
0562 /**
0563   * @brief  Send the Read Multi Block command and check the response
0564   * @param  SDMMCx: Pointer to SDMMC register base
0565   * @retval HAL status
0566   */
0567 uint32_t SDMMC_CmdReadMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
0568 {
0569   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0570   uint32_t errorstate;
0571 
0572   /* Set Block Size for Card */
0573   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
0574   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_MULT_BLOCK;
0575   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0576   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0577   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0578   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0579 
0580   /* Check for error conditions */
0581   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_MULT_BLOCK, SDMMC_CMDTIMEOUT);
0582 
0583   return errorstate;
0584 }
0585 
0586 /**
0587   * @brief  Send the Write Single Block command and check the response
0588   * @param  SDMMCx: Pointer to SDMMC register base
0589   * @retval HAL status
0590   */
0591 uint32_t SDMMC_CmdWriteSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
0592 {
0593   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0594   uint32_t errorstate;
0595 
0596   /* Set Block Size for Card */
0597   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
0598   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_SINGLE_BLOCK;
0599   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0600   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0601   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0602   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0603 
0604   /* Check for error conditions */
0605   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
0606 
0607   return errorstate;
0608 }
0609 
0610 /**
0611   * @brief  Send the Write Multi Block command and check the response
0612   * @param  SDMMCx: Pointer to SDMMC register base
0613   * @retval HAL status
0614   */
0615 uint32_t SDMMC_CmdWriteMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
0616 {
0617   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0618   uint32_t errorstate;
0619 
0620   /* Set Block Size for Card */
0621   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
0622   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_MULT_BLOCK;
0623   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0624   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0625   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0626   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0627 
0628   /* Check for error conditions */
0629   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_WRITE_MULT_BLOCK, SDMMC_CMDTIMEOUT);
0630 
0631   return errorstate;
0632 }
0633 
0634 /**
0635   * @brief  Send the Start Address Erase command for SD and check the response
0636   * @param  SDMMCx: Pointer to SDMMC register base
0637   * @retval HAL status
0638   */
0639 uint32_t SDMMC_CmdSDEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
0640 {
0641   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0642   uint32_t errorstate;
0643 
0644   /* Set Block Size for Card */
0645   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
0646   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_START;
0647   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0648   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0649   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0650   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0651 
0652   /* Check for error conditions */
0653   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_ERASE_GRP_START, SDMMC_CMDTIMEOUT);
0654 
0655   return errorstate;
0656 }
0657 
0658 /**
0659   * @brief  Send the End Address Erase command for SD and check the response
0660   * @param  SDMMCx: Pointer to SDMMC register base
0661   * @retval HAL status
0662   */
0663 uint32_t SDMMC_CmdSDEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
0664 {
0665   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0666   uint32_t errorstate;
0667 
0668   /* Set Block Size for Card */
0669   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
0670   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_END;
0671   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0672   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0673   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0674   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0675 
0676   /* Check for error conditions */
0677   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
0678 
0679   return errorstate;
0680 }
0681 
0682 /**
0683   * @brief  Send the Start Address Erase command and check the response
0684   * @param  SDMMCx: Pointer to SDMMC register base
0685   * @retval HAL status
0686   */
0687 uint32_t SDMMC_CmdEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
0688 {
0689   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0690   uint32_t errorstate;
0691 
0692   /* Set Block Size for Card */
0693   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
0694   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_START;
0695   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0696   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0697   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0698   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0699 
0700   /* Check for error conditions */
0701   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_START, SDMMC_CMDTIMEOUT);
0702 
0703   return errorstate;
0704 }
0705 
0706 /**
0707   * @brief  Send the End Address Erase command and check the response
0708   * @param  SDMMCx: Pointer to SDMMC register base
0709   * @retval HAL status
0710   */
0711 uint32_t SDMMC_CmdEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
0712 {
0713   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0714   uint32_t errorstate;
0715 
0716   /* Set Block Size for Card */
0717   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
0718   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_END;
0719   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0720   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0721   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0722   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0723 
0724   /* Check for error conditions */
0725   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
0726 
0727   return errorstate;
0728 }
0729 
0730 /**
0731   * @brief  Send the Erase command and check the response
0732   * @param  SDMMCx Pointer to SDMMC register base
0733   * @param  EraseType Type of erase to be performed
0734   * @retval HAL status
0735   */
0736 uint32_t SDMMC_CmdErase(SDMMC_TypeDef *SDMMCx, uint32_t EraseType)
0737 {
0738   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0739   uint32_t errorstate;
0740 
0741   /* Set Block Size for Card */
0742   sdmmc_cmdinit.Argument         = EraseType;
0743   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE;
0744   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0745   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0746   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0747   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0748 
0749   /* Check for error conditions */
0750   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE, SDMMC_MAXERASETIMEOUT);
0751 
0752   return errorstate;
0753 }
0754 
0755 /**
0756   * @brief  Send the Stop Transfer command and check the response.
0757   * @param  SDMMCx: Pointer to SDMMC register base
0758   * @retval HAL status
0759   */
0760 uint32_t SDMMC_CmdStopTransfer(SDMMC_TypeDef *SDMMCx)
0761 {
0762   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0763   uint32_t errorstate;
0764 
0765   /* Send CMD12 STOP_TRANSMISSION  */
0766   sdmmc_cmdinit.Argument         = 0U;
0767   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_STOP_TRANSMISSION;
0768   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0769   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0770   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0771 
0772   __SDMMC_CMDSTOP_ENABLE(SDMMCx);
0773   __SDMMC_CMDTRANS_DISABLE(SDMMCx);
0774 
0775   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0776 
0777   /* Check for error conditions */
0778   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_STOP_TRANSMISSION, SDMMC_STOPTRANSFERTIMEOUT);
0779 
0780   __SDMMC_CMDSTOP_DISABLE(SDMMCx);
0781 
0782   /* Ignore Address Out Of Range Error, Not relevant at end of memory */
0783   if (errorstate == SDMMC_ERROR_ADDR_OUT_OF_RANGE)
0784   {
0785     errorstate = SDMMC_ERROR_NONE;
0786   }
0787 
0788   return errorstate;
0789 }
0790 
0791 /**
0792   * @brief  Send the Select Deselect command and check the response.
0793   * @param  SDMMCx: Pointer to SDMMC register base
0794   * @param  addr: Address of the card to be selected
0795   * @retval HAL status
0796   */
0797 uint32_t SDMMC_CmdSelDesel(SDMMC_TypeDef *SDMMCx, uint32_t Addr)
0798 {
0799   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0800   uint32_t errorstate;
0801 
0802   /* Send CMD7 SDMMC_SEL_DESEL_CARD */
0803   sdmmc_cmdinit.Argument         = (uint32_t)Addr;
0804   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEL_DESEL_CARD;
0805   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0806   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0807   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0808   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0809 
0810   /* Check for error conditions */
0811   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEL_DESEL_CARD, SDMMC_CMDTIMEOUT);
0812 
0813   return errorstate;
0814 }
0815 
0816 /**
0817   * @brief  Send the Go Idle State command and check the response.
0818   * @param  SDMMCx: Pointer to SDMMC register base
0819   * @retval HAL status
0820   */
0821 uint32_t SDMMC_CmdGoIdleState(SDMMC_TypeDef *SDMMCx)
0822 {
0823   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0824   uint32_t errorstate;
0825 
0826   sdmmc_cmdinit.Argument         = 0U;
0827   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_GO_IDLE_STATE;
0828   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_NO;
0829   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0830   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0831   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0832 
0833   /* Check for error conditions */
0834   errorstate = SDMMC_GetCmdError(SDMMCx);
0835 
0836   return errorstate;
0837 }
0838 
0839 /**
0840   * @brief  Send the Operating Condition command and check the response.
0841   * @param  SDMMCx: Pointer to SDMMC register base
0842   * @retval HAL status
0843   */
0844 uint32_t SDMMC_CmdOperCond(SDMMC_TypeDef *SDMMCx)
0845 {
0846   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0847   uint32_t errorstate;
0848 
0849   /* Send CMD8 to verify SD card interface operating condition */
0850   /* Argument: - [31:12]: Reserved (shall be set to '0')
0851   - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
0852   - [7:0]: Check Pattern (recommended 0xAA) */
0853   /* CMD Response: R7 */
0854   sdmmc_cmdinit.Argument         = SDMMC_CHECK_PATTERN;
0855   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
0856   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0857   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0858   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0859   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0860 
0861   /* Check for error conditions */
0862   errorstate = SDMMC_GetCmdResp7(SDMMCx);
0863 
0864   return errorstate;
0865 }
0866 
0867 /**
0868   * @brief  Send the Application command to verify that that the next command
0869   *         is an application specific com-mand rather than a standard command
0870   *         and check the response.
0871   * @param  SDMMCx: Pointer to SDMMC register base
0872   * @param  Argument: Command Argument
0873   * @retval HAL status
0874   */
0875 uint32_t SDMMC_CmdAppCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
0876 {
0877   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0878   uint32_t errorstate;
0879 
0880   sdmmc_cmdinit.Argument         = (uint32_t)Argument;
0881   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_CMD;
0882   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0883   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0884   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0885   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0886 
0887   /* Check for error conditions */
0888   /* If there is a HAL_ERROR, it is a MMC card, else
0889   it is a SD card: SD card 2.0 (voltage range mismatch)
0890      or SD card 1.x */
0891   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_CMD, SDMMC_CMDTIMEOUT);
0892 
0893   return errorstate;
0894 }
0895 
0896 /**
0897   * @brief  Send the command asking the accessed card to send its operating
0898   *         condition register (OCR)
0899   * @param  SDMMCx: Pointer to SDMMC register base
0900   * @param  Argument: Command Argument
0901   * @retval HAL status
0902   */
0903 uint32_t SDMMC_CmdAppOperCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
0904 {
0905   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0906   uint32_t errorstate;
0907 
0908   sdmmc_cmdinit.Argument         = Argument;
0909   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_OP_COND;
0910   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0911   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0912   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0913   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0914 
0915   /* Check for error conditions */
0916   errorstate = SDMMC_GetCmdResp3(SDMMCx);
0917 
0918   return errorstate;
0919 }
0920 
0921 /**
0922   * @brief  Send the Bus Width command and check the response.
0923   * @param  SDMMCx: Pointer to SDMMC register base
0924   * @param  BusWidth: BusWidth
0925   * @retval HAL status
0926   */
0927 uint32_t SDMMC_CmdBusWidth(SDMMC_TypeDef *SDMMCx, uint32_t BusWidth)
0928 {
0929   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0930   uint32_t errorstate;
0931 
0932   sdmmc_cmdinit.Argument         = (uint32_t)BusWidth;
0933   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
0934   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0935   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0936   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0937   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0938 
0939   /* Check for error conditions */
0940   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDMMC_CMDTIMEOUT);
0941 
0942   return errorstate;
0943 }
0944 
0945 /**
0946   * @brief  Send the Send SCR command and check the response.
0947   * @param  SDMMCx: Pointer to SDMMC register base
0948   * @retval HAL status
0949   */
0950 uint32_t SDMMC_CmdSendSCR(SDMMC_TypeDef *SDMMCx)
0951 {
0952   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0953   uint32_t errorstate;
0954 
0955   /* Send CMD51 SD_APP_SEND_SCR */
0956   sdmmc_cmdinit.Argument         = 0U;
0957   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_SEND_SCR;
0958   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
0959   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0960   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0961   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0962 
0963   /* Check for error conditions */
0964   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_SEND_SCR, SDMMC_CMDTIMEOUT);
0965 
0966   return errorstate;
0967 }
0968 
0969 /**
0970   * @brief  Send the Send CID command and check the response.
0971   * @param  SDMMCx: Pointer to SDMMC register base
0972   * @retval HAL status
0973   */
0974 uint32_t SDMMC_CmdSendCID(SDMMC_TypeDef *SDMMCx)
0975 {
0976   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
0977   uint32_t errorstate;
0978 
0979   /* Send CMD2 ALL_SEND_CID */
0980   sdmmc_cmdinit.Argument         = 0U;
0981   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ALL_SEND_CID;
0982   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_LONG;
0983   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
0984   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
0985   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
0986 
0987   /* Check for error conditions */
0988   errorstate = SDMMC_GetCmdResp2(SDMMCx);
0989 
0990   return errorstate;
0991 }
0992 
0993 /**
0994   * @brief  Send the Send CSD command and check the response.
0995   * @param  SDMMCx: Pointer to SDMMC register base
0996   * @param  Argument: Command Argument
0997   * @retval HAL status
0998   */
0999 uint32_t SDMMC_CmdSendCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1000 {
1001   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1002   uint32_t errorstate;
1003 
1004   /* Send CMD9 SEND_CSD */
1005   sdmmc_cmdinit.Argument         = Argument;
1006   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_CSD;
1007   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_LONG;
1008   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1009   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1010   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1011 
1012   /* Check for error conditions */
1013   errorstate = SDMMC_GetCmdResp2(SDMMCx);
1014 
1015   return errorstate;
1016 }
1017 
1018 /**
1019   * @brief  Send the Send CSD command and check the response.
1020   * @param  SDMMCx: Pointer to SDMMC register base
1021   * @param  pRCA: Card RCA
1022   * @retval HAL status
1023   */
1024 uint32_t SDMMC_CmdSetRelAdd(SDMMC_TypeDef *SDMMCx, uint16_t *pRCA)
1025 {
1026   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1027   uint32_t errorstate;
1028 
1029   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1030   sdmmc_cmdinit.Argument         = 0U;
1031   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1032   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1033   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1034   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1035   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1036 
1037   /* Check for error conditions */
1038   errorstate = SDMMC_GetCmdResp6(SDMMCx, SDMMC_CMD_SET_REL_ADDR, pRCA);
1039 
1040   return errorstate;
1041 }
1042 
1043 /**
1044   * @brief  Send the Set Relative Address command to MMC card (not SD card).
1045   * @param  SDMMCx Pointer to SDMMC register base
1046   * @param  RCA Card RCA
1047   * @retval HAL status
1048   */
1049 uint32_t SDMMC_CmdSetRelAddMmc(SDMMC_TypeDef *SDMMCx, uint16_t RCA)
1050 {
1051   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1052   uint32_t errorstate;
1053 
1054   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1055   sdmmc_cmdinit.Argument         = ((uint32_t)RCA << 16U);
1056   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1057   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1058   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1059   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1060   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1061 
1062   /* Check for error conditions */
1063   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SET_REL_ADDR, SDMMC_CMDTIMEOUT);
1064 
1065   return errorstate;
1066 }
1067 
1068 /**
1069   * @brief  Send the Sleep command to MMC card (not SD card).
1070   * @param  SDMMCx Pointer to SDMMC register base
1071   * @param  Argument Argument of the command (RCA and Sleep/Awake)
1072   * @retval HAL status
1073   */
1074 uint32_t SDMMC_CmdSleepMmc(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1075 {
1076   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1077   uint32_t errorstate;
1078 
1079   /* Send CMD5 SDMMC_CMD_MMC_SLEEP_AWAKE */
1080   sdmmc_cmdinit.Argument         = Argument;
1081   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_MMC_SLEEP_AWAKE;
1082   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1083   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1084   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1085   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1086 
1087   /* Check for error conditions */
1088   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_MMC_SLEEP_AWAKE, SDMMC_CMDTIMEOUT);
1089 
1090   return errorstate;
1091 }
1092 
1093 /**
1094   * @brief  Send the Status command and check the response.
1095   * @param  SDMMCx: Pointer to SDMMC register base
1096   * @param  Argument: Command Argument
1097   * @retval HAL status
1098   */
1099 uint32_t SDMMC_CmdSendStatus(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1100 {
1101   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1102   uint32_t errorstate;
1103 
1104   sdmmc_cmdinit.Argument         = Argument;
1105   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_STATUS;
1106   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1107   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1108   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1109   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1110 
1111   /* Check for error conditions */
1112   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEND_STATUS, SDMMC_CMDTIMEOUT);
1113 
1114   return errorstate;
1115 }
1116 
1117 /**
1118   * @brief  Send the Status register command and check the response.
1119   * @param  SDMMCx: Pointer to SDMMC register base
1120   * @retval HAL status
1121   */
1122 uint32_t SDMMC_CmdStatusRegister(SDMMC_TypeDef *SDMMCx)
1123 {
1124   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1125   uint32_t errorstate;
1126 
1127   sdmmc_cmdinit.Argument         = 0U;
1128   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_STATUS;
1129   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1130   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1131   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1132   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1133 
1134   /* Check for error conditions */
1135   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_STATUS, SDMMC_CMDTIMEOUT);
1136 
1137   return errorstate;
1138 }
1139 
1140 /**
1141   * @brief  Sends host capacity support information and activates the card's
1142   *         initialization process. Send SDMMC_CMD_SEND_OP_COND command
1143   * @param  SDMMCx: Pointer to SDMMC register base
1144   * @parame Argument: Argument used for the command
1145   * @retval HAL status
1146   */
1147 uint32_t SDMMC_CmdOpCondition(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1148 {
1149   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1150   uint32_t errorstate;
1151 
1152   sdmmc_cmdinit.Argument         = Argument;
1153   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_OP_COND;
1154   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1155   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1156   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1157   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1158 
1159   /* Check for error conditions */
1160   errorstate = SDMMC_GetCmdResp3(SDMMCx);
1161 
1162   return errorstate;
1163 }
1164 
1165 /**
1166   * @brief  Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
1167   * @param  SDMMCx: Pointer to SDMMC register base
1168   * @parame Argument: Argument used for the command
1169   * @retval HAL status
1170   */
1171 uint32_t SDMMC_CmdSwitch(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1172 {
1173   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1174   uint32_t errorstate;
1175 
1176   /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
1177   /* CMD Response: R1 */
1178   sdmmc_cmdinit.Argument         = Argument; /* SDMMC_SDR25_SWITCH_PATTERN*/
1179   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SWITCH;
1180   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1181   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1182   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1183   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1184 
1185   /* Check for error conditions */
1186   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SWITCH, SDMMC_CMDTIMEOUT);
1187 
1188   return errorstate;
1189 }
1190 
1191 /**
1192   * @brief  Send the command asking the accessed card to send its operating
1193   *         condition register (OCR)
1194   * @param  None
1195   * @retval HAL status
1196   */
1197 uint32_t SDMMC_CmdVoltageSwitch(SDMMC_TypeDef *SDMMCx)
1198 {
1199   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1200   uint32_t errorstate;
1201 
1202   sdmmc_cmdinit.Argument         = 0x00000000;
1203   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_VOLTAGE_SWITCH;
1204   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1205   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1206   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1207   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1208 
1209   /* Check for error conditions */
1210   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_VOLTAGE_SWITCH, SDMMC_CMDTIMEOUT);
1211 
1212   return errorstate;
1213 }
1214 
1215 /**
1216   * @brief  Send the Send EXT_CSD command and check the response.
1217   * @param  SDMMCx: Pointer to SDMMC register base
1218   * @param  Argument: Command Argument
1219   * @retval HAL status
1220   */
1221 uint32_t SDMMC_CmdSendEXTCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1222 {
1223   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1224   uint32_t errorstate;
1225 
1226   /* Send CMD9 SEND_CSD */
1227   sdmmc_cmdinit.Argument         = Argument;
1228   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
1229   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1230   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1231   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1232   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1233 
1234   /* Check for error conditions */
1235   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SEND_EXT_CSD, SDMMC_CMDTIMEOUT);
1236 
1237   return errorstate;
1238 }
1239 
1240 /**
1241   * @}
1242   */
1243 
1244 
1245 /** @defgroup HAL_SDMMC_LL_Group5 Responses management functions
1246   * @ingroup RTEMSBSPsARMSTM32H7
1247   *  @brief   Responses functions
1248   *
1249 @verbatim
1250  ===============================================================================
1251                    ##### Responses management functions #####
1252  ===============================================================================
1253     [..]
1254     This subsection provides a set of functions allowing to manage the needed responses.
1255 
1256 @endverbatim
1257   * @{
1258   */
1259 /**
1260   * @brief  Checks for error conditions for R1 response.
1261   * @param  hsd: SD handle
1262   * @param  SD_CMD: The sent command index
1263   * @retval SD Card error state
1264   */
1265 uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
1266 {
1267   uint32_t response_r1;
1268   uint32_t sta_reg;
1269 
1270   /* 8 is the number of required instructions cycles for the below loop statement.
1271   The Timeout is expressed in ms */
1272   uint32_t count = Timeout * (SystemCoreClock / 8U / 1000U);
1273 
1274   do
1275   {
1276     if (count-- == 0U)
1277     {
1278       return SDMMC_ERROR_TIMEOUT;
1279     }
1280     sta_reg = SDMMCx->STA;
1281   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT |
1282                         SDMMC_FLAG_BUSYD0END)) == 0U) || ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1283 
1284   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1285   {
1286     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1287 
1288     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1289   }
1290   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1291   {
1292     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1293 
1294     return SDMMC_ERROR_CMD_CRC_FAIL;
1295   }
1296   else
1297   {
1298     /* Nothing to do */
1299   }
1300 
1301   /* Clear all the static flags */
1302   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1303 
1304   /* Check response received is of desired command */
1305   if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
1306   {
1307     return SDMMC_ERROR_CMD_CRC_FAIL;
1308   }
1309 
1310   /* We have received response, retrieve it for analysis  */
1311   response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1312 
1313   if ((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
1314   {
1315     return SDMMC_ERROR_NONE;
1316   }
1317   else if ((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
1318   {
1319     return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
1320   }
1321   else if ((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
1322   {
1323     return SDMMC_ERROR_ADDR_MISALIGNED;
1324   }
1325   else if ((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
1326   {
1327     return SDMMC_ERROR_BLOCK_LEN_ERR;
1328   }
1329   else if ((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
1330   {
1331     return SDMMC_ERROR_ERASE_SEQ_ERR;
1332   }
1333   else if ((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
1334   {
1335     return SDMMC_ERROR_BAD_ERASE_PARAM;
1336   }
1337   else if ((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
1338   {
1339     return SDMMC_ERROR_WRITE_PROT_VIOLATION;
1340   }
1341   else if ((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
1342   {
1343     return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
1344   }
1345   else if ((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
1346   {
1347     return SDMMC_ERROR_COM_CRC_FAILED;
1348   }
1349   else if ((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
1350   {
1351     return SDMMC_ERROR_ILLEGAL_CMD;
1352   }
1353   else if ((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
1354   {
1355     return SDMMC_ERROR_CARD_ECC_FAILED;
1356   }
1357   else if ((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
1358   {
1359     return SDMMC_ERROR_CC_ERR;
1360   }
1361   else if ((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
1362   {
1363     return SDMMC_ERROR_STREAM_READ_UNDERRUN;
1364   }
1365   else if ((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
1366   {
1367     return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
1368   }
1369   else if ((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
1370   {
1371     return SDMMC_ERROR_CID_CSD_OVERWRITE;
1372   }
1373   else if ((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
1374   {
1375     return SDMMC_ERROR_WP_ERASE_SKIP;
1376   }
1377   else if ((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
1378   {
1379     return SDMMC_ERROR_CARD_ECC_DISABLED;
1380   }
1381   else if ((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
1382   {
1383     return SDMMC_ERROR_ERASE_RESET;
1384   }
1385   else if ((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
1386   {
1387     return SDMMC_ERROR_AKE_SEQ_ERR;
1388   }
1389   else
1390   {
1391     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1392   }
1393 }
1394 
1395 /**
1396   * @brief  Checks for error conditions for R2 (CID or CSD) response.
1397   * @param  hsd: SD handle
1398   * @retval SD Card error state
1399   */
1400 uint32_t SDMMC_GetCmdResp2(SDMMC_TypeDef *SDMMCx)
1401 {
1402   uint32_t sta_reg;
1403   /* 8 is the number of required instructions cycles for the below loop statement.
1404   The SDMMC_CMDTIMEOUT is expressed in ms */
1405   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1406 
1407   do
1408   {
1409     if (count-- == 0U)
1410     {
1411       return SDMMC_ERROR_TIMEOUT;
1412     }
1413     sta_reg = SDMMCx->STA;
1414   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1415            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1416 
1417   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1418   {
1419     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1420 
1421     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1422   }
1423   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1424   {
1425     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1426 
1427     return SDMMC_ERROR_CMD_CRC_FAIL;
1428   }
1429   else
1430   {
1431     /* No error flag set */
1432     /* Clear all the static flags */
1433     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1434   }
1435 
1436   return SDMMC_ERROR_NONE;
1437 }
1438 
1439 /**
1440   * @brief  Checks for error conditions for R3 (OCR) response.
1441   * @param  hsd: SD handle
1442   * @retval SD Card error state
1443   */
1444 uint32_t SDMMC_GetCmdResp3(SDMMC_TypeDef *SDMMCx)
1445 {
1446   uint32_t sta_reg;
1447   /* 8 is the number of required instructions cycles for the below loop statement.
1448   The SDMMC_CMDTIMEOUT is expressed in ms */
1449   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1450 
1451   do
1452   {
1453     if (count-- == 0U)
1454     {
1455       return SDMMC_ERROR_TIMEOUT;
1456     }
1457     sta_reg = SDMMCx->STA;
1458   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1459            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1460 
1461   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1462   {
1463     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1464 
1465     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1466   }
1467   else
1468   {
1469     /* Clear all the static flags */
1470     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1471   }
1472 
1473   return SDMMC_ERROR_NONE;
1474 }
1475 
1476 /**
1477   * @brief  Checks for error conditions for R6 (RCA) response.
1478   * @param  hsd: SD handle
1479   * @param  SD_CMD: The sent command index
1480   * @param  pRCA: Pointer to the variable that will contain the SD card relative
1481   *         address RCA
1482   * @retval SD Card error state
1483   */
1484 uint32_t SDMMC_GetCmdResp6(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint16_t *pRCA)
1485 {
1486   uint32_t response_r1;
1487   uint32_t sta_reg;
1488 
1489   /* 8 is the number of required instructions cycles for the below loop statement.
1490   The SDMMC_CMDTIMEOUT is expressed in ms */
1491   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1492 
1493   do
1494   {
1495     if (count-- == 0U)
1496     {
1497       return SDMMC_ERROR_TIMEOUT;
1498     }
1499     sta_reg = SDMMCx->STA;
1500   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1501            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1502 
1503   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1504   {
1505     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1506 
1507     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1508   }
1509   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1510   {
1511     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1512 
1513     return SDMMC_ERROR_CMD_CRC_FAIL;
1514   }
1515   else
1516   {
1517     /* Nothing to do */
1518   }
1519 
1520   /* Check response received is of desired command */
1521   if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
1522   {
1523     return SDMMC_ERROR_CMD_CRC_FAIL;
1524   }
1525 
1526   /* Clear all the static flags */
1527   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1528 
1529   /* We have received response, retrieve it.  */
1530   response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1531 
1532   if ((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD |
1533                       SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
1534   {
1535     *pRCA = (uint16_t)(response_r1 >> 16);
1536 
1537     return SDMMC_ERROR_NONE;
1538   }
1539   else if ((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
1540   {
1541     return SDMMC_ERROR_ILLEGAL_CMD;
1542   }
1543   else if ((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
1544   {
1545     return SDMMC_ERROR_COM_CRC_FAILED;
1546   }
1547   else
1548   {
1549     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1550   }
1551 }
1552 
1553 /**
1554   * @brief  Checks for error conditions for R7 response.
1555   * @param  hsd: SD handle
1556   * @retval SD Card error state
1557   */
1558 uint32_t SDMMC_GetCmdResp7(SDMMC_TypeDef *SDMMCx)
1559 {
1560   uint32_t sta_reg;
1561   /* 8 is the number of required instructions cycles for the below loop statement.
1562   The SDMMC_CMDTIMEOUT is expressed in ms */
1563   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1564 
1565   do
1566   {
1567     if (count-- == 0U)
1568     {
1569       return SDMMC_ERROR_TIMEOUT;
1570     }
1571     sta_reg = SDMMCx->STA;
1572   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1573            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1574 
1575   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1576   {
1577     /* Card is not SD V2.0 compliant */
1578     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1579 
1580     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1581   }
1582 
1583   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1584   {
1585     /* Card is not SD V2.0 compliant */
1586     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1587 
1588     return SDMMC_ERROR_CMD_CRC_FAIL;
1589   }
1590   else
1591   {
1592     /* Nothing to do */
1593   }
1594 
1595   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDREND))
1596   {
1597     /* Card is SD V2.0 compliant */
1598     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CMDREND);
1599   }
1600 
1601   return SDMMC_ERROR_NONE;
1602 
1603 }
1604 
1605 /**
1606   * @}
1607   */
1608 
1609 /* Private function ----------------------------------------------------------*/
1610 /** @addtogroup SD_Private_Functions
1611   * @{
1612   */
1613 
1614 /**
1615   * @brief  Checks for error conditions for CMD0.
1616   * @param  hsd: SD handle
1617   * @retval SD Card error state
1618   */
1619 static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx)
1620 {
1621   /* 8 is the number of required instructions cycles for the below loop statement.
1622   The SDMMC_CMDTIMEOUT is expressed in ms */
1623   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1624 
1625   do
1626   {
1627     if (count-- == 0U)
1628     {
1629       return SDMMC_ERROR_TIMEOUT;
1630     }
1631 
1632   } while (!__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDSENT));
1633 
1634   /* Clear all the static flags */
1635   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1636 
1637   return SDMMC_ERROR_NONE;
1638 }
1639 
1640 /**
1641   * @}
1642   */
1643 
1644 #endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
1645 /**
1646   * @}
1647   */
1648 
1649 /**
1650   * @}
1651   */