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