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