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