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