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