Subversion Repositories DashDisplay

Rev

Rev 56 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
56 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
  @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) 2018 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 "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
static uint32_t SDMMC_GetCmdResp1(SDIO_TypeDef *SDIOx, uint8_t SD_CMD, uint32_t Timeout);
181
static uint32_t SDMMC_GetCmdResp2(SDIO_TypeDef *SDIOx);
182
static uint32_t SDMMC_GetCmdResp3(SDIO_TypeDef *SDIOx);
183
static uint32_t SDMMC_GetCmdResp7(SDIO_TypeDef *SDIOx);
184
static 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
  */
212
HAL_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
  */
265
uint32_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
  */
277
HAL_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
  */
309
HAL_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
  */
326
HAL_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
  */
343
uint32_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
  */
356
HAL_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
  */
386
uint8_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
  */
403
uint32_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
  */
424
HAL_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
  */
459
uint32_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
  */
469
uint32_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
  */
483
HAL_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
/**
61 mjames 514
  * @brief  Send the Data Block Length command and check the response
56 mjames 515
  * @param  SDIOx: Pointer to SDIO register base
516
  * @retval HAL status
517
  */
518
uint32_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
  */
542
uint32_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
  */
566
uint32_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
  */
590
uint32_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
  */
614
uint32_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
  */
638
uint32_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
  */
662
uint32_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
  */
686
uint32_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
  */
710
uint32_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
  */
734
uint32_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
  */
758
uint32_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
  */
783
uint32_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
  */
807
uint32_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
  */
830
uint32_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
  */
861
uint32_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
  */
889
uint32_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
  */
913
uint32_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
  */
936
uint32_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
  */
960
uint32_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
  */
985
uint32_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
  */
1010
uint32_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
  */
1035
uint32_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
  */
1058
uint32_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
  */
1083
uint32_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
/**
61 mjames 1102
  * @brief  Checks switchable function and switch card function. SDMMC_CMD_HS_SWITCH command
56 mjames 1103
  * @param  SDIOx: Pointer to SDIO register base
1104
  * @parame Argument: Argument used for the command
1105
  * @retval HAL status
1106
  */
1107
uint32_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 */
61 mjames 1114
  sdmmc_cmdinit.Argument         = Argument; /* SDMMC_SDR25_SWITCH_PATTERN */
56 mjames 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
  */
1141
static 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
  */
1168
static 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
  */
1303
static 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
  */
1347
static 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
  */
1387
static 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
  */
1460
static 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
/**
61 mjames 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
  */
1512
uint32_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
/**
56 mjames 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****/