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