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