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