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 
153 /* Includes ------------------------------------------------------------------*/
154 #include "stm32u5xx_hal.h"
155 
156 /** @addtogroup STM32U5xx_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) || defined (HAL_SDIO_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(const SDMMC_TypeDef * SDMMCx)252 uint32_t SDMMC_ReadFIFO(const 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(const SDMMC_TypeDef * SDMMCx)339 uint32_t SDMMC_GetPowerState(const 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,const SDMMC_CmdInitTypeDef * Command)352 HAL_StatusTypeDef SDMMC_SendCommand(SDMMC_TypeDef *SDMMCx, const 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(const SDMMC_TypeDef * SDMMCx)382 uint8_t SDMMC_GetCommandResponse(const 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(const SDMMC_TypeDef * SDMMCx,uint32_t Response)399 uint32_t SDMMC_GetResponse(const 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,const SDMMC_DataInitTypeDef * Data)420 HAL_StatusTypeDef SDMMC_ConfigData(SDMMC_TypeDef *SDMMCx, const 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(const SDMMC_TypeDef * SDMMCx)455 uint32_t SDMMC_GetDataCounter(const 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(const SDMMC_TypeDef * SDMMCx)465 uint32_t SDMMC_GetFIFOCount(const 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 Data Block number command and check the response
535   * @param  SDMMCx: Pointer to SDMMC register base
536   * @retval HAL status
537   */
SDMMC_CmdBlockCount(SDMMC_TypeDef * SDMMCx,uint32_t BlockCount)538 uint32_t SDMMC_CmdBlockCount(SDMMC_TypeDef *SDMMCx, uint32_t BlockCount)
539 {
540   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
541   uint32_t errorstate;
542 
543   /* Set Block Size for Card */
544   sdmmc_cmdinit.Argument         = (uint32_t)BlockCount;
545   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_BLOCK_COUNT;
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_SET_BLOCK_COUNT, SDMMC_CMDTIMEOUT);
553 
554   return errorstate;
555 }
556 
557 /**
558   * @brief  Send the Read Single Block command and check the response
559   * @param  SDMMCx: Pointer to SDMMC register base
560   * @retval HAL status
561   */
SDMMC_CmdReadSingleBlock(SDMMC_TypeDef * SDMMCx,uint32_t ReadAdd)562 uint32_t SDMMC_CmdReadSingleBlock(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_SINGLE_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_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
577 
578   return errorstate;
579 }
580 
581 /**
582   * @brief  Send the Read Multi Block command and check the response
583   * @param  SDMMCx: Pointer to SDMMC register base
584   * @retval HAL status
585   */
SDMMC_CmdReadMultiBlock(SDMMC_TypeDef * SDMMCx,uint32_t ReadAdd)586 uint32_t SDMMC_CmdReadMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t ReadAdd)
587 {
588   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
589   uint32_t errorstate;
590 
591   /* Set Block Size for Card */
592   sdmmc_cmdinit.Argument         = (uint32_t)ReadAdd;
593   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_READ_MULT_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_READ_MULT_BLOCK, SDMMC_CMDTIMEOUT);
601 
602   return errorstate;
603 }
604 
605 /**
606   * @brief  Send the Write Single Block command and check the response
607   * @param  SDMMCx: Pointer to SDMMC register base
608   * @retval HAL status
609   */
SDMMC_CmdWriteSingleBlock(SDMMC_TypeDef * SDMMCx,uint32_t WriteAdd)610 uint32_t SDMMC_CmdWriteSingleBlock(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_SINGLE_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_SINGLE_BLOCK, SDMMC_CMDTIMEOUT);
625 
626   return errorstate;
627 }
628 
629 /**
630   * @brief  Send the Write Multi Block command and check the response
631   * @param  SDMMCx: Pointer to SDMMC register base
632   * @retval HAL status
633   */
SDMMC_CmdWriteMultiBlock(SDMMC_TypeDef * SDMMCx,uint32_t WriteAdd)634 uint32_t SDMMC_CmdWriteMultiBlock(SDMMC_TypeDef *SDMMCx, uint32_t WriteAdd)
635 {
636   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
637   uint32_t errorstate;
638 
639   /* Set Block Size for Card */
640   sdmmc_cmdinit.Argument         = (uint32_t)WriteAdd;
641   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_WRITE_MULT_BLOCK;
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_WRITE_MULT_BLOCK, SDMMC_CMDTIMEOUT);
649 
650   return errorstate;
651 }
652 
653 /**
654   * @brief  Send the Start Address Erase command for SD and check the response
655   * @param  SDMMCx: Pointer to SDMMC register base
656   * @retval HAL status
657   */
SDMMC_CmdSDEraseStartAdd(SDMMC_TypeDef * SDMMCx,uint32_t StartAdd)658 uint32_t SDMMC_CmdSDEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
659 {
660   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
661   uint32_t errorstate;
662 
663   /* Set Block Size for Card */
664   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
665   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_START;
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_START, SDMMC_CMDTIMEOUT);
673 
674   return errorstate;
675 }
676 
677 /**
678   * @brief  Send the End Address Erase command for SD and check the response
679   * @param  SDMMCx: Pointer to SDMMC register base
680   * @retval HAL status
681   */
SDMMC_CmdSDEraseEndAdd(SDMMC_TypeDef * SDMMCx,uint32_t EndAdd)682 uint32_t SDMMC_CmdSDEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
683 {
684   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
685   uint32_t errorstate;
686 
687   /* Set Block Size for Card */
688   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
689   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_ERASE_GRP_END;
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_SD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
697 
698   return errorstate;
699 }
700 
701 /**
702   * @brief  Send the Start Address Erase command and check the response
703   * @param  SDMMCx: Pointer to SDMMC register base
704   * @retval HAL status
705   */
SDMMC_CmdEraseStartAdd(SDMMC_TypeDef * SDMMCx,uint32_t StartAdd)706 uint32_t SDMMC_CmdEraseStartAdd(SDMMC_TypeDef *SDMMCx, uint32_t StartAdd)
707 {
708   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
709   uint32_t errorstate;
710 
711   /* Set Block Size for Card */
712   sdmmc_cmdinit.Argument         = (uint32_t)StartAdd;
713   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_START;
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_START, SDMMC_CMDTIMEOUT);
721 
722   return errorstate;
723 }
724 
725 /**
726   * @brief  Send the End Address Erase command and check the response
727   * @param  SDMMCx: Pointer to SDMMC register base
728   * @retval HAL status
729   */
SDMMC_CmdEraseEndAdd(SDMMC_TypeDef * SDMMCx,uint32_t EndAdd)730 uint32_t SDMMC_CmdEraseEndAdd(SDMMC_TypeDef *SDMMCx, uint32_t EndAdd)
731 {
732   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
733   uint32_t errorstate;
734 
735   /* Set Block Size for Card */
736   sdmmc_cmdinit.Argument         = (uint32_t)EndAdd;
737   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE_GRP_END;
738   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
739   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
740   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
741   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
742 
743   /* Check for error conditions */
744   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE_GRP_END, SDMMC_CMDTIMEOUT);
745 
746   return errorstate;
747 }
748 
749 /**
750   * @brief  Send the Erase command and check the response
751   * @param  SDMMCx Pointer to SDMMC register base
752   * @param  EraseType Type of erase to be performed
753   * @retval HAL status
754   */
SDMMC_CmdErase(SDMMC_TypeDef * SDMMCx,uint32_t EraseType)755 uint32_t SDMMC_CmdErase(SDMMC_TypeDef *SDMMCx, uint32_t EraseType)
756 {
757   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
758   uint32_t errorstate;
759 
760   /* Set Block Size for Card */
761   sdmmc_cmdinit.Argument         = EraseType;
762   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ERASE;
763   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
764   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
765   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
766   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
767 
768   /* Check for error conditions */
769   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_ERASE, SDMMC_MAXERASETIMEOUT);
770 
771   return errorstate;
772 }
773 
774 /**
775   * @brief  Send the Stop Transfer command and check the response.
776   * @param  SDMMCx: Pointer to SDMMC register base
777   * @retval HAL status
778   */
SDMMC_CmdStopTransfer(SDMMC_TypeDef * SDMMCx)779 uint32_t SDMMC_CmdStopTransfer(SDMMC_TypeDef *SDMMCx)
780 {
781   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
782   uint32_t errorstate;
783 
784   /* Send CMD12 STOP_TRANSMISSION  */
785   sdmmc_cmdinit.Argument         = 0U;
786   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_STOP_TRANSMISSION;
787   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
788   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
789   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
790 
791   __SDMMC_CMDSTOP_ENABLE(SDMMCx);
792   __SDMMC_CMDTRANS_DISABLE(SDMMCx);
793 
794   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
795 
796   /* Check for error conditions */
797   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_STOP_TRANSMISSION, SDMMC_STOPTRANSFERTIMEOUT);
798 
799   __SDMMC_CMDSTOP_DISABLE(SDMMCx);
800 
801   /* Ignore Address Out Of Range Error, Not relevant at end of memory */
802   if (errorstate == SDMMC_ERROR_ADDR_OUT_OF_RANGE)
803   {
804     errorstate = SDMMC_ERROR_NONE;
805   }
806 
807   return errorstate;
808 }
809 
810 /**
811   * @brief  Send the Select Deselect command and check the response.
812   * @param  SDMMCx: Pointer to SDMMC register base
813   * @param  addr: Address of the card to be selected
814   * @retval HAL status
815   */
SDMMC_CmdSelDesel(SDMMC_TypeDef * SDMMCx,uint32_t Addr)816 uint32_t SDMMC_CmdSelDesel(SDMMC_TypeDef *SDMMCx, uint32_t Addr)
817 {
818   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
819   uint32_t errorstate;
820 
821   /* Send CMD7 SDMMC_SEL_DESEL_CARD */
822   sdmmc_cmdinit.Argument         = (uint32_t)Addr;
823   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEL_DESEL_CARD;
824   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
825   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
826   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
827   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
828 
829   /* Check for error conditions */
830   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEL_DESEL_CARD, SDMMC_CMDTIMEOUT);
831 
832   return errorstate;
833 }
834 
835 /**
836   * @brief  Send the Go Idle State command and check the response.
837   * @param  SDMMCx: Pointer to SDMMC register base
838   * @retval HAL status
839   */
SDMMC_CmdGoIdleState(SDMMC_TypeDef * SDMMCx)840 uint32_t SDMMC_CmdGoIdleState(SDMMC_TypeDef *SDMMCx)
841 {
842   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
843   uint32_t errorstate;
844 
845   sdmmc_cmdinit.Argument         = 0U;
846   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_GO_IDLE_STATE;
847   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_NO;
848   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
849   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
850   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
851 
852   /* Check for error conditions */
853   errorstate = SDMMC_GetCmdError(SDMMCx);
854 
855   return errorstate;
856 }
857 
858 /**
859   * @brief  Send the Operating Condition command and check the response.
860   * @param  SDMMCx: Pointer to SDMMC register base
861   * @retval HAL status
862   */
SDMMC_CmdOperCond(SDMMC_TypeDef * SDMMCx)863 uint32_t SDMMC_CmdOperCond(SDMMC_TypeDef *SDMMCx)
864 {
865   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
866   uint32_t errorstate;
867 
868   /* Send CMD8 to verify SD card interface operating condition */
869   /* Argument: - [31:12]: Reserved (shall be set to '0')
870   - [11:8]: Supply Voltage (VHS) 0x1 (Range: 2.7-3.6 V)
871   - [7:0]: Check Pattern (recommended 0xAA) */
872   /* CMD Response: R7 */
873   sdmmc_cmdinit.Argument         = SDMMC_CHECK_PATTERN;
874   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
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   errorstate = SDMMC_GetCmdResp7(SDMMCx);
882 
883   return errorstate;
884 }
885 
886 /**
887   * @brief  Send the Application command to verify that that the next command
888   *         is an application specific com-mand rather than a standard command
889   *         and check the response.
890   * @param  SDMMCx: Pointer to SDMMC register base
891   * @param  Argument: Command Argument
892   * @retval HAL status
893   */
SDMMC_CmdAppCommand(SDMMC_TypeDef * SDMMCx,uint32_t Argument)894 uint32_t SDMMC_CmdAppCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
895 {
896   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
897   uint32_t errorstate;
898 
899   sdmmc_cmdinit.Argument         = (uint32_t)Argument;
900   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_CMD;
901   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
902   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
903   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
904   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
905 
906   /* Check for error conditions */
907   /* If there is a HAL_ERROR, it is a MMC card, else
908   it is a SD card: SD card 2.0 (voltage range mismatch)
909      or SD card 1.x */
910   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_APP_CMD, SDMMC_CMDTIMEOUT);
911 
912   return errorstate;
913 }
914 
915 /**
916   * @brief  Send the command asking the accessed card to send its operating
917   *         condition register (OCR)
918   * @param  SDMMCx: Pointer to SDMMC register base
919   * @param  Argument: Command Argument
920   * @retval HAL status
921   */
SDMMC_CmdAppOperCommand(SDMMC_TypeDef * SDMMCx,uint32_t Argument)922 uint32_t SDMMC_CmdAppOperCommand(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
923 {
924   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
925   uint32_t errorstate;
926 
927   sdmmc_cmdinit.Argument         = Argument;
928   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_OP_COND;
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_GetCmdResp3(SDMMCx);
936 
937   return errorstate;
938 }
939 
940 /**
941   * @brief  Send the Bus Width command and check the response.
942   * @param  SDMMCx: Pointer to SDMMC register base
943   * @param  BusWidth: BusWidth
944   * @retval HAL status
945   */
SDMMC_CmdBusWidth(SDMMC_TypeDef * SDMMCx,uint32_t BusWidth)946 uint32_t SDMMC_CmdBusWidth(SDMMC_TypeDef *SDMMCx, uint32_t BusWidth)
947 {
948   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
949   uint32_t errorstate;
950 
951   sdmmc_cmdinit.Argument         = (uint32_t)BusWidth;
952   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_APP_SD_SET_BUSWIDTH;
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_APP_SD_SET_BUSWIDTH, SDMMC_CMDTIMEOUT);
960 
961   return errorstate;
962 }
963 
964 /**
965   * @brief  Send the Send SCR command and check the response.
966   * @param  SDMMCx: Pointer to SDMMC register base
967   * @retval HAL status
968   */
SDMMC_CmdSendSCR(SDMMC_TypeDef * SDMMCx)969 uint32_t SDMMC_CmdSendSCR(SDMMC_TypeDef *SDMMCx)
970 {
971   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
972   uint32_t errorstate;
973 
974   /* Send CMD51 SD_APP_SEND_SCR */
975   sdmmc_cmdinit.Argument         = 0U;
976   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_SEND_SCR;
977   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
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_GetCmdResp1(SDMMCx, SDMMC_CMD_SD_APP_SEND_SCR, SDMMC_CMDTIMEOUT);
984 
985   return errorstate;
986 }
987 
988 /**
989   * @brief  Send the Send CID command and check the response.
990   * @param  SDMMCx: Pointer to SDMMC register base
991   * @retval HAL status
992   */
SDMMC_CmdSendCID(SDMMC_TypeDef * SDMMCx)993 uint32_t SDMMC_CmdSendCID(SDMMC_TypeDef *SDMMCx)
994 {
995   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
996   uint32_t errorstate;
997 
998   /* Send CMD2 ALL_SEND_CID */
999   sdmmc_cmdinit.Argument         = 0U;
1000   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_ALL_SEND_CID;
1001   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_LONG;
1002   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1003   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1004   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1005 
1006   /* Check for error conditions */
1007   errorstate = SDMMC_GetCmdResp2(SDMMCx);
1008 
1009   return errorstate;
1010 }
1011 
1012 /**
1013   * @brief  Send the Send CSD command and check the response.
1014   * @param  SDMMCx: Pointer to SDMMC register base
1015   * @param  Argument: Command Argument
1016   * @retval HAL status
1017   */
SDMMC_CmdSendCSD(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1018 uint32_t SDMMC_CmdSendCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1019 {
1020   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1021   uint32_t errorstate;
1022 
1023   /* Send CMD9 SEND_CSD */
1024   sdmmc_cmdinit.Argument         = Argument;
1025   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_CSD;
1026   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_LONG;
1027   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1028   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1029   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1030 
1031   /* Check for error conditions */
1032   errorstate = SDMMC_GetCmdResp2(SDMMCx);
1033 
1034   return errorstate;
1035 }
1036 
1037 /**
1038   * @brief  Send the Send CSD command and check the response.
1039   * @param  SDMMCx: Pointer to SDMMC register base
1040   * @param  pRCA: Card RCA
1041   * @retval HAL status
1042   */
SDMMC_CmdSetRelAdd(SDMMC_TypeDef * SDMMCx,uint16_t * pRCA)1043 uint32_t SDMMC_CmdSetRelAdd(SDMMC_TypeDef *SDMMCx, uint16_t *pRCA)
1044 {
1045   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1046   uint32_t errorstate;
1047 
1048   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1049   sdmmc_cmdinit.Argument         = 0U;
1050   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1051   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1052   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1053   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1054   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1055 
1056   /* Check for error conditions */
1057   errorstate = SDMMC_GetCmdResp6(SDMMCx, SDMMC_CMD_SET_REL_ADDR, pRCA);
1058 
1059   return errorstate;
1060 }
1061 
1062 /**
1063   * @brief  Send the Set Relative Address command to MMC card (not SD card).
1064   * @param  SDMMCx Pointer to SDMMC register base
1065   * @param  RCA Card RCA
1066   * @retval HAL status
1067   */
SDMMC_CmdSetRelAddMmc(SDMMC_TypeDef * SDMMCx,uint16_t RCA)1068 uint32_t SDMMC_CmdSetRelAddMmc(SDMMC_TypeDef *SDMMCx, uint16_t RCA)
1069 {
1070   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1071   uint32_t errorstate;
1072 
1073   /* Send CMD3 SD_CMD_SET_REL_ADDR */
1074   sdmmc_cmdinit.Argument         = ((uint32_t)RCA << 16U);
1075   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SET_REL_ADDR;
1076   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1077   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1078   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1079   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1080 
1081   /* Check for error conditions */
1082   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SET_REL_ADDR, SDMMC_CMDTIMEOUT);
1083 
1084   return errorstate;
1085 }
1086 
1087 /**
1088   * @brief  Send the Sleep command to MMC card (not SD card).
1089   * @param  SDMMCx Pointer to SDMMC register base
1090   * @param  Argument Argument of the command (RCA and Sleep/Awake)
1091   * @retval HAL status
1092   */
SDMMC_CmdSleepMmc(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1093 uint32_t SDMMC_CmdSleepMmc(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1094 {
1095   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1096   uint32_t errorstate;
1097 
1098   /* Send CMD5 SDMMC_CMD_MMC_SLEEP_AWAKE */
1099   sdmmc_cmdinit.Argument         = Argument;
1100   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_MMC_SLEEP_AWAKE;
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_MMC_SLEEP_AWAKE, SDMMC_CMDTIMEOUT);
1108 
1109   return errorstate;
1110 }
1111 
1112 /**
1113   * @brief  Send the Status command and check the response.
1114   * @param  SDMMCx: Pointer to SDMMC register base
1115   * @param  Argument: Command Argument
1116   * @retval HAL status
1117   */
SDMMC_CmdSendStatus(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1118 uint32_t SDMMC_CmdSendStatus(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1119 {
1120   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1121   uint32_t errorstate;
1122 
1123   sdmmc_cmdinit.Argument         = Argument;
1124   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_STATUS;
1125   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1126   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1127   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1128   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1129 
1130   /* Check for error conditions */
1131   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_SEND_STATUS, SDMMC_CMDTIMEOUT);
1132 
1133   return errorstate;
1134 }
1135 
1136 /**
1137   * @brief  Send the Status register command and check the response.
1138   * @param  SDMMCx: Pointer to SDMMC register base
1139   * @retval HAL status
1140   */
SDMMC_CmdStatusRegister(SDMMC_TypeDef * SDMMCx)1141 uint32_t SDMMC_CmdStatusRegister(SDMMC_TypeDef *SDMMCx)
1142 {
1143   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1144   uint32_t errorstate;
1145 
1146   sdmmc_cmdinit.Argument         = 0U;
1147   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SD_APP_STATUS;
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_SD_APP_STATUS, SDMMC_CMDTIMEOUT);
1155 
1156   return errorstate;
1157 }
1158 
1159 /**
1160   * @brief  Sends host capacity support information and activates the card's
1161   *         initialization process. Send SDMMC_CMD_SEND_OP_COND command
1162   * @param  SDMMCx: Pointer to SDMMC register base
1163   * @parame Argument: Argument used for the command
1164   * @retval HAL status
1165   */
SDMMC_CmdOpCondition(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1166 uint32_t SDMMC_CmdOpCondition(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1167 {
1168   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1169   uint32_t errorstate;
1170 
1171   sdmmc_cmdinit.Argument         = Argument;
1172   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SEND_OP_COND;
1173   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1174   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1175   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1176   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1177 
1178   /* Check for error conditions */
1179   errorstate = SDMMC_GetCmdResp3(SDMMCx);
1180 
1181   return errorstate;
1182 }
1183 
1184 /**
1185   * @brief  Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
1186   * @param  SDMMCx: Pointer to SDMMC register base
1187   * @parame Argument: Argument used for the command
1188   * @retval HAL status
1189   */
SDMMC_CmdSwitch(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1190 uint32_t SDMMC_CmdSwitch(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1191 {
1192   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1193   uint32_t errorstate;
1194 
1195   /* Send CMD6 to activate SDR50 Mode and Power Limit 1.44W */
1196   /* CMD Response: R1 */
1197   sdmmc_cmdinit.Argument         = Argument; /* SDMMC_SDR25_SWITCH_PATTERN*/
1198   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_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_HS_SWITCH, SDMMC_CMDTIMEOUT);
1206 
1207   return errorstate;
1208 }
1209 
1210 /**
1211   * @brief  Send the command asking the accessed card to send its operating
1212   *         condition register (OCR)
1213   * @param  None
1214   * @retval HAL status
1215   */
SDMMC_CmdVoltageSwitch(SDMMC_TypeDef * SDMMCx)1216 uint32_t SDMMC_CmdVoltageSwitch(SDMMC_TypeDef *SDMMCx)
1217 {
1218   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1219   uint32_t errorstate;
1220 
1221   sdmmc_cmdinit.Argument         = 0x00000000;
1222   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_VOLTAGE_SWITCH;
1223   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1224   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1225   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1226   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1227 
1228   /* Check for error conditions */
1229   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_VOLTAGE_SWITCH, SDMMC_CMDTIMEOUT);
1230 
1231   return errorstate;
1232 }
1233 
1234 /**
1235   * @brief  Send the Send EXT_CSD command and check the response.
1236   * @param  SDMMCx: Pointer to SDMMC register base
1237   * @param  Argument: Command Argument
1238   * @retval HAL status
1239   */
SDMMC_CmdSendEXTCSD(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1240 uint32_t SDMMC_CmdSendEXTCSD(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1241 {
1242   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1243   uint32_t errorstate;
1244 
1245   /* Send CMD9 SEND_CSD */
1246   sdmmc_cmdinit.Argument         = Argument;
1247   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_HS_SEND_EXT_CSD;
1248   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1249   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1250   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1251   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1252 
1253   /* Check for error conditions */
1254   errorstate = SDMMC_GetCmdResp1(SDMMCx, SDMMC_CMD_HS_SEND_EXT_CSD, SDMMC_CMDTIMEOUT);
1255 
1256   return errorstate;
1257 }
1258 
1259 /**
1260   * @brief  Execute a cmd52 to write single byte data and read single byte data if needed
1261   * @param  SDMMCx: Pointer to SDMMC register base
1262   * @param  Argument:  SDMMC command argument which is sent to a card as part of a command message
1263   * @param  pData: pointer to read response if needed
1264   * @retval SD Card error state
1265   */
SDMMC_SDIO_CmdReadWriteDirect(SDMMC_TypeDef * SDMMCx,uint32_t Argument,uint8_t * pResponse)1266 uint32_t SDMMC_SDIO_CmdReadWriteDirect(SDMMC_TypeDef *SDMMCx, uint32_t Argument, uint8_t *pResponse)
1267 {
1268   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1269   uint32_t errorstate;
1270 
1271   sdmmc_cmdinit.Argument         = Argument;
1272   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SDMMC_RW_DIRECT;
1273   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1274   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1275   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1276   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1277 
1278   /* Check for error conditions */
1279   errorstate = SDMMC_GetCmdResp5(SDMMCx, SDMMC_CMD_SDMMC_RW_DIRECT, pResponse);
1280 
1281   return errorstate;
1282 }
1283 
1284 /**
1285   * @brief  Execute a cmd53 to write or read multiple data with a single command
1286   * @param  SDMMCx: Pointer to SDMMC register base
1287   * @param  Argument: SDMMC command argument which is sent to a card as part of a command message
1288   * @retval SD Card error state
1289   */
SDMMC_SDIO_CmdReadWriteExtended(SDMMC_TypeDef * SDMMCx,uint32_t Argument)1290 uint32_t SDMMC_SDIO_CmdReadWriteExtended(SDMMC_TypeDef *SDMMCx, uint32_t Argument)
1291 {
1292   SDMMC_CmdInitTypeDef  sdmmc_cmdinit;
1293   uint32_t errorstate;
1294 
1295   sdmmc_cmdinit.Argument         = Argument;
1296   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SDMMC_RW_EXTENDED;
1297   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1298   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1299   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1300   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1301 
1302   /* Check for error conditions */
1303   errorstate = SDMMC_GetCmdResp5(SDMMCx, SDMMC_CMD_SDMMC_RW_EXTENDED, NULL);
1304 
1305   return errorstate;
1306 }
1307 
1308 /**
1309   * @brief  Execute a cmd5 to write or read multiple data with a single command
1310   * @param  SDMMCx: Pointer to SDMMC register base
1311   * @param  Argument: SDMMC command argument which is sent to a card as part of a command message
1312   * @retval SD Card error state
1313   */
SDMMC_CmdSendOperationcondition(SDMMC_TypeDef * SDMMCx,uint32_t Argument,uint32_t * pResp)1314 uint32_t SDMMC_CmdSendOperationcondition(SDMMC_TypeDef *SDMMCx, uint32_t Argument, uint32_t *pResp)
1315 {
1316   SDMMC_CmdInitTypeDef sdmmc_cmdinit;
1317   uint32_t             errorstate;
1318 
1319   sdmmc_cmdinit.Argument         = Argument;
1320   sdmmc_cmdinit.CmdIndex         = SDMMC_CMD_SDMMC_SEN_OP_COND;
1321   sdmmc_cmdinit.Response         = SDMMC_RESPONSE_SHORT;
1322   sdmmc_cmdinit.WaitForInterrupt = SDMMC_WAIT_NO;
1323   sdmmc_cmdinit.CPSM             = SDMMC_CPSM_ENABLE;
1324   (void)SDMMC_SendCommand(SDMMCx, &sdmmc_cmdinit);
1325 
1326   /* Check for error conditions */
1327   errorstate = SDMMC_GetCmdResp4(SDMMCx, pResp);
1328 
1329   return errorstate;
1330 }
1331 /**
1332   * @}
1333   */
1334 
1335 
1336 /** @defgroup HAL_SDMMC_LL_Group5 Responses management functions
1337   *  @brief   Responses functions
1338   *
1339 @verbatim
1340  ===============================================================================
1341                    ##### Responses management functions #####
1342  ===============================================================================
1343     [..]
1344     This subsection provides a set of functions allowing to manage the needed responses.
1345 
1346 @endverbatim
1347   * @{
1348   */
1349 /**
1350   * @brief  Checks for error conditions for R1 response.
1351   * @param  hsd: SD handle
1352   * @param  SD_CMD: The sent command index
1353   * @retval SD Card error state
1354   */
SDMMC_GetCmdResp1(SDMMC_TypeDef * SDMMCx,uint8_t SD_CMD,uint32_t Timeout)1355 uint32_t SDMMC_GetCmdResp1(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint32_t Timeout)
1356 {
1357   uint32_t response_r1;
1358   uint32_t sta_reg;
1359 
1360   /* 8 is the number of required instructions cycles for the below loop statement.
1361   The Timeout is expressed in ms */
1362   uint32_t count = Timeout * (SystemCoreClock / 8U / 1000U);
1363 
1364   do
1365   {
1366     if (count-- == 0U)
1367     {
1368       return SDMMC_ERROR_TIMEOUT;
1369     }
1370     sta_reg = SDMMCx->STA;
1371   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT |
1372                         SDMMC_FLAG_BUSYD0END)) == 0U) || ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1373 
1374   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1375   {
1376     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1377 
1378     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1379   }
1380   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1381   {
1382     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1383 
1384     return SDMMC_ERROR_CMD_CRC_FAIL;
1385   }
1386   else
1387   {
1388     /* Nothing to do */
1389   }
1390 
1391   /* Clear all the static flags */
1392   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1393 
1394   /* Check response received is of desired command */
1395   if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
1396   {
1397     return SDMMC_ERROR_CMD_CRC_FAIL;
1398   }
1399 
1400   /* We have received response, retrieve it for analysis  */
1401   response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1402 
1403   if ((response_r1 & SDMMC_OCR_ERRORBITS) == SDMMC_ALLZERO)
1404   {
1405     return SDMMC_ERROR_NONE;
1406   }
1407   else if ((response_r1 & SDMMC_OCR_ADDR_OUT_OF_RANGE) == SDMMC_OCR_ADDR_OUT_OF_RANGE)
1408   {
1409     return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
1410   }
1411   else if ((response_r1 & SDMMC_OCR_ADDR_MISALIGNED) == SDMMC_OCR_ADDR_MISALIGNED)
1412   {
1413     return SDMMC_ERROR_ADDR_MISALIGNED;
1414   }
1415   else if ((response_r1 & SDMMC_OCR_BLOCK_LEN_ERR) == SDMMC_OCR_BLOCK_LEN_ERR)
1416   {
1417     return SDMMC_ERROR_BLOCK_LEN_ERR;
1418   }
1419   else if ((response_r1 & SDMMC_OCR_ERASE_SEQ_ERR) == SDMMC_OCR_ERASE_SEQ_ERR)
1420   {
1421     return SDMMC_ERROR_ERASE_SEQ_ERR;
1422   }
1423   else if ((response_r1 & SDMMC_OCR_BAD_ERASE_PARAM) == SDMMC_OCR_BAD_ERASE_PARAM)
1424   {
1425     return SDMMC_ERROR_BAD_ERASE_PARAM;
1426   }
1427   else if ((response_r1 & SDMMC_OCR_WRITE_PROT_VIOLATION) == SDMMC_OCR_WRITE_PROT_VIOLATION)
1428   {
1429     return SDMMC_ERROR_WRITE_PROT_VIOLATION;
1430   }
1431   else if ((response_r1 & SDMMC_OCR_LOCK_UNLOCK_FAILED) == SDMMC_OCR_LOCK_UNLOCK_FAILED)
1432   {
1433     return SDMMC_ERROR_LOCK_UNLOCK_FAILED;
1434   }
1435   else if ((response_r1 & SDMMC_OCR_COM_CRC_FAILED) == SDMMC_OCR_COM_CRC_FAILED)
1436   {
1437     return SDMMC_ERROR_COM_CRC_FAILED;
1438   }
1439   else if ((response_r1 & SDMMC_OCR_ILLEGAL_CMD) == SDMMC_OCR_ILLEGAL_CMD)
1440   {
1441     return SDMMC_ERROR_ILLEGAL_CMD;
1442   }
1443   else if ((response_r1 & SDMMC_OCR_CARD_ECC_FAILED) == SDMMC_OCR_CARD_ECC_FAILED)
1444   {
1445     return SDMMC_ERROR_CARD_ECC_FAILED;
1446   }
1447   else if ((response_r1 & SDMMC_OCR_CC_ERROR) == SDMMC_OCR_CC_ERROR)
1448   {
1449     return SDMMC_ERROR_CC_ERR;
1450   }
1451   else if ((response_r1 & SDMMC_OCR_STREAM_READ_UNDERRUN) == SDMMC_OCR_STREAM_READ_UNDERRUN)
1452   {
1453     return SDMMC_ERROR_STREAM_READ_UNDERRUN;
1454   }
1455   else if ((response_r1 & SDMMC_OCR_STREAM_WRITE_OVERRUN) == SDMMC_OCR_STREAM_WRITE_OVERRUN)
1456   {
1457     return SDMMC_ERROR_STREAM_WRITE_OVERRUN;
1458   }
1459   else if ((response_r1 & SDMMC_OCR_CID_CSD_OVERWRITE) == SDMMC_OCR_CID_CSD_OVERWRITE)
1460   {
1461     return SDMMC_ERROR_CID_CSD_OVERWRITE;
1462   }
1463   else if ((response_r1 & SDMMC_OCR_WP_ERASE_SKIP) == SDMMC_OCR_WP_ERASE_SKIP)
1464   {
1465     return SDMMC_ERROR_WP_ERASE_SKIP;
1466   }
1467   else if ((response_r1 & SDMMC_OCR_CARD_ECC_DISABLED) == SDMMC_OCR_CARD_ECC_DISABLED)
1468   {
1469     return SDMMC_ERROR_CARD_ECC_DISABLED;
1470   }
1471   else if ((response_r1 & SDMMC_OCR_ERASE_RESET) == SDMMC_OCR_ERASE_RESET)
1472   {
1473     return SDMMC_ERROR_ERASE_RESET;
1474   }
1475   else if ((response_r1 & SDMMC_OCR_AKE_SEQ_ERROR) == SDMMC_OCR_AKE_SEQ_ERROR)
1476   {
1477     return SDMMC_ERROR_AKE_SEQ_ERR;
1478   }
1479   else
1480   {
1481     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1482   }
1483 }
1484 
1485 /**
1486   * @brief  Checks for error conditions for R2 (CID or CSD) response.
1487   * @param  hsd: SD handle
1488   * @retval SD Card error state
1489   */
SDMMC_GetCmdResp2(SDMMC_TypeDef * SDMMCx)1490 uint32_t SDMMC_GetCmdResp2(SDMMC_TypeDef *SDMMCx)
1491 {
1492   uint32_t sta_reg;
1493   /* 8 is the number of required instructions cycles for the below loop statement.
1494   The SDMMC_CMDTIMEOUT is expressed in ms */
1495   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1496 
1497   do
1498   {
1499     if (count-- == 0U)
1500     {
1501       return SDMMC_ERROR_TIMEOUT;
1502     }
1503     sta_reg = SDMMCx->STA;
1504   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1505            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1506 
1507   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1508   {
1509     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1510 
1511     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1512   }
1513   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1514   {
1515     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1516 
1517     return SDMMC_ERROR_CMD_CRC_FAIL;
1518   }
1519   else
1520   {
1521     /* No error flag set */
1522     /* Clear all the static flags */
1523     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1524   }
1525 
1526   return SDMMC_ERROR_NONE;
1527 }
1528 
1529 /**
1530   * @brief  Checks for error conditions for R3 (OCR) response.
1531   * @param  hsd: SD handle
1532   * @retval SD Card error state
1533   */
SDMMC_GetCmdResp3(SDMMC_TypeDef * SDMMCx)1534 uint32_t SDMMC_GetCmdResp3(SDMMC_TypeDef *SDMMCx)
1535 {
1536   uint32_t sta_reg;
1537   /* 8 is the number of required instructions cycles for the below loop statement.
1538   The SDMMC_CMDTIMEOUT is expressed in ms */
1539   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1540 
1541   do
1542   {
1543     if (count-- == 0U)
1544     {
1545       return SDMMC_ERROR_TIMEOUT;
1546     }
1547     sta_reg = SDMMCx->STA;
1548   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1549            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1550 
1551   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1552   {
1553     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1554 
1555     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1556   }
1557   else
1558   {
1559     /* Clear all the static flags */
1560     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1561   }
1562 
1563   return SDMMC_ERROR_NONE;
1564 }
1565 
1566 /**
1567   * @brief  Checks for error conditions for R4 response.
1568   * @param  SDMMCx: Pointer to SDMMC register base
1569   * @param  pResp: pointer to response
1570   * @retval error state
1571   */
SDMMC_GetCmdResp4(SDMMC_TypeDef * SDMMCx,uint32_t * pResp)1572 uint32_t SDMMC_GetCmdResp4(SDMMC_TypeDef *SDMMCx, uint32_t *pResp)
1573 {
1574   uint32_t sta_reg;
1575 
1576   /* 8 is the number of required instructions cycles for the below loop statement.
1577   The SDMMC_CMDTIMEOUT is expressed in ms */
1578   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1579 
1580   do
1581   {
1582     if (count-- == 0U)
1583     {
1584       return SDMMC_ERROR_TIMEOUT;
1585     }
1586     sta_reg = SDMMCx->STA;
1587   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1588            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1589 
1590   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1591   {
1592     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1593 
1594     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1595   }
1596   else
1597   {
1598     /* Clear all the static flags */
1599     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1600   }
1601 
1602   /* Clear all the static flags */
1603   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1604 
1605   /* We have received response, retrieve it.  */
1606   *pResp = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1607 
1608   return SDMMC_ERROR_NONE;
1609 }
1610 
1611 /**
1612   * @brief  Checks for error conditions for R5 (cmd52/cmd53) response.
1613   * @param  SDMMCx: Pointer to SDMMC register base
1614   * @param  SDIO_CMD: The sent command index
1615   * @param  pData: pointer to the read/write buffer needed for cmd52
1616   * @retval SDIO Card error state
1617   */
SDMMC_GetCmdResp5(SDMMC_TypeDef * SDMMCx,uint8_t SDIO_CMD,uint8_t * pData)1618 uint32_t SDMMC_GetCmdResp5(SDMMC_TypeDef *SDMMCx, uint8_t SDIO_CMD, uint8_t *pData)
1619 {
1620   uint32_t response_r5;
1621   uint32_t sta_reg;
1622 
1623   /* 8 is the number of required instructions cycles for the below loop statement.
1624   The SDMMC_CMDTIMEOUT is expressed in ms */
1625   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1626 
1627   do
1628   {
1629     if (count-- == 0U)
1630     {
1631       return SDMMC_ERROR_TIMEOUT;
1632     }
1633     sta_reg = SDMMCx->STA;
1634   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1635            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1636 
1637   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1638   {
1639     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1640 
1641     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1642   }
1643   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1644   {
1645     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1646 
1647     return SDMMC_ERROR_CMD_CRC_FAIL;
1648   }
1649   else
1650   {
1651     /* Nothing to do */
1652   }
1653 
1654   /* Check response received is of desired command */
1655   if (SDMMC_GetCommandResponse(SDMMCx) != SDIO_CMD)
1656   {
1657     return SDMMC_ERROR_CMD_CRC_FAIL;
1658   }
1659 
1660   /* Clear all the static flags */
1661   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1662 
1663   /* We have received response, retrieve it.  */
1664   response_r5 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1665 
1666   if ((response_r5 & SDMMC_SDIO_R5_ERRORBITS) == SDMMC_ALLZERO)
1667   {
1668     /* we only want 8 bit read or write data and the 8 bit response flags are masked in the data pointer */
1669     if (pData != NULL)
1670     {
1671       *pData = (uint8_t)(response_r5 & 0xFFU);
1672     }
1673 
1674     return SDMMC_ERROR_NONE;
1675   }
1676   else if ((response_r5 & SDMMC_SDIO_R5_OUT_OF_RANGE) == SDMMC_SDIO_R5_OUT_OF_RANGE)
1677   {
1678     return SDMMC_ERROR_ADDR_OUT_OF_RANGE;
1679   }
1680   else if ((response_r5 & SDMMC_SDIO_R5_INVALID_FUNCTION_NUMBER) == SDMMC_SDIO_R5_INVALID_FUNCTION_NUMBER)
1681   {
1682     return SDMMC_ERROR_INVALID_PARAMETER;
1683   }
1684   else if ((response_r5 & SDMMC_SDIO_R5_ILLEGAL_CMD) == SDMMC_SDIO_R5_ILLEGAL_CMD)
1685   {
1686     return SDMMC_ERROR_ILLEGAL_CMD;
1687   }
1688   else if ((response_r5 & SDMMC_SDIO_R5_COM_CRC_FAILED) == SDMMC_SDIO_R5_COM_CRC_FAILED)
1689   {
1690     return SDMMC_ERROR_COM_CRC_FAILED;
1691   }
1692   else
1693   {
1694     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1695   }
1696 }
1697 
1698 /**
1699   * @brief  Checks for error conditions for R6 (RCA) response.
1700   * @param  hsd: SD handle
1701   * @param  SD_CMD: The sent command index
1702   * @param  pRCA: Pointer to the variable that will contain the SD card relative
1703   *         address RCA
1704   * @retval SD Card error state
1705   */
SDMMC_GetCmdResp6(SDMMC_TypeDef * SDMMCx,uint8_t SD_CMD,uint16_t * pRCA)1706 uint32_t SDMMC_GetCmdResp6(SDMMC_TypeDef *SDMMCx, uint8_t SD_CMD, uint16_t *pRCA)
1707 {
1708   uint32_t response_r1;
1709   uint32_t sta_reg;
1710 
1711   /* 8 is the number of required instructions cycles for the below loop statement.
1712   The SDMMC_CMDTIMEOUT is expressed in ms */
1713   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1714 
1715   do
1716   {
1717     if (count-- == 0U)
1718     {
1719       return SDMMC_ERROR_TIMEOUT;
1720     }
1721     sta_reg = SDMMCx->STA;
1722   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1723            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1724 
1725   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1726   {
1727     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1728 
1729     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1730   }
1731   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1732   {
1733     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1734 
1735     return SDMMC_ERROR_CMD_CRC_FAIL;
1736   }
1737   else
1738   {
1739     /* Nothing to do */
1740   }
1741 
1742   /* Check response received is of desired command */
1743   if (SDMMC_GetCommandResponse(SDMMCx) != SD_CMD)
1744   {
1745     return SDMMC_ERROR_CMD_CRC_FAIL;
1746   }
1747 
1748   /* Clear all the static flags */
1749   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
1750 
1751   /* We have received response, retrieve it.  */
1752   response_r1 = SDMMC_GetResponse(SDMMCx, SDMMC_RESP1);
1753 
1754   if ((response_r1 & (SDMMC_R6_GENERAL_UNKNOWN_ERROR | SDMMC_R6_ILLEGAL_CMD |
1755                       SDMMC_R6_COM_CRC_FAILED)) == SDMMC_ALLZERO)
1756   {
1757     *pRCA = (uint16_t)(response_r1 >> 16);
1758 
1759     return SDMMC_ERROR_NONE;
1760   }
1761   else if ((response_r1 & SDMMC_R6_ILLEGAL_CMD) == SDMMC_R6_ILLEGAL_CMD)
1762   {
1763     return SDMMC_ERROR_ILLEGAL_CMD;
1764   }
1765   else if ((response_r1 & SDMMC_R6_COM_CRC_FAILED) == SDMMC_R6_COM_CRC_FAILED)
1766   {
1767     return SDMMC_ERROR_COM_CRC_FAILED;
1768   }
1769   else
1770   {
1771     return SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
1772   }
1773 }
1774 
1775 /**
1776   * @brief  Checks for error conditions for R7 response.
1777   * @param  hsd: SD handle
1778   * @retval SD Card error state
1779   */
SDMMC_GetCmdResp7(SDMMC_TypeDef * SDMMCx)1780 uint32_t SDMMC_GetCmdResp7(SDMMC_TypeDef *SDMMCx)
1781 {
1782   uint32_t sta_reg;
1783   /* 8 is the number of required instructions cycles for the below loop statement.
1784   The SDMMC_CMDTIMEOUT is expressed in ms */
1785   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
1786 
1787   do
1788   {
1789     if (count-- == 0U)
1790     {
1791       return SDMMC_ERROR_TIMEOUT;
1792     }
1793     sta_reg = SDMMCx->STA;
1794   } while (((sta_reg & (SDMMC_FLAG_CCRCFAIL | SDMMC_FLAG_CMDREND | SDMMC_FLAG_CTIMEOUT)) == 0U) ||
1795            ((sta_reg & SDMMC_FLAG_CMDACT) != 0U));
1796 
1797   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT))
1798   {
1799     /* Card is not SD V2.0 compliant */
1800     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CTIMEOUT);
1801 
1802     return SDMMC_ERROR_CMD_RSP_TIMEOUT;
1803   }
1804 
1805   else if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL))
1806   {
1807     /* Card is not SD V2.0 compliant */
1808     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CCRCFAIL);
1809 
1810     return SDMMC_ERROR_CMD_CRC_FAIL;
1811   }
1812   else
1813   {
1814     /* Nothing to do */
1815   }
1816 
1817   if (__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDREND))
1818   {
1819     /* Card is SD V2.0 compliant */
1820     __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_FLAG_CMDREND);
1821   }
1822 
1823   return SDMMC_ERROR_NONE;
1824 
1825 }
1826 
1827 /**
1828   * @}
1829   */
1830 
1831 
1832 /** @defgroup HAL_SDMMC_LL_Group6 Linked List functions
1833   *  @brief   Linked List management functions
1834   *
1835 @verbatim
1836  ===============================================================================
1837                    ##### Linked List management functions #####
1838  ===============================================================================
1839     [..]
1840     This subsection provides a set of functions allowing to manage the needed functions.
1841 
1842 @endverbatim
1843   * @{
1844   */
1845 
1846 /**
1847   * @brief  Build new Linked List node.
1848   * @param  pNode: Pointer to new node to add.
1849   * @param  pNodeConf: Pointer to configuration parameters for new node to add.
1850   * @retval Error status
1851   */
SDMMC_DMALinkedList_BuildNode(SDMMC_DMALinkNodeTypeDef * pNode,const SDMMC_DMALinkNodeConfTypeDef * pNodeConf)1852 uint32_t SDMMC_DMALinkedList_BuildNode(SDMMC_DMALinkNodeTypeDef *pNode, const SDMMC_DMALinkNodeConfTypeDef *pNodeConf)
1853 {
1854 
1855   if ((pNode == NULL) || (pNodeConf == NULL))
1856   {
1857     return SDMMC_ERROR_INVALID_PARAMETER;
1858   }
1859   /* Configure the Link Node registers*/
1860   pNode->IDMABASER = pNodeConf->BufferAddress;
1861   pNode->IDMABSIZE = pNodeConf->BufferSize;
1862   pNode->IDMALAR   = SDMMC_IDMALAR_ULS | SDMMC_IDMALAR_ABR;
1863 
1864   return SDMMC_ERROR_NONE;
1865 }
1866 
1867 /**
1868   * @brief  Insert new Linked List node.
1869   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
1870   * @param  pPrevNode: Pointer to previous node .
1871   * @param  pNewNode: Pointer to new node to add.
1872   * @retval Error status
1873   */
SDMMC_DMALinkedList_InsertNode(SDMMC_DMALinkedListTypeDef * pLinkedList,SDMMC_DMALinkNodeTypeDef * pPrevNode,SDMMC_DMALinkNodeTypeDef * pNode)1874 uint32_t SDMMC_DMALinkedList_InsertNode(SDMMC_DMALinkedListTypeDef *pLinkedList, SDMMC_DMALinkNodeTypeDef *pPrevNode,
1875                                         SDMMC_DMALinkNodeTypeDef *pNode)
1876 {
1877   uint32_t link_list_offset;
1878   uint32_t node_address = (uint32_t) pNode;
1879 
1880   /* First Node */
1881   if (pLinkedList->NodesCounter == 0U)
1882   {
1883 
1884     pLinkedList->pHeadNode = pNode;
1885     pLinkedList->pTailNode = pNode;
1886     pLinkedList->NodesCounter = 1U;
1887 
1888   }
1889   else if (pPrevNode == pLinkedList->pTailNode)
1890   {
1891     if (pNode <= pLinkedList->pHeadNode)
1892     {
1893       /* Node Address should greater than Head Node Address*/
1894       return SDMMC_ERROR_INVALID_PARAMETER;
1895     }
1896 
1897     /*Last Node, no next node */
1898     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_ULA, 0U);
1899 
1900     /*link Prev node with new one */
1901     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_ULA, SDMMC_IDMALAR_ULA);
1902     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_IDMALA, (node_address - (uint32_t)pLinkedList->pHeadNode));
1903 
1904     pLinkedList->NodesCounter ++;
1905     pLinkedList->pTailNode = pNode;
1906 
1907   }
1908   else
1909   {
1910 
1911     if (pNode <= pLinkedList->pHeadNode)
1912     {
1913       /* Node Address should greater than Head Node Address*/
1914       return SDMMC_ERROR_INVALID_PARAMETER;
1915     }
1916 
1917     /*link New node with Next one */
1918     link_list_offset = pNode->IDMALAR;
1919     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_IDMALA, link_list_offset);
1920 
1921     /*link Prev node with new one */
1922     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_ULA, SDMMC_IDMALAR_ULA);
1923     MODIFY_REG(pPrevNode->IDMALAR, SDMMC_IDMALAR_IDMALA, (node_address - (uint32_t)pLinkedList->pHeadNode));
1924 
1925     pLinkedList->NodesCounter ++;
1926 
1927   }
1928   return SDMMC_ERROR_NONE;
1929 }
1930 
1931 /**
1932   * @brief  Remove  node from the Linked List.
1933   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
1934   * @param  pNode: Pointer to new node to add.
1935   * @retval Error status
1936    */
SDMMC_DMALinkedList_RemoveNode(SDMMC_DMALinkedListTypeDef * pLinkedList,SDMMC_DMALinkNodeTypeDef * pNode)1937 uint32_t SDMMC_DMALinkedList_RemoveNode(SDMMC_DMALinkedListTypeDef *pLinkedList, SDMMC_DMALinkNodeTypeDef *pNode)
1938 {
1939   uint32_t count = 0U;
1940   uint32_t linked_list_offset;
1941   SDMMC_DMALinkNodeTypeDef *prev_node = NULL;
1942   SDMMC_DMALinkNodeTypeDef *curr_node ;
1943 
1944   /* First Node */
1945   if (pLinkedList->NodesCounter == 0U)
1946   {
1947 
1948     return SDMMC_ERROR_INVALID_PARAMETER;
1949   }
1950   else
1951   {
1952     curr_node = pLinkedList->pHeadNode;
1953     while ((curr_node != pNode) && (count <= pLinkedList->NodesCounter))
1954     {
1955       prev_node = curr_node;
1956       curr_node = (SDMMC_DMALinkNodeTypeDef *)((prev_node->IDMALAR & SDMMC_IDMALAR_IDMALA) +
1957                                                (uint32_t)pLinkedList->pHeadNode);
1958       count++;
1959     }
1960 
1961     if ((count == 0U) || (count > pLinkedList->NodesCounter))
1962     {
1963       /* Node not found in the linked list */
1964       return SDMMC_ERROR_INVALID_PARAMETER;
1965     }
1966 
1967     pLinkedList->NodesCounter--;
1968 
1969     if (pLinkedList->NodesCounter == 0U)
1970     {
1971       pLinkedList->pHeadNode = 0U;
1972       pLinkedList->pTailNode = 0U;
1973     }
1974     else
1975     {
1976       /*link prev node with next one */
1977       linked_list_offset = curr_node->IDMALAR;
1978       MODIFY_REG(prev_node->IDMALAR, SDMMC_IDMALAR_IDMALA, linked_list_offset);
1979       /* Configure the new Link Node registers*/
1980       pNode->IDMALAR    |= linked_list_offset;
1981 
1982       pLinkedList->pTailNode = prev_node;
1983     }
1984   }
1985   return SDMMC_ERROR_NONE;
1986 }
1987 
1988 /**
1989   * @brief  Lock Linked List Node
1990   * @param  pNode: Pointer to node to lock.
1991   * @retval Error status
1992 
1993   */
SDMMC_DMALinkedList_LockNode(SDMMC_DMALinkNodeTypeDef * pNode)1994 uint32_t SDMMC_DMALinkedList_LockNode(SDMMC_DMALinkNodeTypeDef *pNode)
1995 {
1996 
1997   if (pNode == NULL)
1998   {
1999     return SDMMC_ERROR_INVALID_PARAMETER;
2000   }
2001 
2002   MODIFY_REG(pNode->IDMALAR, SDMMC_IDMALAR_ABR, 0U);
2003 
2004   return SDMMC_ERROR_NONE;
2005 }
2006 
2007 /**
2008   * @brief  Unlock Linked List Node
2009   * @param  pNode: Pointer to node to unlock.
2010   * @retval Error status
2011 
2012   */
SDMMC_DMALinkedList_UnlockNode(SDMMC_DMALinkNodeTypeDef * pNode)2013 uint32_t SDMMC_DMALinkedList_UnlockNode(SDMMC_DMALinkNodeTypeDef *pNode)
2014 {
2015 
2016   if (pNode == NULL)
2017   {
2018     return SDMMC_ERROR_INVALID_PARAMETER;
2019   }
2020 
2021   MODIFY_REG(pNode->IDMALAR, SDMMC_IDMALAR_ABR, SDMMC_IDMALAR_ABR);
2022 
2023   return SDMMC_ERROR_NONE;
2024 }
2025 
2026 /**
2027   * @brief  Enable Linked List circular mode
2028   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
2029   * @retval Error status
2030 
2031   */
SDMMC_DMALinkedList_EnableCircularMode(SDMMC_DMALinkedListTypeDef * pLinkedList)2032 uint32_t SDMMC_DMALinkedList_EnableCircularMode(SDMMC_DMALinkedListTypeDef *pLinkedList)
2033 {
2034 
2035   if (pLinkedList == NULL)
2036   {
2037     return SDMMC_ERROR_INVALID_PARAMETER;
2038   }
2039 
2040   MODIFY_REG(pLinkedList->pTailNode->IDMALAR, SDMMC_IDMALAR_ULA | SDMMC_IDMALAR_IDMALA, SDMMC_IDMALAR_ULA);
2041 
2042   return SDMMC_ERROR_NONE;
2043 }
2044 
2045 /**
2046   * @brief  Disable DMA Linked List Circular mode
2047   * @param  pLinkedList: Pointer to the linkedlist that contains transfer nodes
2048   * @retval Error status
2049    */
SDMMC_DMALinkedList_DisableCircularMode(SDMMC_DMALinkedListTypeDef * pLinkedList)2050 uint32_t SDMMC_DMALinkedList_DisableCircularMode(SDMMC_DMALinkedListTypeDef *pLinkedList)
2051 {
2052 
2053   if (pLinkedList == NULL)
2054   {
2055     return SDMMC_ERROR_INVALID_PARAMETER;
2056   }
2057 
2058   MODIFY_REG(pLinkedList->pTailNode->IDMALAR, SDMMC_IDMALAR_ULA, 0U);
2059 
2060   return SDMMC_ERROR_NONE;
2061 }
2062 
2063 /**
2064   * @}
2065   */
2066 
2067 
2068 /* Private function ----------------------------------------------------------*/
2069 /** @addtogroup SD_Private_Functions
2070   * @{
2071   */
2072 
2073 /**
2074   * @brief  Checks for error conditions for CMD0.
2075   * @param  hsd: SD handle
2076   * @retval SD Card error state
2077   */
SDMMC_GetCmdError(SDMMC_TypeDef * SDMMCx)2078 static uint32_t SDMMC_GetCmdError(SDMMC_TypeDef *SDMMCx)
2079 {
2080   /* 8 is the number of required instructions cycles for the below loop statement.
2081   The SDMMC_CMDTIMEOUT is expressed in ms */
2082   uint32_t count = SDMMC_CMDTIMEOUT * (SystemCoreClock / 8U / 1000U);
2083 
2084   do
2085   {
2086     if (count-- == 0U)
2087     {
2088       return SDMMC_ERROR_TIMEOUT;
2089     }
2090 
2091   } while (!__SDMMC_GET_FLAG(SDMMCx, SDMMC_FLAG_CMDSENT));
2092 
2093   /* Clear all the static flags */
2094   __SDMMC_CLEAR_FLAG(SDMMCx, SDMMC_STATIC_CMD_FLAGS);
2095 
2096   return SDMMC_ERROR_NONE;
2097 }
2098 
2099 /**
2100   * @}
2101   */
2102 
2103 #endif /* HAL_SD_MODULE_ENABLED || HAL_MMC_MODULE_ENABLED */
2104 #endif /* SDMMC1 || SDMMC2 */
2105 /**
2106   * @}
2107   */
2108 
2109 /**
2110   * @}
2111   */
2112