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