source: S-port/trunk/Drivers/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_sdmmc.c

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