1 /**
2   ******************************************************************************
3   * @file    stm32h5xx_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) 2022 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 "stm32h5xx_hal.h"
155 
156 /** @addtogroup STM32H5xx_HAL_Driver
157   * @{
158   */
159 
160 /** @defgroup SDMMC_LL SDMMC Low Layer
161   * @brief Low layer module for SD
162   * @{
163   */
164 
165 #if defined (SDMMC1) || defined (SDMMC2)
166 #if defined (HAL_SD_MODULE_ENABLED) || defined (HAL_MMC_MODULE_ENABLED)
167 
168 /* Private typedef -----------------------------------------------------------*/
169 /* Private define ------------------------------------------------------------*/
170 /* Private macro -------------------------------------------------------------*/
171 /* Private variables ---------------------------------------------------------*/
172 /* Private function prototypes -----------------------------------------------*/
173 static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx);
174 
175 /* Exported functions --------------------------------------------------------*/
176 
177 /** @defgroup SDMMC_LL_Exported_Functions SDMMC Low Layer Exported Functions
178   * @{
179   */
180 
181 /** @defgroup HAL_SDMMC_LL_Group1 Initialization de-initialization functions
182   *  @brief    Initialization and Configuration functions
183   *
184 @verbatim
185  ===============================================================================
186               ##### Initialization/de-initialization functions #####
187  ===============================================================================
188     [..]  This section provides functions allowing to:
189 
190 @endverbatim
191   * @{
192   */
193 
194 /**
195   * @brief  Initializes the SDMMC according to the specified
196   *         parameters in the SDMMC_InitTypeDef and create the associated handle.
197   * @param  SDMMCx: Pointer to SDMMC register base
198   * @param  Init: SDMMC initialization structure
199   * @retval HAL status
200   */
SDMMC_Init(SDMMC_TypeDef * SDMMCx,SDMMC_InitTypeDef Init)201 HAL_StatusTypeDef SDMMC_Init(SDMMC_TypeDef *SDMMCx, SDMMC_InitTypeDef Init)
202 {
203   uint32_t tmpreg = 0;
204 
205   /* Check the parameters */
206   assert_param(IS_SDMMC_ALL_INSTANCE(SDMMCx));
207   assert_param(IS_SDMMC_CLOCK_EDGE(Init.ClockEdge));
208   assert_param(IS_SDMMC_CLOCK_POWER_SAVE(Init.ClockPowerSave));
209   assert_param(IS_SDMMC_BUS_WIDE(Init.BusWide));
210   assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(Init.HardwareFlowControl));
211   assert_param(IS_SDMMC_CLKDIV(Init.ClockDiv));
212 
213   /* Set SDMMC configuration parameters */
214   tmpreg |= (Init.ClockEdge           | \
215              Init.ClockPowerSave      | \
216              Init.BusWide             | \
217              Init.HardwareFlowControl | \
218              Init.ClockDiv
219             );
220 
221   /* Write to SDMMC CLKCR */
222   MODIFY_REG(SDMMCx->CLKCR, CLKCR_CLEAR_MASK, tmpreg);
223 
224   return HAL_OK;
225 }
226 
227 
228 /**
229   * @}
230   */
231 
232 /** @defgroup HAL_SDMMC_LL_Group2 IO operation functions
233   *  @brief   Data transfers functions
234   *
235 @verbatim
236  ===============================================================================
237                       ##### I/O operation functions #####
238  ===============================================================================
239     [..]
240     This subsection provides a set of functions allowing to manage the SDMMC data
241     transfers.
242 
243 @endverbatim
244   * @{
245   */
246 
247 /**
248   * @brief  Read data (word) from Rx FIFO in blocking mode (polling)
249   * @param  SDMMCx: Pointer to SDMMC register base
250   * @retval HAL status
251   */
SDMMC_ReadFIFO(SDMMC_TypeDef * SDMMCx)252 uint32_t SDMMC_ReadFIFO(SDMMC_TypeDef *SDMMCx)
253 {
254   /* Read data from Rx FIFO */
255   return (SDMMCx->FIFO);
256 }
257 
258 /**
259   * @brief  Write data (word) to Tx FIFO in blocking mode (polling)
260   * @param  SDMMCx: Pointer to SDMMC register base
261   * @param  pWriteData: pointer to data to write
262   * @retval HAL status
263   */
SDMMC_WriteFIFO(SDMMC_TypeDef * SDMMCx,uint32_t * pWriteData)264 HAL_StatusTypeDef SDMMC_WriteFIFO(SDMMC_TypeDef *SDMMCx, uint32_t *pWriteData)
265 {
266   /* Write data to FIFO */
267   SDMMCx->FIFO = *pWriteData;
268 
269   return HAL_OK;
270 }
271 
272 /**
273   * @}
274   */
275 
276 /** @defgroup HAL_SDMMC_LL_Group3 Peripheral Control functions
277   *  @brief   management functions
278   *
279 @verbatim
280  ===============================================================================
281                       ##### Peripheral Control functions #####
282  ===============================================================================
283     [..]
284     This subsection provides a set of functions allowing to control the SDMMC data
285     transfers.
286 
287 @endverbatim
288   * @{
289   */
290 
291 /**
292   * @brief  Set SDMMC Power state to ON.
293   * @param  SDMMCx: Pointer to SDMMC register base
294   * @retval HAL status
295   */
SDMMC_PowerState_ON(SDMMC_TypeDef * SDMMCx)296 HAL_StatusTypeDef SDMMC_PowerState_ON(SDMMC_TypeDef *SDMMCx)
297 {
298   /* Set power state to ON */
299   SDMMCx->POWER |= SDMMC_POWER_PWRCTRL;
300 
301   return HAL_OK;
302 }
303 
304 /**
305   * @brief  Set SDMMC Power state to Power-Cycle.
306   * @param  SDMMCx: Pointer to SDMMC register base
307   * @retval HAL status
308   */
SDMMC_PowerState_Cycle(SDMMC_TypeDef * SDMMCx)309 HAL_StatusTypeDef SDMMC_PowerState_Cycle(SDMMC_TypeDef *SDMMCx)
310 {
311   /* Set power state to Power Cycle*/
312   SDMMCx->POWER |= SDMMC_POWER_PWRCTRL_1;
313 
314   return HAL_OK;
315 }
316 
317 /**
318   * @brief  Set SDMMC Power state to OFF.
319   * @param  SDMMCx: Pointer to SDMMC register base
320   * @retval HAL status
321   */
SDMMC_PowerState_OFF(SDMMC_TypeDef * SDMMCx)322 HAL_StatusTypeDef SDMMC_PowerState_OFF(SDMMC_TypeDef *SDMMCx)
323 {
324   /* Set power state to OFF */
325   SDMMCx->POWER &= ~(SDMMC_POWER_PWRCTRL);
326 
327   return HAL_OK;
328 }
329 
330 /**
331   * @brief  Get SDMMC Power state.
332   * @param  SDMMCx: Pointer to SDMMC register base
333   * @retval Power status of the controller. The returned value can be one of the
334   *         following values:
335   *            - 0x00: Power OFF
336   *            - 0x02: Power UP
337   *            - 0x03: Power ON
338   */
SDMMC_GetPowerState(SDMMC_TypeDef * SDMMCx)339 uint32_t SDMMC_GetPowerState(SDMMC_TypeDef *SDMMCx)
340 {
341   return (SDMMCx->POWER & SDMMC_POWER_PWRCTRL);
342 }
343 
344 /**
345   * @brief  Configure the SDMMC command path according to the specified parameters in
346   *         SDMMC_CmdInitTypeDef structure and send the command
347   * @param  SDMMCx: Pointer to SDMMC register base
348   * @param  Command: pointer to a SDMMC_CmdInitTypeDef structure that contains
349   *         the configuration information for the SDMMC command
350   * @retval HAL status
351   */
SDMMC_SendCommand(SDMMC_TypeDef * SDMMCx,SDMMC_CmdInitTypeDef * Command)352 HAL_StatusTypeDef SDMMC_SendCommand(SDMMC_TypeDef *SDMMCx, SDMMC_CmdInitTypeDef *Command)
353 {
354   uint32_t tmpreg = 0;
355 
356   /* Check the parameters */
357   assert_param(IS_SDMMC_CMD_INDEX(Command->CmdIndex));
358   assert_param(IS_SDMMC_RESPONSE(Command->Response));
359   assert_param(IS_SDMMC_WAIT(Command->WaitForInterrupt));
360   assert_param(IS_SDMMC_CPSM(Command->CPSM));
361 
362   /* Set the SDMMC Argument value */
363   SDMMCx->ARG = Command->Argument;
364 
365   /* Set SDMMC command parameters */
366   tmpreg |= (uint32_t)(Command->CmdIndex         | \
367                        Command->Response         | \
368                        Command->WaitForInterrupt | \
369                        Command->CPSM);
370 
371   /* Write to SDMMC CMD register */
372   MODIFY_REG(SDMMCx->CMD, CMD_CLEAR_MASK, tmpreg);
373 
374   return HAL_OK;
375 }
376 
377 /**
378   * @brief  Return the command index of last command for which response received
379   * @param  SDMMCx: Pointer to SDMMC register base
380   * @retval Command index of the last command response received
381   */
SDMMC_GetCommandResponse(SDMMC_TypeDef * SDMMCx)382 uint8_t SDMMC_GetCommandResponse(SDMMC_TypeDef *SDMMCx)
383 {
384   return (uint8_t)(SDMMCx->RESPCMD);
385 }
386 
387 
388 /**
389   * @brief  Return the response received from the card for the last command
390   * @param  SDMMCx: Pointer to SDMMC register base
391   * @param  Response: Specifies the SDMMC response register.
392   *          This parameter can be one of the following values:
393   *            @arg SDMMC_RESP1: Response Register 1
394   *            @arg SDMMC_RESP2: Response Register 2
395   *            @arg SDMMC_RESP3: Response Register 3
396   *            @arg SDMMC_RESP4: Response Register 4
397   * @retval The Corresponding response register value
398   */
SDMMC_GetResponse(SDMMC_TypeDef * SDMMCx,uint32_t Response)399 uint32_t SDMMC_GetResponse(SDMMC_TypeDef *SDMMCx, uint32_t Response)
400 {
401   uint32_t tmp;
402 
403   /* Check the parameters */
404   assert_param(IS_SDMMC_RESP(Response));
405 
406   /* Get the response */
407   tmp = (uint32_t)(&(SDMMCx->RESP1)) + Response;
408 
409   return (*(__IO uint32_t *) tmp);
410 }
411 
412 /**
413   * @brief  Configure the SDMMC data path according to the specified
414   *         parameters in the SDMMC_DataInitTypeDef.
415   * @param  SDMMCx: Pointer to SDMMC register base
416   * @param  Data : pointer to a SDMMC_DataInitTypeDef structure
417   *         that contains the configuration information for the SDMMC data.
418   * @retval HAL status
419   */
SDMMC_ConfigData(SDMMC_TypeDef * SDMMCx,SDMMC_DataInitTypeDef * Data)420 HAL_StatusTypeDef SDMMC_ConfigData(SDMMC_TypeDef *SDMMCx, SDMMC_DataInitTypeDef *Data)
421 {
422   uint32_t tmpreg = 0;
423 
424   /* Check the parameters */
425   assert_param(IS_SDMMC_DATA_LENGTH(Data->DataLength));
426   assert_param(IS_SDMMC_BLOCK_SIZE(Data->DataBlockSize));
427   assert_param(IS_SDMMC_TRANSFER_DIR(Data->TransferDir));
428   assert_param(IS_SDMMC_TRANSFER_MODE(Data->TransferMode));
429   assert_param(IS_SDMMC_DPSM(Data->DPSM));
430 
431   /* Set the SDMMC Data TimeOut value */
432   SDMMCx->DTIMER = Data->DataTimeOut;
433 
434   /* Set the SDMMC DataLength value */
435   SDMMCx->DLEN = Data->DataLength;
436 
437   /* Set the SDMMC data configuration parameters */
438   tmpreg |= (uint32_t)(Data->DataBlockSize | \
439                        Data->TransferDir   | \
440                        Data->TransferMode  | \
441                        Data->DPSM);
442 
443   /* Write to SDMMC DCTRL */
444   MODIFY_REG(SDMMCx->DCTRL, DCTRL_CLEAR_MASK, tmpreg);
445 
446   return HAL_OK;
447 
448 }
449 
450 /**
451   * @brief  Returns number of remaining data bytes to be transferred.
452   * @param  SDMMCx: Pointer to SDMMC register base
453   * @retval Number of remaining data bytes to be transferred
454   */
SDMMC_GetDataCounter(SDMMC_TypeDef * SDMMCx)455 uint32_t SDMMC_GetDataCounter(SDMMC_TypeDef *SDMMCx)
456 {
457   return (SDMMCx->DCOUNT);
458 }
459 
460 /**
461   * @brief  Get the FIFO data
462   * @param  SDMMCx: Pointer to SDMMC register base
463   * @retval Data received
464   */
SDMMC_GetFIFOCount(SDMMC_TypeDef * SDMMCx)465 uint32_t SDMMC_GetFIFOCount(SDMMC_TypeDef *SDMMCx)
466 {
467   return (SDMMCx->FIFO);
468 }
469 
470 /**
471   * @brief  Sets one of the two options of inserting read wait interval.
472   * @param  SDMMCx: Pointer to SDMMC register base
473   * @param  SDMMC_ReadWaitMode: SDMMC Read Wait operation mode.
474   *          This parameter can be:
475   *            @arg SDMMC_READ_WAIT_MODE_CLK: Read Wait control by stopping SDMMCCLK
476   *            @arg SDMMC_READ_WAIT_MODE_DATA2: Read Wait control using SDMMC_DATA2
477   * @retval None
478   */
SDMMC_SetSDMMCReadWaitMode(SDMMC_TypeDef * SDMMCx,uint32_t SDMMC_ReadWaitMode)479 HAL_StatusTypeDef SDMMC_SetSDMMCReadWaitMode(SDMMC_TypeDef *SDMMCx, uint32_t SDMMC_ReadWaitMode)
480 {
481   /* Check the parameters */
482   assert_param(IS_SDMMC_READWAIT_MODE(SDMMC_ReadWaitMode));
483 
484   /* Set SDMMC read wait mode */
485   MODIFY_REG(SDMMCx->DCTRL, SDMMC_DCTRL_RWMOD, SDMMC_ReadWaitMode);
486 
487   return HAL_OK;
488 }
489 
490 /**
491   * @}
492   */
493 
494 
495 /** @defgroup HAL_SDMMC_LL_Group4 Command management functions
496   *  @brief   Data transfers functions
497   *
498 @verbatim
499  ===============================================================================
500                    ##### Commands management functions #####
501  ===============================================================================
502     [..]
503     This subsection provides a set of functions allowing to manage the needed commands.
504 
505 @endverbatim
506   * @{
507   */
508 
509 /**
510   * @brief  Send the Data Block Length command and check the response
511   * @param  SDMMCx: Pointer to SDMMC register base
512   * @retval HAL status
513   */
SDMMC_CmdBlockLength(SDMMC_TypeDef * SDMMCx,uint32_t BlockSize)514 uint32_t SDMMC_CmdBlockLength(SDMMC_TypeDef *SDMMCx, uint32_t BlockSize)
515 {
516   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
517   uint32_t errorstate;
518 
519   /* Set Block Size for Card */
520   sdmmc_cmdinit.Argument         = (uint32_t)BlockSize;
521   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_BLOCKLEN;
522   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
523   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
524   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
525   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
526 
527   /* Check for error conditions */
528   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SET_BLOCKLEN, SDMMC_CMDTIMEOUT);
529 
530   return errorstate;
531 }
532 
533 /**
534   * @brief  Send the Read Single Block command and check the response
535   * @param  SDMMCx: Pointer to SDMMC register base
536   * @retval HAL status
537   */
SDMMC_CmdReadSingleBlock(SDMMC_TypeDef * SDMMCx,uint32_t ReadAdd)538 uint32_t SDMMC_CmdReadSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
539 {
540   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
541   uint32_t errorstate;
542 
543   /* Set Block Size for Card */
544   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
545   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_SINGLE_BLOCK;
546   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
547   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
548   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
549   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
550 
551   /* Check for error conditions */
552   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
553 
554   return errorstate;
555 }
556 
557 /**
558   * @brief  Send the Read Multi Block command and check the response
559   * @param  SDMMCx: Pointer to SDMMC register base
560   * @retval HAL status
561   */
SDMMC_CmdReadMultiBlock(SDMMC_TypeDef * SDMMCx,uint32_t ReadAdd)562 uint32_t SDMMC_CmdReadMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
563 {
564   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
565   uint32_t errorstate;
566 
567   /* Set Block Size for Card */
568   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
569   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_MULT_BLOCK;
570   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
571   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
572   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
573   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
574 
575   /* Check for error conditions */
576   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_READ_MULT_BLOCK, SDMMC_CMDTIMEOUT);
577 
578   return errorstate;
579 }
580 
581 /**
582   * @brief  Send the Write Single Block command and check the response
583   * @param  SDMMCx: Pointer to SDMMC register base
584   * @retval HAL status
585   */
SDMMC_CmdWriteSingleBlock(SDMMC_TypeDef * SDMMCx,uint32_t WriteAdd)586 uint32_t SDMMC_CmdWriteSingleBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
587 {
588   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
589   uint32_t errorstate;
590 
591   /* Set Block Size for Card */
592   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
593   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_SINGLE_BLOCK;
594   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
595   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
596   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
597   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
598 
599   /* Check for error conditions */
600   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_WRITE_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
601 
602   return errorstate;
603 }
604 
605 /**
606   * @brief  Send the Write Multi Block command and check the response
607   * @param  SDMMCx: Pointer to SDMMC register base
608   * @retval HAL status
609   */
SDMMC_CmdWriteMultiBlock(SDMMC_TypeDef * SDMMCx,uint32_t WriteAdd)610 uint32_t SDMMC_CmdWriteMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
611 {
612   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
613   uint32_t errorstate;
614 
615   /* Set Block Size for Card */
616   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
617   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_MULT_BLOCK;
618   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
619   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
620   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
621   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
622 
623   /* Check for error conditions */
624   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_WRITE_MULT_BLOCK, SDMMC_CMDTIMEOUT);
625 
626   return errorstate;
627 }
628 
629 /**
630   * @brief  Send the Start Address Erase command for SD and check the response
631   * @param  SDMMCx: Pointer to SDMMC register base
632   * @retval HAL status
633   */
SDMMC_CmdSDEraseStartAdd(SDMMC_TypeDef * SDMMCx,uint32_t StartAdd)634 uint32_t SDMMC_CmdSDEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
635 {
636   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
637   uint32_t errorstate;
638 
639   /* Set Block Size for Card */
640   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
641   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_START;
642   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
643   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
644   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
645   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
646 
647   /* Check for error conditions */
648   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_ERASE_GRP_START, SDMMC_CMDTIMEOUT);
649 
650   return errorstate;
651 }
652 
653 /**
654   * @brief  Send the End Address Erase command for SD and check the response
655   * @param  SDMMCx: Pointer to SDMMC register base
656   * @retval HAL status
657   */
SDMMC_CmdSDEraseEndAdd(SDMMC_TypeDef * SDMMCx,uint32_t EndAdd)658 uint32_t SDMMC_CmdSDEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
659 {
660   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
661   uint32_t errorstate;
662 
663   /* Set Block Size for Card */
664   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
665   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_END;
666   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
667   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
668   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
669   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
670 
671   /* Check for error conditions */
672   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
673 
674   return errorstate;
675 }
676 
677 /**
678   * @brief  Send the Start Address Erase command and check the response
679   * @param  SDMMCx: Pointer to SDMMC register base
680   * @retval HAL status
681   */
SDMMC_CmdEraseStartAdd(SDMMC_TypeDef * SDMMCx,uint32_t StartAdd)682 uint32_t SDMMC_CmdEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
683 {
684   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
685   uint32_t errorstate;
686 
687   /* Set Block Size for Card */
688   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
689   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_START;
690   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
691   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
692   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
693   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
694 
695   /* Check for error conditions */
696   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_START, SDMMC_CMDTIMEOUT);
697 
698   return errorstate;
699 }
700 
701 /**
702   * @brief  Send the End Address Erase command and check the response
703   * @param  SDMMCx: Pointer to SDMMC register base
704   * @retval HAL status
705   */
SDMMC_CmdEraseEndAdd(SDMMC_TypeDef * SDMMCx,uint32_t EndAdd)706 uint32_t SDMMC_CmdEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
707 {
708   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
709   uint32_t errorstate;
710 
711   /* Set Block Size for Card */
712   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
713   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_END;
714   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
715   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
716   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
717   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
718 
719   /* Check for error conditions */
720   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
721 
722   return errorstate;
723 }
724 
725 /**
726   * @brief  Send the Erase command and check the response
727   * @param  SDMMCx Pointer to SDMMC register base
728   * @param  EraseType Type of erase to be performed
729   * @retval HAL status
730   */
SDMMC_CmdErase(SDMMC_TypeDef * SDMMCx,uint32_t EraseType)731 uint32_t SDMMC_CmdErase(SDMMC_TypeDef *SDMMCx, uint32_t EraseType)
732 {
733   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
734   uint32_t errorstate;
735 
736   /* Set Block Size for Card */
737   sdmmc_cmdinit.Argument         = EraseType;
738   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE;
739   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
740   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
741   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
742   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
743 
744   /* Check for error conditions */
745   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE, SDMMC_MAXERASETIMEOUT);
746 
747   return errorstate;
748 }
749 
750 /**
751   * @brief  Send the Stop Transfer command and check the response.
752   * @param  SDMMCx: Pointer to SDMMC register base
753   * @retval HAL status
754   */
SDMMC_CmdStopTransfer(SDMMC_TypeDef * SDMMCx)755 uint32_t SDMMC_CmdStopTransfer(SDMMC_TypeDef *SDMMCx)
756 {
757   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
758   uint32_t errorstate;
759 
760   /* Send CMD12 STOP_TRANSMISSION  */
761   sdmmc_cmdinit.Argument         = 0U;
762   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_STOP_TRANSMISSION;
763   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
764   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
765   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
766 
767   __SDMMC_CMDSTOP_ENABLE(SDMMCx);
768   __SDMMC_CMDTRANS_DISABLE(SDMMCx);
769 
770   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
771 
772   /* Check for error conditions */
773   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_STOP_TRANSMISSION, SDMMC_STOPTRANSFERTIMEOUT);
774 
775   __SDMMC_CMDSTOP_DISABLE(SDMMCx);
776 
777   /* Ignore Address Out Of Range Error, Not relevant at end of memory */
778   if (errorstate == SDMMC_ERROR_ADDR_OUT_OF_RANGE)
779   {
780     errorstate = SDMMC_ERROR_NONE;
781   }
782 
783   return errorstate;
784 }
785 
786 /**
787   * @brief  Send the Select Deselect command and check the response.
788   * @param  SDMMCx: Pointer to SDMMC register base
789   * @param  addr: Address of the card to be selected
790   * @retval HAL status
791   */
SDMMC_CmdSelDesel(SDMMC_TypeDef * SDMMCx,uint32_t Addr)792 uint32_t SDMMC_CmdSelDesel(SDMMC_TypeDef *SDMMCx, uint32_t Addr)
793 {
794   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
795   uint32_t errorstate;
796 
797   /* Send CMD7 SDMMC_SEL_DESEL_CARD */
798   sdmmc_cmdinit.Argument         = (uint32_t)Addr;
799   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEL_DESEL_CARD;
800   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
801   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
802   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
803   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
804 
805   /* Check for error conditions */
806   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEL_DESEL_CARD, SDMMC_CMDTIMEOUT);
807 
808   return errorstate;
809 }
810 
811 /**
812   * @brief  Send the Go Idle State command and check the response.
813   * @param  SDMMCx: Pointer to SDMMC register base
814   * @retval HAL status
815   */
SDMMC_CmdGoIdleState(SDMMC_TypeDef * SDMMCx)816 uint32_t SDMMC_CmdGoIdleState(SDMMC_TypeDef *SDMMCx)
817 {
818   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
819   uint32_t errorstate;
820 
821   sdmmc_cmdinit.Argument         = 0U;
822   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_GO_IDLE_STATE;
823   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_NO;
824   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
825   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
826   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
827 
828   /* Check for error conditions */
829   errorstate = SDMMC_GetCmdError(SDMMCx);
830 
831   return errorstate;
832 }
833 
834 /**
835   * @brief  Send the Operating Condition command and check the response.
836   * @param  SDMMCx: Pointer to SDMMC register base
837   * @retval HAL status
838   */
SDMMC_CmdOperCond(SDMMC_TypeDef * SDMMCx)839 uint32_t SDMMC_CmdOperCond(SDMMC_TypeDef *SDMMCx)
840 {
841   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
842   uint32_t errorstate;
843 
844   /* Send CMD8 to verify SD card interface operating condition */
845   /* Argument: - [31:12]: Reserved (shall be set to '0')
846   - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
847   - [7:0]: Check Pattern (recommended 0xAA) */
848   /* CMD Response: R7 */
849   sdmmc_cmdinit.Argument         = SDMMC_CHECK_PATTERN;
850   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
851   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
852   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
853   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
854   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
855 
856   /* Check for error conditions */
857   errorstate = SDMMC_GetCmdResp7(SDMMCx);
858 
859   return errorstate;
860 }
861 
862 /**
863   * @brief  Send the Application command to verify that that the next command
864   *         is an application specific com-mand rather than a standard command
865   *         and check the response.
866   * @param  SDMMCx: Pointer to SDMMC register base
867   * @param  Argument: Command Argument
868   * @retval HAL status
869   */
SDMMC_CmdAppCommand(SDMMC_TypeDef * SDMMCx,uint32_t Argument)870 uint32_t SDMMC_CmdAppCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
871 {
872   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
873   uint32_t errorstate;
874 
875   sdmmc_cmdinit.Argument         = (uint32_t)Argument;
876   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_CMD;
877   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
878   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
879   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
880   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
881 
882   /* Check for error conditions */
883   /* If there is a HAL_ERROR, it is a MMC card, else
884   it is a SD card: SD card 2.0 (voltage range mismatch)
885      or SD card 1.x */
886   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_CMD, SDMMC_CMDTIMEOUT);
887 
888   return errorstate;
889 }
890 
891 /**
892   * @brief  Send the command asking the accessed card to send its operating
893   *         condition register (OCR)
894   * @param  SDMMCx: Pointer to SDMMC register base
895   * @param  Argument: Command Argument
896   * @retval HAL status
897   */
SDMMC_CmdAppOperCommand(SDMMC_TypeDef * SDMMCx,uint32_t Argument)898 uint32_t SDMMC_CmdAppOperCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
899 {
900   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
901   uint32_t errorstate;
902 
903   sdmmc_cmdinit.Argument         = Argument;
904   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_OP_COND;
905   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
906   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
907   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
908   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
909 
910   /* Check for error conditions */
911   errorstate = SDMMC_GetCmdResp3(SDMMCx);
912 
913   return errorstate;
914 }
915 
916 /**
917   * @brief  Send the Bus Width command and check the response.
918   * @param  SDMMCx: Pointer to SDMMC register base
919   * @param  BusWidth: BusWidth
920   * @retval HAL status
921   */
SDMMC_CmdBusWidth(SDMMC_TypeDef * SDMMCx,uint32_t BusWidth)922 uint32_t SDMMC_CmdBusWidth(SDMMC_TypeDef *SDMMCx, uint32_t BusWidth)
923 {
924   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
925   uint32_t errorstate;
926 
927   sdmmc_cmdinit.Argument         = (uint32_t)BusWidth;
928   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
929   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
930   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
931   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
932   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
933 
934   /* Check for error conditions */
935   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_SD_SET_BUSWIDTH, SDMMC_CMDTIMEOUT);
936 
937   return errorstate;
938 }
939 
940 /**
941   * @brief  Send the Send SCR command and check the response.
942   * @param  SDMMCx: Pointer to SDMMC register base
943   * @retval HAL status
944   */
SDMMC_CmdSendSCR(SDMMC_TypeDef * SDMMCx)945 uint32_t SDMMC_CmdSendSCR(SDMMC_TypeDef *SDMMCx)
946 {
947   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
948   uint32_t errorstate;
949 
950   /* Send CMD51 SD_APP_SEND_SCR */
951   sdmmc_cmdinit.Argument         = 0U;
952   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_SEND_SCR;
953   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
954   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
955   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
956   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
957 
958   /* Check for error conditions */
959   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_SEND_SCR, SDMMC_CMDTIMEOUT);
960 
961   return errorstate;
962 }
963 
964 /**
965   * @brief  Send the Send CID command and check the response.
966   * @param  SDMMCx: Pointer to SDMMC register base
967   * @retval HAL status
968   */
SDMMC_CmdSendCID(SDMMC_TypeDef * SDMMCx)969 uint32_t SDMMC_CmdSendCID(SDMMC_TypeDef *SDMMCx)
970 {
971   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
972   uint32_t errorstate;
973 
974   /* Send CMD2 ALL_SEND_CID */
975   sdmmc_cmdinit.Argument         = 0U;
976   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ALL_SEND_CID;
977   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_LONG;
978   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
979   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
980   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
981 
982   /* Check for error conditions */
983   errorstate = SDMMC_GetCmdResp2(SDMMCx);
984 
985   return errorstate;
986 }
987 
988 /**
989   * @brief  Send the Send CSD command and check the response.
990   * @param  SDMMCx: Pointer to SDMMC register base
991   * @param  Argument: Command Argument
992   * @retval HAL status
993   */
SDMMC_CmdSendCSD(SDMMC_TypeDef * SDMMCx,uint32_t Argument)994 uint32_t SDMMC_CmdSendCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
995 {
996   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
997   uint32_t errorstate;
998 
999   /* Send CMD9 SEND_CSD */
1000   sdmmc_cmdinit.Argument         = Argument;
1001   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_CSD;
1002   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_LONG;
1003   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1004   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1005   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1006 
1007   /* Check for error conditions */
1008   errorstate = SDMMC_GetCmdResp2(SDMMCx);
1009 
1010   return errorstate;
1011 }
1012 
1013 /**
1014   * @brief  Send the Send CSD command and check the response.
1015   * @param  SDMMCx: Pointer to SDMMC register base
1016   * @param  pRCA: Card RCA
1017   * @retval HAL status
1018   */
SDMMC_CmdSetRelAdd(SDMMC_TypeDef * SDMMCx,uint16_t * pRCA)1019 uint32_t SDMMC_CmdSetRelAdd(SDMMC_TypeDef *SDMMCx, uint16_t *pRCA)
1020 {
1021   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1022   uint32_t errorstate;
1023 
1024   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1025   sdmmc_cmdinit.Argument         = 0U;
1026   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1027   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1028   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1029   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1030   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1031 
1032   /* Check for error conditions */
1033   errorstate = SDMMC_GetCmdResp6(SDMMCx, SDMMC_CMD_SET_REL_ADDR, pRCA);
1034 
1035   return errorstate;
1036 }
1037 
1038 /**
1039   * @brief  Send the Set Relative Address command to MMC card (not SD card).
1040   * @param  SDMMCx Pointer to SDMMC register base
1041   * @param  RCA Card RCA
1042   * @retval HAL status
1043   */
SDMMC_CmdSetRelAddMmc(SDMMC_TypeDef * SDMMCx,uint16_t RCA)1044 uint32_t SDMMC_CmdSetRelAddMmc(SDMMC_TypeDef *SDMMCx, uint16_t RCA)
1045 {
1046   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1047   uint32_t errorstate;
1048 
1049   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1050   sdmmc_cmdinit.Argument         = ((uint32_t)RCA << 16U);
1051   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1052   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1053   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1054   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1055   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1056 
1057   /* Check for error conditions */
1058   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SET_REL_ADDR, SDMMC_CMDTIMEOUT);
1059 
1060   return errorstate;
1061 }
1062 
1063 /**
1064   * @brief  Send the Sleep command to MMC card (not SD card).
1065   * @param  SDMMCx Pointer to SDMMC register base
1066   * @param  Argument Argument of the command (RCA and Sleep/Awake)
1067   * @retval HAL status
1068   */
SDMMC_CmdSleepMmc(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1069 uint32_t SDMMC_CmdSleepMmc(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1070 {
1071   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1072   uint32_t errorstate;
1073 
1074   /* Send CMD5 SDMMC_CMD_MMC_SLEEP_AWAKE */
1075   sdmmc_cmdinit.Argument         = Argument;
1076   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_MMC_SLEEP_AWAKE;
1077   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1078   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1079   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1080   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1081 
1082   /* Check for error conditions */
1083   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_MMC_SLEEP_AWAKE, SDMMC_CMDTIMEOUT);
1084 
1085   return errorstate;
1086 }
1087 
1088 /**
1089   * @brief  Send the Status command and check the response.
1090   * @param  SDMMCx: Pointer to SDMMC register base
1091   * @param  Argument: Command Argument
1092   * @retval HAL status
1093   */
SDMMC_CmdSendStatus(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1094 uint32_t SDMMC_CmdSendStatus(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1095 {
1096   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1097   uint32_t errorstate;
1098 
1099   sdmmc_cmdinit.Argument         = Argument;
1100   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_STATUS;
1101   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1102   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1103   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1104   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1105 
1106   /* Check for error conditions */
1107   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEND_STATUS, SDMMC_CMDTIMEOUT);
1108 
1109   return errorstate;
1110 }
1111 
1112 /**
1113   * @brief  Send the Status register command and check the response.
1114   * @param  SDMMCx: Pointer to SDMMC register base
1115   * @retval HAL status
1116   */
SDMMC_CmdStatusRegister(SDMMC_TypeDef * SDMMCx)1117 uint32_t SDMMC_CmdStatusRegister(SDMMC_TypeDef *SDMMCx)
1118 {
1119   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1120   uint32_t errorstate;
1121 
1122   sdmmc_cmdinit.Argument         = 0U;
1123   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_STATUS;
1124   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1125   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1126   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1127   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1128 
1129   /* Check for error conditions */
1130   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_STATUS, SDMMC_CMDTIMEOUT);
1131 
1132   return errorstate;
1133 }
1134 
1135 /**
1136   * @brief  Sends host capacity support information and activates the card's
1137   *         initialization process. Send SDMMC_CMD_SEND_OP_COND command
1138   * @param  SDMMCx: Pointer to SDMMC register base
1139   * @parame Argument: Argument used for the command
1140   * @retval HAL status
1141   */
SDMMC_CmdOpCondition(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1142 uint32_t SDMMC_CmdOpCondition(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1143 {
1144   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1145   uint32_t errorstate;
1146 
1147   sdmmc_cmdinit.Argument         = Argument;
1148   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_OP_COND;
1149   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1150   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1151   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1152   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1153 
1154   /* Check for error conditions */
1155   errorstate = SDMMC_GetCmdResp3(SDMMCx);
1156 
1157   return errorstate;
1158 }
1159 
1160 /**
1161   * @brief  Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
1162   * @param  SDMMCx: Pointer to SDMMC register base
1163   * @parame Argument: Argument used for the command
1164   * @retval HAL status
1165   */
SDMMC_CmdSwitch(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1166 uint32_t SDMMC_CmdSwitch(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1167 {
1168   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1169   uint32_t errorstate;
1170 
1171   /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
1172   /* CMD Response: R1 */
1173   sdmmc_cmdinit.Argument         = Argument; /* SDMMC_SDR25_SWITCH_PATTERN*/
1174   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SWITCH;
1175   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1176   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1177   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1178   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1179 
1180   /* Check for error conditions */
1181   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SWITCH, SDMMC_CMDTIMEOUT);
1182 
1183   return errorstate;
1184 }
1185 
1186 /**
1187   * @brief  Send the command asking the accessed card to send its operating
1188   *         condition register (OCR)
1189   * @param  None
1190   * @retval HAL status
1191   */
SDMMC_CmdVoltageSwitch(SDMMC_TypeDef * SDMMCx)1192 uint32_t SDMMC_CmdVoltageSwitch(SDMMC_TypeDef *SDMMCx)
1193 {
1194   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1195   uint32_t errorstate;
1196 
1197   sdmmc_cmdinit.Argument         = 0x00000000;
1198   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_VOLTAGE_SWITCH;
1199   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1200   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1201   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1202   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1203 
1204   /* Check for error conditions */
1205   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_VOLTAGE_SWITCH, SDMMC_CMDTIMEOUT);
1206 
1207   return errorstate;
1208 }
1209 
1210 /**
1211   * @brief  Send the Send EXT_CSD command and check the response.
1212   * @param  SDMMCx: Pointer to SDMMC register base
1213   * @param  Argument: Command Argument
1214   * @retval HAL status
1215   */
SDMMC_CmdSendEXTCSD(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1216 uint32_t SDMMC_CmdSendEXTCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1217 {
1218   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1219   uint32_t errorstate;
1220 
1221   /* Send CMD9 SEND_CSD */
1222   sdmmc_cmdinit.Argument         = Argument;
1223   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
1224   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1225   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1226   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1227   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1228 
1229   /* Check for error conditions */
1230   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SEND_EXT_CSD, SDMMC_CMDTIMEOUT);
1231 
1232   return errorstate;
1233 }
1234 
1235 /**
1236   * @}
1237   */
1238 
1239 
1240 /** @defgroup HAL_SDMMC_LL_Group5 Responses management functions
1241   *  @brief   Responses functions
1242   *
1243 @verbatim
1244  ===============================================================================
1245                    ##### Responses management functions #####
1246  ===============================================================================
1247     [..]
1248     This subsection provides a set of functions allowing to manage the needed responses.
1249 
1250 @endverbatim
1251   * @{
1252   */
1253 /**
1254   * @brief  Checks for error conditions for R1 response.
1255   * @param  hsd: SD handle
1256   * @param  SD_CMD: The sent command index
1257   * @retval SD Card error state
1258   */
SDMMC_GetCmdResp1(SDMMC_TypeDef * SDMMCx,uint8_t SD_CMD,uint32_t Timeout)1259 uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
1260 {
1261   uint32_t response_r1;
1262   uint32_t sta_reg;
1263 
1264   /* 8 is the number of required instructions cycles for the below loop statement.
1265   The Timeout is expressed in ms */
1266   uint32_t count = Timeout * (SystemCoreClock / 8U / 1000U);
1267 
1268   do
1269   {
1270     if (count-- == 0U)
1271     {
1272       return SDMMC_ERROR_TIMEOUT;
1273     }
1274     sta_reg = SDMMCx->STA;
1275   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT |
1276                         SDMMC_FLAG_BUSYD0END)) == 0U) || ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1277 
1278   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1279   {
1280     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1281 
1282     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1283   }
1284   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1285   {
1286     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1287 
1288     return SDMMC_ERROR_CMD_CRC_FAIL;
1289   }
1290   else
1291   {
1292     /* Nothing to do */
1293   }
1294 
1295   /* Clear all the static flags */
1296   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1297 
1298   /* Check response received is of desired command */
1299   if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
1300   {
1301     return SDMMC_ERROR_CMD_CRC_FAIL;
1302   }
1303 
1304   /* We have received response, retrieve it for analysis  */
1305   response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1306 
1307   if ((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
1308   {
1309     return SDMMC_ERROR_NONE;
1310   }
1311   else if ((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
1312   {
1313     return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
1314   }
1315   else if ((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
1316   {
1317     return SDMMC_ERROR_ADDR_MISALIGNED;
1318   }
1319   else if ((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
1320   {
1321     return SDMMC_ERROR_BLOCK_LEN_ERR;
1322   }
1323   else if ((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
1324   {
1325     return SDMMC_ERROR_ERASE_SEQ_ERR;
1326   }
1327   else if ((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
1328   {
1329     return SDMMC_ERROR_BAD_ERASE_PARAM;
1330   }
1331   else if ((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
1332   {
1333     return SDMMC_ERROR_WRITE_PROT_VIOLATION;
1334   }
1335   else if ((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
1336   {
1337     return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
1338   }
1339   else if ((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
1340   {
1341     return SDMMC_ERROR_COM_CRC_FAILED;
1342   }
1343   else if ((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
1344   {
1345     return SDMMC_ERROR_ILLEGAL_CMD;
1346   }
1347   else if ((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
1348   {
1349     return SDMMC_ERROR_CARD_ECC_FAILED;
1350   }
1351   else if ((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
1352   {
1353     return SDMMC_ERROR_CC_ERR;
1354   }
1355   else if ((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
1356   {
1357     return SDMMC_ERROR_STREAM_READ_UNDERRUN;
1358   }
1359   else if ((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
1360   {
1361     return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
1362   }
1363   else if ((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
1364   {
1365     return SDMMC_ERROR_CID_CSD_OVERWRITE;
1366   }
1367   else if ((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
1368   {
1369     return SDMMC_ERROR_WP_ERASE_SKIP;
1370   }
1371   else if ((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
1372   {
1373     return SDMMC_ERROR_CARD_ECC_DISABLED;
1374   }
1375   else if ((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
1376   {
1377     return SDMMC_ERROR_ERASE_RESET;
1378   }
1379   else if ((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
1380   {
1381     return SDMMC_ERROR_AKE_SEQ_ERR;
1382   }
1383   else
1384   {
1385     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1386   }
1387 }
1388 
1389 /**
1390   * @brief  Checks for error conditions for R2 (CID or CSD) response.
1391   * @param  hsd: SD handle
1392   * @retval SD Card error state
1393   */
SDMMC_GetCmdResp2(SDMMC_TypeDef * SDMMCx)1394 uint32_t SDMMC_GetCmdResp2(SDMMC_TypeDef *SDMMCx)
1395 {
1396   uint32_t sta_reg;
1397   /* 8 is the number of required instructions cycles for the below loop statement.
1398   The SDMMC_CMDTIMEOUT is expressed in ms */
1399   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1400 
1401   do
1402   {
1403     if (count-- == 0U)
1404     {
1405       return SDMMC_ERROR_TIMEOUT;
1406     }
1407     sta_reg = SDMMCx->STA;
1408   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1409            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1410 
1411   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1412   {
1413     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1414 
1415     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1416   }
1417   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1418   {
1419     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1420 
1421     return SDMMC_ERROR_CMD_CRC_FAIL;
1422   }
1423   else
1424   {
1425     /* No error flag set */
1426     /* Clear all the static flags */
1427     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1428   }
1429 
1430   return SDMMC_ERROR_NONE;
1431 }
1432 
1433 /**
1434   * @brief  Checks for error conditions for R3 (OCR) response.
1435   * @param  hsd: SD handle
1436   * @retval SD Card error state
1437   */
SDMMC_GetCmdResp3(SDMMC_TypeDef * SDMMCx)1438 uint32_t SDMMC_GetCmdResp3(SDMMC_TypeDef *SDMMCx)
1439 {
1440   uint32_t sta_reg;
1441   /* 8 is the number of required instructions cycles for the below loop statement.
1442   The SDMMC_CMDTIMEOUT is expressed in ms */
1443   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1444 
1445   do
1446   {
1447     if (count-- == 0U)
1448     {
1449       return SDMMC_ERROR_TIMEOUT;
1450     }
1451     sta_reg = SDMMCx->STA;
1452   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1453            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1454 
1455   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1456   {
1457     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1458 
1459     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1460   }
1461   else
1462   {
1463     /* Clear all the static flags */
1464     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1465   }
1466 
1467   return SDMMC_ERROR_NONE;
1468 }
1469 
1470 /**
1471   * @brief  Checks for error conditions for R6 (RCA) response.
1472   * @param  hsd: SD handle
1473   * @param  SD_CMD: The sent command index
1474   * @param  pRCA: Pointer to the variable that will contain the SD card relative
1475   *         address RCA
1476   * @retval SD Card error state
1477   */
SDMMC_GetCmdResp6(SDMMC_TypeDef * SDMMCx,uint8_t SD_CMD,uint16_t * pRCA)1478 uint32_t SDMMC_GetCmdResp6(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint16_t *pRCA)
1479 {
1480   uint32_t response_r1;
1481   uint32_t sta_reg;
1482 
1483   /* 8 is the number of required instructions cycles for the below loop statement.
1484   The SDMMC_CMDTIMEOUT is expressed in ms */
1485   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1486 
1487   do
1488   {
1489     if (count-- == 0U)
1490     {
1491       return SDMMC_ERROR_TIMEOUT;
1492     }
1493     sta_reg = SDMMCx->STA;
1494   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1495            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1496 
1497   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1498   {
1499     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1500 
1501     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1502   }
1503   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1504   {
1505     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1506 
1507     return SDMMC_ERROR_CMD_CRC_FAIL;
1508   }
1509   else
1510   {
1511     /* Nothing to do */
1512   }
1513 
1514   /* Check response received is of desired command */
1515   if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
1516   {
1517     return SDMMC_ERROR_CMD_CRC_FAIL;
1518   }
1519 
1520   /* Clear all the static flags */
1521   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1522 
1523   /* We have received response, retrieve it.  */
1524   response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1525 
1526   if ((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD |
1527                       SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
1528   {
1529     *pRCA = (uint16_t)(response_r1 >> 16);
1530 
1531     return SDMMC_ERROR_NONE;
1532   }
1533   else if ((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
1534   {
1535     return SDMMC_ERROR_ILLEGAL_CMD;
1536   }
1537   else if ((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
1538   {
1539     return SDMMC_ERROR_COM_CRC_FAILED;
1540   }
1541   else
1542   {
1543     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1544   }
1545 }
1546 
1547 /**
1548   * @brief  Checks for error conditions for R7 response.
1549   * @param  hsd: SD handle
1550   * @retval SD Card error state
1551   */
SDMMC_GetCmdResp7(SDMMC_TypeDef * SDMMCx)1552 uint32_t SDMMC_GetCmdResp7(SDMMC_TypeDef *SDMMCx)
1553 {
1554   uint32_t sta_reg;
1555   /* 8 is the number of required instructions cycles for the below loop statement.
1556   The SDMMC_CMDTIMEOUT is expressed in ms */
1557   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1558 
1559   do
1560   {
1561     if (count-- == 0U)
1562     {
1563       return SDMMC_ERROR_TIMEOUT;
1564     }
1565     sta_reg = SDMMCx->STA;
1566   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1567            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1568 
1569   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1570   {
1571     /* Card is not SD V2.0 compliant */
1572     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1573 
1574     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1575   }
1576 
1577   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1578   {
1579     /* Card is not SD V2.0 compliant */
1580     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1581 
1582     return SDMMC_ERROR_CMD_CRC_FAIL;
1583   }
1584   else
1585   {
1586     /* Nothing to do */
1587   }
1588 
1589   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDREND))
1590   {
1591     /* Card is SD V2.0 compliant */
1592     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CMDREND);
1593   }
1594 
1595   return SDMMC_ERROR_NONE;
1596 
1597 }
1598 
1599 /**
1600   * @}
1601   */
1602 
1603 
1604 /** @defgroup HAL_SDMMC_LL_Group6 Linked List functions
1605   *  @brief   Linked List management functions
1606   *
1607 @verbatim
1608  ===============================================================================
1609                    ##### Linked List management functions #####
1610  ===============================================================================
1611     [..]
1612     This subsection provides a set of functions allowing to manage the needed functions.
1613 
1614 @endverbatim
1615   * @{
1616   */
1617 
1618 /**
1619   * @brief  Build new Linked List node.
1620   * @param  pNode: Pointer to new node to add.
1621   * @param  pNodeConf: Pointer to configuration parameters for new node to add.
1622   * @retval Error status
1623   */
SDMMC_DMALinkedList_BuildNode(SDMMC_DMALinkNodeTypeDef * pNode,SDMMC_DMALinkNodeConfTypeDef * pNodeConf)1624 uint32_t SDMMC_DMALinkedList_BuildNode(SDMMC_DMALinkNodeTypeDef *pNode, SDMMC_DMALinkNodeConfTypeDef *pNodeConf)
1625 {
1626 
1627   if ((pNode == NULL) || (pNodeConf == NULL))
1628   {
1629     return SDMMC_ERROR_INVALID_PARAMETER;
1630   }
1631   /* Configure the Link Node registers*/
1632   pNode->IDMABASER = pNodeConf->BufferAddress;
1633   pNode->IDMABSIZE = pNodeConf->BufferSize;
1634   pNode->IDMALAR   = SDMMC_IDMALAR_ULS | SDMMC_IDMALAR_ABR;
1635 
1636   return SDMMC_ERROR_NONE;
1637 }
1638 
1639 /**
1640   * @brief  Insert new Linked List node.
1641   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
1642   * @param  pPrevNode: Pointer to previous node .
1643   * @param  pNewNode: Pointer to new node to add.
1644   * @retval Error status
1645   */
SDMMC_DMALinkedList_InsertNode(SDMMC_DMALinkedListTypeDef * pLinkedList,SDMMC_DMALinkNodeTypeDef * pPrevNode,SDMMC_DMALinkNodeTypeDef * pNode)1646 uint32_t SDMMC_DMALinkedList_InsertNode(SDMMC_DMALinkedListTypeDef *pLinkedList, SDMMC_DMALinkNodeTypeDef *pPrevNode,
1647                                         SDMMC_DMALinkNodeTypeDef *pNode)
1648 {
1649   uint32_t link_list_offset;
1650   uint32_t node_address = (uint32_t) pNode;
1651 
1652   /* First Node */
1653   if (pLinkedList->NodesCounter == 0U)
1654   {
1655 
1656     pLinkedList->pHeadNode = pNode;
1657     pLinkedList->pTailNode = pNode;
1658     pLinkedList->NodesCounter = 1U;
1659 
1660   }
1661   else if (pPrevNode == pLinkedList->pTailNode)
1662   {
1663     if (pNode <= pLinkedList->pHeadNode)
1664     {
1665       /* Node Address should greater than Head Node Address*/
1666       return SDMMC_ERROR_INVALID_PARAMETER;
1667     }
1668 
1669     /*Last Node, no next node */
1670     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_ULA, 0U);
1671 
1672     /*link Prev node with new one */
1673     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_ULA, SDMMC_IDMALAR_ULA);
1674     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_IDMALA, (node_address - (uint32_t)pLinkedList->pHeadNode));
1675 
1676     pLinkedList->NodesCounter ++;
1677     pLinkedList->pTailNode = pNode;
1678 
1679   }
1680   else
1681   {
1682 
1683     if (pNode <= pLinkedList->pHeadNode)
1684     {
1685       /* Node Address should greater than Head Node Address*/
1686       return SDMMC_ERROR_INVALID_PARAMETER;
1687     }
1688 
1689     /*link New node with Next one */
1690     link_list_offset = pNode->IDMALAR;
1691     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_IDMALA, link_list_offset);
1692 
1693     /*link Prev node with new one */
1694     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_ULA, SDMMC_IDMALAR_ULA);
1695     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_IDMALA, (node_address - (uint32_t)pLinkedList->pHeadNode));
1696 
1697     pLinkedList->NodesCounter ++;
1698 
1699   }
1700   return SDMMC_ERROR_NONE;
1701 }
1702 
1703 /**
1704   * @brief  Remove  node from the Linked List.
1705   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
1706   * @param  pNode: Pointer to new node to add.
1707   * @retval Error status
1708    */
SDMMC_DMALinkedList_RemoveNode(SDMMC_DMALinkedListTypeDef * pLinkedList,SDMMC_DMALinkNodeTypeDef * pNode)1709 uint32_t SDMMC_DMALinkedList_RemoveNode(SDMMC_DMALinkedListTypeDef *pLinkedList, SDMMC_DMALinkNodeTypeDef *pNode)
1710 {
1711   uint32_t count = 0U;
1712   uint32_t linked_list_offset;
1713   SDMMC_DMALinkNodeTypeDef *prev_node = NULL;
1714   SDMMC_DMALinkNodeTypeDef *curr_node ;
1715 
1716   /* First Node */
1717   if (pLinkedList->NodesCounter == 0U)
1718   {
1719 
1720     return SDMMC_ERROR_INVALID_PARAMETER;
1721   }
1722   else
1723   {
1724     curr_node = pLinkedList->pHeadNode;
1725     while ((curr_node != pNode) && (count <= pLinkedList->NodesCounter))
1726     {
1727       prev_node = curr_node;
1728       curr_node = (SDMMC_DMALinkNodeTypeDef *)((prev_node->IDMALAR & SDMMC_IDMALAR_IDMALA) +
1729                                                (uint32_t)pLinkedList->pHeadNode);
1730       count++;
1731     }
1732 
1733     if ((count == 0U) || (count > pLinkedList->NodesCounter))
1734     {
1735       /* Node not found in the linked list */
1736       return SDMMC_ERROR_INVALID_PARAMETER;
1737     }
1738 
1739     pLinkedList->NodesCounter--;
1740 
1741     if (pLinkedList->NodesCounter == 0U)
1742     {
1743       pLinkedList->pHeadNode = 0U;
1744       pLinkedList->pTailNode = 0U;
1745     }
1746     else
1747     {
1748       /*link prev node with next one */
1749       linked_list_offset = curr_node->IDMALAR;
1750       MODIFY_REG(prev_node->IDMALAR, SDMMC_IDMALAR_IDMALA, linked_list_offset);
1751       /* Configure the new Link Node registers*/
1752       pNode->IDMALAR    |= linked_list_offset;
1753 
1754       pLinkedList->pTailNode = prev_node;
1755     }
1756   }
1757   return SDMMC_ERROR_NONE;
1758 }
1759 
1760 /**
1761   * @brief  Lock Linked List Node
1762   * @param  pNode: Pointer to node to lock.
1763   * @retval Error status
1764 
1765   */
SDMMC_DMALinkedList_LockNode(SDMMC_DMALinkNodeTypeDef * pNode)1766 uint32_t SDMMC_DMALinkedList_LockNode(SDMMC_DMALinkNodeTypeDef *pNode)
1767 {
1768 
1769   if (pNode == NULL)
1770   {
1771     return SDMMC_ERROR_INVALID_PARAMETER;
1772   }
1773 
1774   MODIFY_REG(pNode->IDMALAR, SDMMC_IDMALAR_ABR, 0U);
1775 
1776   return SDMMC_ERROR_NONE;
1777 }
1778 
1779 /**
1780   * @brief  Unlock Linked List Node
1781   * @param  pNode: Pointer to node to unlock.
1782   * @retval Error status
1783 
1784   */
SDMMC_DMALinkedList_UnlockNode(SDMMC_DMALinkNodeTypeDef * pNode)1785 uint32_t SDMMC_DMALinkedList_UnlockNode(SDMMC_DMALinkNodeTypeDef *pNode)
1786 {
1787 
1788   if (pNode == NULL)
1789   {
1790     return SDMMC_ERROR_INVALID_PARAMETER;
1791   }
1792 
1793   MODIFY_REG(pNode->IDMALAR, SDMMC_IDMALAR_ABR, SDMMC_IDMALAR_ABR);
1794 
1795   return SDMMC_ERROR_NONE;
1796 }
1797 
1798 /**
1799   * @brief  Enable Linked List circular mode
1800   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
1801   * @retval Error status
1802 
1803   */
SDMMC_DMALinkedList_EnableCircularMode(SDMMC_DMALinkedListTypeDef * pLinkedList)1804 uint32_t SDMMC_DMALinkedList_EnableCircularMode(SDMMC_DMALinkedListTypeDef *pLinkedList)
1805 {
1806 
1807   if (pLinkedList == NULL)
1808   {
1809     return SDMMC_ERROR_INVALID_PARAMETER;
1810   }
1811 
1812   MODIFY_REG(pLinkedList->pTailNode->IDMALAR, SDMMC_IDMALAR_ULA | SDMMC_IDMALAR_IDMALA, SDMMC_IDMALAR_ULA);
1813 
1814   return SDMMC_ERROR_NONE;
1815 }
1816 
1817 /**
1818   * @brief  Disable DMA Linked List Circular mode
1819   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
1820   * @retval Error status
1821    */
SDMMC_DMALinkedList_DisableCircularMode(SDMMC_DMALinkedListTypeDef * pLinkedList)1822 uint32_t SDMMC_DMALinkedList_DisableCircularMode(SDMMC_DMALinkedListTypeDef *pLinkedList)
1823 {
1824 
1825   if (pLinkedList == NULL)
1826   {
1827     return SDMMC_ERROR_INVALID_PARAMETER;
1828   }
1829 
1830   MODIFY_REG(pLinkedList->pTailNode->IDMALAR, SDMMC_IDMALAR_ULA, 0U);
1831 
1832   return SDMMC_ERROR_NONE;
1833 }
1834 
1835 /**
1836   * @}
1837   */
1838 
1839 
1840 /* Private function ----------------------------------------------------------*/
1841 /** @addtogroup SD_Private_Functions
1842   * @{
1843   */
1844 
1845 /**
1846   * @brief  Checks for error conditions for CMD0.
1847   * @param  hsd: SD handle
1848   * @retval SD Card error state
1849   */
SDMMC_GetCmdError(SDMMC_TypeDef * SDMMCx)1850 static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx)
1851 {
1852   /* 8 is the number of required instructions cycles for the below loop statement.
1853   The SDMMC_CMDTIMEOUT is expressed in ms */
1854   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1855 
1856   do
1857   {
1858     if (count-- == 0U)
1859     {
1860       return SDMMC_ERROR_TIMEOUT;
1861     }
1862 
1863   } while (!__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDSENT));
1864 
1865   /* Clear all the static flags */
1866   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1867 
1868   return SDMMC_ERROR_NONE;
1869 }
1870 
1871 /**
1872   * @}
1873   */
1874 
1875 #endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
1876 #endif /* SDMMC1 || SDMMC2 */
1877 /**
1878   * @}
1879   */
1880 
1881 /**
1882   * @}
1883   */
1884