Subversion Repositories DashDisplay

Rev

Rev 61 | Details | Compare with Previous | Last modification | View Log | RSS feed

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