Subversion Repositories LedShow

Rev

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

Rev Author Line No. Line
2 mjames 1
/**
2
  ******************************************************************************
3
  * @file    stm32f1xx_hal_mmc.c
4
  * @author  MCD Application Team
5
  * @brief   MMC card HAL module driver.
9 mjames 6
  *          This file provides firmware functions to manage the following
2 mjames 7
  *          functionalities of the Secure Digital (MMC) peripheral:
8
  *           + Initialization and de-initialization functions
9
  *           + IO operation functions
9 mjames 10
  *           + Peripheral Control functions
2 mjames 11
  *           + MMC card Control functions
9 mjames 12
  *
2 mjames 13
  @verbatim
14
  ==============================================================================
15
                        ##### How to use this driver #####
16
  ==============================================================================
17
  [..]
9 mjames 18
    This driver implements a high level communication layer for read and write from/to
19
    this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
20
    the user in HAL_MMC_MspInit() function (MSP layer).
21
    Basically, the MSP layer configuration should be the same as we provide in the
2 mjames 22
    examples.
23
    You can easily tailor this configuration according to hardware resources.
24
 
25
  [..]
9 mjames 26
    This driver is a generic layered driver for SDMMC memories which uses the HAL
27
    SDMMC driver functions to interface with MMC and eMMC cards devices.
2 mjames 28
    It is used as follows:
9 mjames 29
 
2 mjames 30
    (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
9 mjames 31
        (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
2 mjames 32
        (##) SDMMC pins configuration for MMC card
9 mjames 33
            (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
2 mjames 34
            (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
35
                  and according to your pin assignment;
36
        (##) DMA Configuration if you need to use DMA process (HAL_MMC_ReadBlocks_DMA()
37
             and HAL_MMC_WriteBlocks_DMA() APIs).
38
            (+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
39
            (+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
40
        (##) NVIC configuration if you need to use interrupt process when using DMA transfer.
9 mjames 41
            (+++) Configure the SDMMC and DMA interrupt priorities using function HAL_NVIC_SetPriority();
42
                  DMA priority is superior to SDMMC's priority
2 mjames 43
            (+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ()
44
            (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
45
                  and __HAL_MMC_DISABLE_IT() inside the communication process.
46
            (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
47
                  and __HAL_MMC_CLEAR_IT()
48
        (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
49
             and HAL_MMC_WriteBlocks_IT() APIs).
9 mjames 50
            (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
2 mjames 51
            (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
9 mjames 52
            (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
2 mjames 53
                  and __HAL_MMC_DISABLE_IT() inside the communication process.
54
            (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
55
                  and __HAL_MMC_CLEAR_IT()
9 mjames 56
    (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
2 mjames 57
 
9 mjames 58
 
2 mjames 59
  *** MMC Card Initialization and configuration ***
9 mjames 60
  ================================================
2 mjames 61
  [..]
9 mjames 62
    To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
63
    SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
2 mjames 64
    This function provide the following operations:
65
 
66
    (#) Initialize the SDMMC peripheral interface with defaullt configuration.
9 mjames 67
        The initialization process is done at 400KHz. You can change or adapt
68
        this frequency by adjusting the "ClockDiv" field.
2 mjames 69
        The MMC Card frequency (SDMMC_CK) is computed as follows:
9 mjames 70
 
2 mjames 71
           SDMMC_CK = SDMMCCLK / (ClockDiv + 2)
9 mjames 72
 
73
        In initialization mode and according to the MMC Card standard,
2 mjames 74
        make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
75
 
9 mjames 76
        This phase of initialization is done through SDMMC_Init() and
2 mjames 77
        SDMMC_PowerState_ON() SDMMC low level APIs.
78
 
79
    (#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
9 mjames 80
        This phase allows the card initialization and identification
2 mjames 81
        and check the MMC Card type (Standard Capacity or High Capacity)
82
        The initialization flow is compatible with MMC standard.
83
 
9 mjames 84
        This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
2 mjames 85
        of plug-off plug-in.
86
 
9 mjames 87
    (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
2 mjames 88
        frequency is set to 24MHz. You can change or adapt this frequency by adjusting
89
        the "ClockDiv" field.
9 mjames 90
        In transfer mode and according to the MMC Card standard, make sure that the
2 mjames 91
        SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
9 mjames 92
        To be able to use a frequency higher than 24MHz, you should use the SDMMC
93
        peripheral in bypass mode. Refer to the corresponding reference manual
2 mjames 94
        for more details.
9 mjames 95
 
2 mjames 96
    (#) Select the corresponding MMC Card according to the address read with the step 2.
9 mjames 97
 
2 mjames 98
    (#) Configure the MMC Card in wide bus mode: 4-bits data.
9 mjames 99
 
2 mjames 100
  *** MMC Card Read operation ***
101
  ==============================
9 mjames 102
  [..]
103
    (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
104
        This function support only 512-bytes block length (the block size should be
105
        chosen as 512 bytes).
106
        You can choose either one block read operation or multiple block read operation
2 mjames 107
        by adjusting the "NumberOfBlocks" parameter.
108
        After this, you have to ensure that the transfer is done correctly. The check is done
109
        through HAL_MMC_GetCardState() function for MMC card state.
110
 
111
    (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
9 mjames 112
        This function support only 512-bytes block length (the block size should be
113
        chosen as 512 bytes).
114
        You can choose either one block read operation or multiple block read operation
2 mjames 115
        by adjusting the "NumberOfBlocks" parameter.
116
        After this, you have to ensure that the transfer is done correctly. The check is done
117
        through HAL_MMC_GetCardState() function for MMC card state.
118
        You could also check the DMA transfer process through the MMC Rx interrupt event.
119
 
120
    (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
121
        This function allows the read of 512 bytes blocks.
122
        You can choose either one block read operation or multiple block read operation
123
        by adjusting the "NumberOfBlocks" parameter.
124
        After this, you have to ensure that the transfer is done correctly. The check is done
125
        through HAL_MMC_GetCardState() function for MMC card state.
126
        You could also check the IT transfer process through the MMC Rx interrupt event.
9 mjames 127
 
2 mjames 128
  *** MMC Card Write operation ***
9 mjames 129
  ===============================
130
  [..]
131
    (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
132
        This function support only 512-bytes block length (the block size should be
133
        chosen as 512 bytes).
134
        You can choose either one block read operation or multiple block read operation
2 mjames 135
        by adjusting the "NumberOfBlocks" parameter.
136
        After this, you have to ensure that the transfer is done correctly. The check is done
137
        through HAL_MMC_GetCardState() function for MMC card state.
138
 
139
    (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
9 mjames 140
        This function support only 512-bytes block length (the block size should be
141
        chosen as 512 byte).
142
        You can choose either one block read operation or multiple block read operation
2 mjames 143
        by adjusting the "NumberOfBlocks" parameter.
144
        After this, you have to ensure that the transfer is done correctly. The check is done
145
        through HAL_MMC_GetCardState() function for MMC card state.
146
        You could also check the DMA transfer process through the MMC Tx interrupt event.  
147
 
148
    (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
149
        This function allows the read of 512 bytes blocks.
150
        You can choose either one block read operation or multiple block read operation
151
        by adjusting the "NumberOfBlocks" parameter.
152
        After this, you have to ensure that the transfer is done correctly. The check is done
153
        through HAL_MMC_GetCardState() function for MMC card state.
154
        You could also check the IT transfer process through the MMC Tx interrupt event.
155
 
156
  *** MMC card information ***
157
  ===========================
158
  [..]
159
    (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
160
        It returns useful information about the MMC card such as block size, card type,
161
        block number ...
162
 
163
  *** MMC card CSD register ***
164
  ============================
165
  [..]
166
    (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
167
        Some of the CSD parameters are useful for card initialization and identification.
168
 
169
  *** MMC card CID register ***
170
  ============================
171
  [..]
172
    (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
173
        Some of the CID parameters are useful for card initialization and identification.
174
 
175
  *** MMC HAL driver macros list ***
176
  ==================================
177
  [..]
178
    Below the list of most used macros in MMC HAL driver.
9 mjames 179
 
2 mjames 180
    (+) __HAL_MMC_ENABLE : Enable the MMC device
181
    (+) __HAL_MMC_DISABLE : Disable the MMC device
182
    (+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer
183
    (+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer
184
    (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
185
    (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
186
    (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
187
    (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
9 mjames 188
 
189
  [..]
190
    (@) You can refer to the MMC HAL driver header file for more useful macros
191
 
192
  *** Callback registration ***
193
  =============================================
194
  [..]
195
    The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
196
    allows the user to configure dynamically the driver callbacks.
197
 
198
    Use Functions @ref HAL_MMC_RegisterCallback() to register a user callback,
199
    it allows to register following callbacks:
200
      (+) TxCpltCallback : callback when a transmission transfer is completed.
201
      (+) RxCpltCallback : callback when a reception transfer is completed.
202
      (+) ErrorCallback : callback when error occurs.
203
      (+) AbortCpltCallback : callback when abort is completed.
204
      (+) MspInitCallback    : MMC MspInit.
205
      (+) MspDeInitCallback  : MMC MspDeInit.
206
    This function takes as parameters the HAL peripheral handle, the Callback ID
207
    and a pointer to the user callback function.
208
 
209
    Use function @ref HAL_MMC_UnRegisterCallback() to reset a callback to the default
210
    weak (surcharged) function. It allows to reset following callbacks:
211
      (+) TxCpltCallback : callback when a transmission transfer is completed.
212
      (+) RxCpltCallback : callback when a reception transfer is completed.
213
      (+) ErrorCallback : callback when error occurs.
214
      (+) AbortCpltCallback : callback when abort is completed.
215
      (+) MspInitCallback    : MMC MspInit.
216
      (+) MspDeInitCallback  : MMC MspDeInit.
217
    This function) takes as parameters the HAL peripheral handle and the Callback ID.
218
 
219
    By default, after the @ref HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
220
    all callbacks are reset to the corresponding legacy weak (surcharged) functions.
221
    Exception done for MspInit and MspDeInit callbacks that are respectively
222
    reset to the legacy weak (surcharged) functions in the @ref HAL_MMC_Init
223
    and @ref  HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
224
    If not, MspInit or MspDeInit are not null, the @ref HAL_MMC_Init and @ref HAL_MMC_DeInit
225
    keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
226
 
227
    Callbacks can be registered/unregistered in READY state only.
228
    Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
229
    in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
230
    during the Init/DeInit.
231
    In that case first register the MspInit/MspDeInit user callbacks
232
    using @ref HAL_MMC_RegisterCallback before calling @ref HAL_MMC_DeInit
233
    or @ref HAL_MMC_Init function.
234
 
235
    When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
236
    not defined, the callback registering feature is not available
237
    and weak (surcharged) callbacks are used.
238
 
2 mjames 239
  @endverbatim
240
  ******************************************************************************
241
  * @attention
242
  *
9 mjames 243
  * <h2><center>&copy; Copyright (c) 2018 STMicroelectronics.
244
  * All rights reserved.</center></h2>
2 mjames 245
  *
9 mjames 246
  * This software component is licensed by ST under BSD 3-Clause license,
247
  * the "License"; You may not use this file except in compliance with the
248
  * License. You may obtain a copy of the License at:
249
  *                       opensource.org/licenses/BSD-3-Clause
2 mjames 250
  *
251
  ******************************************************************************
9 mjames 252
  */
2 mjames 253
 
254
/* Includes ------------------------------------------------------------------*/
255
#include "stm32f1xx_hal.h"
256
 
257
/** @addtogroup STM32F1xx_HAL_Driver
258
  * @{
259
  */
260
 
9 mjames 261
/** @defgroup MMC MMC
262
  * @brief MMC HAL module driver
2 mjames 263
  * @{
264
  */
265
 
266
#ifdef HAL_MMC_MODULE_ENABLED
267
 
9 mjames 268
#if defined(SDIO)
2 mjames 269
 
270
/* Private typedef -----------------------------------------------------------*/
271
/* Private define ------------------------------------------------------------*/
272
/** @addtogroup MMC_Private_Defines
273
  * @{
274
  */
9 mjames 275
 
2 mjames 276
/**
277
  * @}
278
  */
9 mjames 279
 
2 mjames 280
/* Private macro -------------------------------------------------------------*/
281
/* Private variables ---------------------------------------------------------*/
282
/* Private function prototypes -----------------------------------------------*/
283
/* Private functions ---------------------------------------------------------*/
284
/** @defgroup MMC_Private_Functions MMC Private Functions
285
  * @{
286
  */
287
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
9 mjames 288
static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
2 mjames 289
static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
9 mjames 290
static void     MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
291
static void     MMC_Write_IT(MMC_HandleTypeDef *hmmc);
292
static void     MMC_Read_IT(MMC_HandleTypeDef *hmmc);
293
static void     MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma);
294
static void     MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
295
static void     MMC_DMAError(DMA_HandleTypeDef *hdma);
296
static void     MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
297
static void     MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
2 mjames 298
/**
299
  * @}
300
  */
301
/* Exported functions --------------------------------------------------------*/
302
/** @addtogroup MMC_Exported_Functions
303
  * @{
304
  */
305
 
306
/** @addtogroup MMC_Exported_Functions_Group1
9 mjames 307
 *  @brief   Initialization and de-initialization functions
2 mjames 308
 *
9 mjames 309
@verbatim
2 mjames 310
  ==============================================================================
311
          ##### Initialization and de-initialization functions #####
312
  ==============================================================================
9 mjames 313
  [..]
2 mjames 314
    This section provides functions allowing to initialize/de-initialize the MMC
315
    card device to be ready for use.
316
 
317
@endverbatim
318
  * @{
319
  */
320
 
321
/**
9 mjames 322
  * @brief  Initializes the MMC according to the specified parameters in the
2 mjames 323
            MMC_HandleTypeDef and create the associated handle.
9 mjames 324
  * @param  hmmc: Pointer to the MMC handle
2 mjames 325
  * @retval HAL status
326
  */
327
HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
328
{
329
  /* Check the MMC handle allocation */
330
  if(hmmc == NULL)
331
  {
332
    return HAL_ERROR;
333
  }
334
 
335
  /* Check the parameters */
336
  assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
337
  assert_param(IS_SDIO_CLOCK_EDGE(hmmc->Init.ClockEdge));
338
  assert_param(IS_SDIO_CLOCK_BYPASS(hmmc->Init.ClockBypass));
339
  assert_param(IS_SDIO_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
340
  assert_param(IS_SDIO_BUS_WIDE(hmmc->Init.BusWide));
341
  assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
342
  assert_param(IS_SDIO_CLKDIV(hmmc->Init.ClockDiv));
343
 
344
  if(hmmc->State == HAL_MMC_STATE_RESET)
345
  {
346
    /* Allocate lock resource and initialize it */
347
    hmmc->Lock = HAL_UNLOCKED;
9 mjames 348
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
349
    /* Reset Callback pointers in HAL_MMC_STATE_RESET only */
350
    hmmc->TxCpltCallback    = HAL_MMC_TxCpltCallback;
351
    hmmc->RxCpltCallback    = HAL_MMC_RxCpltCallback;
352
    hmmc->ErrorCallback     = HAL_MMC_ErrorCallback;
353
    hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
354
 
355
    if(hmmc->MspInitCallback == NULL)
356
    {
357
      hmmc->MspInitCallback = HAL_MMC_MspInit;
358
    }
359
 
360
    /* Init the low level hardware */
361
    hmmc->MspInitCallback(hmmc);
362
#else
2 mjames 363
    /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
364
    HAL_MMC_MspInit(hmmc);
9 mjames 365
#endif
2 mjames 366
  }
367
 
368
  hmmc->State = HAL_MMC_STATE_BUSY;
369
 
370
  /* Initialize the Card parameters */
9 mjames 371
  if(HAL_MMC_InitCard(hmmc) == HAL_ERROR)
372
  {
373
    return HAL_ERROR;
374
  }
2 mjames 375
 
376
  /* Initialize the error code */
377
  hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
9 mjames 378
 
2 mjames 379
  /* Initialize the MMC operation */
380
  hmmc->Context = MMC_CONTEXT_NONE;
9 mjames 381
 
2 mjames 382
  /* Initialize the MMC state */
383
  hmmc->State = HAL_MMC_STATE_READY;
384
 
385
  return HAL_OK;
386
}
387
 
388
/**
389
  * @brief  Initializes the MMC Card.
390
  * @param  hmmc: Pointer to MMC handle
9 mjames 391
  * @note   This function initializes the MMC card. It could be used when a card
2 mjames 392
            re-initialization is needed.
393
  * @retval HAL status
394
  */
395
HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
396
{
9 mjames 397
  uint32_t errorstate;
2 mjames 398
  MMC_InitTypeDef Init;
9 mjames 399
  HAL_StatusTypeDef status;
2 mjames 400
 
9 mjames 401
  /* Default SDIO peripheral configuration for MMC card initialization */
2 mjames 402
  Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
403
  Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
404
  Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
405
  Init.BusWide             = SDIO_BUS_WIDE_1B;
406
  Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
407
  Init.ClockDiv            = SDIO_INIT_CLK_DIV;
408
 
9 mjames 409
  /* Initialize SDIO peripheral interface with default configuration */
410
  status = SDIO_Init(hmmc->Instance, Init);
411
  if(status == HAL_ERROR)
412
  {
413
    return HAL_ERROR;
414
  }
2 mjames 415
 
9 mjames 416
  /* Disable SDIO Clock */
2 mjames 417
  __HAL_MMC_DISABLE(hmmc);
418
 
419
  /* Set Power State to ON */
9 mjames 420
  status = SDIO_PowerState_ON(hmmc->Instance);
421
  if(status == HAL_ERROR)
422
  {
423
    return HAL_ERROR;
424
  }
425
 
426
  /* Enable MMC Clock */
2 mjames 427
  __HAL_MMC_ENABLE(hmmc);
9 mjames 428
 
2 mjames 429
  /* Identify card operating voltage */
430
  errorstate = MMC_PowerON(hmmc);
431
  if(errorstate != HAL_MMC_ERROR_NONE)
432
  {
433
    hmmc->State = HAL_MMC_STATE_READY;
434
    hmmc->ErrorCode |= errorstate;
435
    return HAL_ERROR;
436
  }
437
 
438
  /* Card initialization */
439
  errorstate = MMC_InitCard(hmmc);
440
  if(errorstate != HAL_MMC_ERROR_NONE)
441
  {
442
    hmmc->State = HAL_MMC_STATE_READY;
443
    hmmc->ErrorCode |= errorstate;
444
    return HAL_ERROR;
445
  }
446
 
447
  return HAL_OK;
448
}
449
 
450
/**
451
  * @brief  De-Initializes the MMC card.
452
  * @param  hmmc: Pointer to MMC handle
453
  * @retval HAL status
454
  */
455
HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
456
{
457
  /* Check the MMC handle allocation */
458
  if(hmmc == NULL)
459
  {
460
    return HAL_ERROR;
461
  }
9 mjames 462
 
2 mjames 463
  /* Check the parameters */
464
  assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
465
 
466
  hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 467
 
468
  /* Set MMC power state to off */
2 mjames 469
  MMC_PowerOFF(hmmc);
9 mjames 470
 
471
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
472
  if(hmmc->MspDeInitCallback == NULL)
473
  {
474
    hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
475
  }
476
 
477
  /* DeInit the low level hardware */
478
  hmmc->MspDeInitCallback(hmmc);
479
#else
2 mjames 480
  /* De-Initialize the MSP layer */
481
  HAL_MMC_MspDeInit(hmmc);
9 mjames 482
#endif
483
 
2 mjames 484
  hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
485
  hmmc->State = HAL_MMC_STATE_RESET;
9 mjames 486
 
2 mjames 487
  return HAL_OK;
488
}
489
 
490
 
491
/**
492
  * @brief  Initializes the MMC MSP.
493
  * @param  hmmc: Pointer to MMC handle
494
  * @retval None
495
  */
496
__weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
497
{
498
  /* Prevent unused argument(s) compilation warning */
499
  UNUSED(hmmc);
9 mjames 500
 
2 mjames 501
  /* NOTE : This function Should not be modified, when the callback is needed,
502
            the HAL_MMC_MspInit could be implemented in the user file
503
   */
504
}
505
 
506
/**
507
  * @brief  De-Initialize MMC MSP.
508
  * @param  hmmc: Pointer to MMC handle
509
  * @retval None
510
  */
511
__weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
512
{
513
  /* Prevent unused argument(s) compilation warning */
514
  UNUSED(hmmc);
9 mjames 515
 
2 mjames 516
  /* NOTE : This function Should not be modified, when the callback is needed,
517
            the HAL_MMC_MspDeInit could be implemented in the user file
518
   */
519
}
520
 
521
/**
522
  * @}
523
  */
524
 
525
/** @addtogroup MMC_Exported_Functions_Group2
9 mjames 526
 *  @brief   Data transfer functions
2 mjames 527
 *
9 mjames 528
@verbatim
2 mjames 529
  ==============================================================================
530
                        ##### IO operation functions #####
9 mjames 531
  ==============================================================================
2 mjames 532
  [..]
9 mjames 533
    This subsection provides a set of functions allowing to manage the data
2 mjames 534
    transfer from/to MMC card.
535
 
536
@endverbatim
537
  * @{
538
  */
539
 
540
/**
9 mjames 541
  * @brief  Reads block(s) from a specified address in a card. The Data transfer
2 mjames 542
  *         is managed by polling mode.
543
  * @note   This API should be followed by a check on the card state through
544
  *         HAL_MMC_GetCardState().
545
  * @param  hmmc: Pointer to MMC handle
546
  * @param  pData: pointer to the buffer that will contain the received data
9 mjames 547
  * @param  BlockAdd: Block Address from where data is to be read
2 mjames 548
  * @param  NumberOfBlocks: Number of MMC blocks to read
549
  * @param  Timeout: Specify timeout value
550
  * @retval HAL status
551
  */
552
HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
553
{
554
  SDIO_DataInitTypeDef config;
9 mjames 555
  uint32_t errorstate;
2 mjames 556
  uint32_t tickstart = HAL_GetTick();
9 mjames 557
  uint32_t count, data, dataremaining;
558
  uint32_t add = BlockAdd;
559
  uint8_t *tempbuff = pData;
560
 
2 mjames 561
  if(NULL == pData)
562
  {
563
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
564
    return HAL_ERROR;
565
  }
9 mjames 566
 
2 mjames 567
  if(hmmc->State == HAL_MMC_STATE_READY)
568
  {
9 mjames 569
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
570
 
2 mjames 571
    if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
572
    {
573
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
574
      return HAL_ERROR;
575
    }
9 mjames 576
 
2 mjames 577
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 578
 
2 mjames 579
    /* Initialize data control register */
580
    hmmc->Instance->DCTRL = 0U;
9 mjames 581
 
582
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 583
    {
9 mjames 584
      add *= 512U;
2 mjames 585
    }
586
 
587
    /* Set Block Size for Card */
9 mjames 588
    errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
2 mjames 589
    if(errorstate != HAL_MMC_ERROR_NONE)
590
    {
591
      /* Clear all the static flags */
9 mjames 592
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 593
      hmmc->ErrorCode |= errorstate;
594
      hmmc->State = HAL_MMC_STATE_READY;
595
      return HAL_ERROR;
596
    }
9 mjames 597
 
2 mjames 598
    /* Configure the MMC DPSM (Data Path State Machine) */
599
    config.DataTimeOut   = SDMMC_DATATIMEOUT;
9 mjames 600
    config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
2 mjames 601
    config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
602
    config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
603
    config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
604
    config.DPSM          = SDIO_DPSM_ENABLE;
9 mjames 605
    (void)SDIO_ConfigData(hmmc->Instance, &config);
606
 
2 mjames 607
    /* Read block(s) in polling mode */
608
    if(NumberOfBlocks > 1U)
609
    {
610
      hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
9 mjames 611
 
612
      /* Read Multi Block command */
613
      errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
2 mjames 614
    }
615
    else
616
    {
617
      hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
9 mjames 618
 
2 mjames 619
      /* Read Single Block command */
9 mjames 620
      errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
2 mjames 621
    }
622
    if(errorstate != HAL_MMC_ERROR_NONE)
623
    {
624
      /* Clear all the static flags */
625
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
626
      hmmc->ErrorCode |= errorstate;
627
      hmmc->State = HAL_MMC_STATE_READY;
628
      return HAL_ERROR;
629
    }
9 mjames 630
 
631
    /* Poll on SDIO flags */
632
    dataremaining = config.DataLength;
633
    while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
2 mjames 634
    {
9 mjames 635
      if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U))
2 mjames 636
      {
9 mjames 637
        /* Read data from SDIO Rx FIFO */
2 mjames 638
        for(count = 0U; count < 8U; count++)
639
        {
9 mjames 640
          data = SDIO_ReadFIFO(hmmc->Instance);
641
          *tempbuff = (uint8_t)(data & 0xFFU);
642
          tempbuff++;
643
          dataremaining--;
644
          *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
645
          tempbuff++;
646
          dataremaining--;
647
          *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
648
          tempbuff++;
649
          dataremaining--;
650
          *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
651
          tempbuff++;
652
          dataremaining--;
2 mjames 653
        }
654
      }
9 mjames 655
 
656
      if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
2 mjames 657
      {
658
        /* Clear all the static flags */
659
        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
660
        hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
661
        hmmc->State= HAL_MMC_STATE_READY;
662
        return HAL_TIMEOUT;
663
      }
664
    }
9 mjames 665
 
2 mjames 666
    /* Send stop transmission command in case of multiblock read */
667
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
9 mjames 668
    {
2 mjames 669
      /* Send stop transmission command */
670
      errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
671
      if(errorstate != HAL_MMC_ERROR_NONE)
672
      {
673
        /* Clear all the static flags */
674
        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
675
        hmmc->ErrorCode |= errorstate;
676
        hmmc->State = HAL_MMC_STATE_READY;
677
        return HAL_ERROR;
678
      }
679
    }
9 mjames 680
 
2 mjames 681
    /* Get error state */
682
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
683
    {
684
      /* Clear all the static flags */
685
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
686
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
687
      hmmc->State = HAL_MMC_STATE_READY;
688
      return HAL_ERROR;
689
    }
690
    else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
691
    {
692
      /* Clear all the static flags */
693
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
694
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
695
      hmmc->State = HAL_MMC_STATE_READY;
696
      return HAL_ERROR;
697
    }
698
    else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
699
    {
700
      /* Clear all the static flags */
701
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
702
      hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
703
      hmmc->State = HAL_MMC_STATE_READY;
704
      return HAL_ERROR;
705
    }
9 mjames 706
    else
707
    {
708
      /* Nothing to do */
709
    }
710
 
2 mjames 711
    /* Empty FIFO if there is still any data */
9 mjames 712
    while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U))
2 mjames 713
    {
9 mjames 714
      data = SDIO_ReadFIFO(hmmc->Instance);
715
      *tempbuff = (uint8_t)(data & 0xFFU);
2 mjames 716
      tempbuff++;
9 mjames 717
      dataremaining--;
718
      *tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
719
      tempbuff++;
720
      dataremaining--;
721
      *tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
722
      tempbuff++;
723
      dataremaining--;
724
      *tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
725
      tempbuff++;
726
      dataremaining--;
727
 
728
      if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
2 mjames 729
      {
730
        /* Clear all the static flags */
731
        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);        
732
        hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
733
        hmmc->State= HAL_MMC_STATE_READY;
734
        return HAL_ERROR;
735
      }
736
    }
9 mjames 737
 
2 mjames 738
    /* Clear all the static flags */
9 mjames 739
    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
740
 
2 mjames 741
    hmmc->State = HAL_MMC_STATE_READY;
9 mjames 742
 
2 mjames 743
    return HAL_OK;
744
  }
745
  else
746
  {
747
    hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
748
    return HAL_ERROR;
749
  }
750
}
751
 
752
/**
753
  * @brief  Allows to write block(s) to a specified address in a card. The Data
754
  *         transfer is managed by polling mode.
755
  * @note   This API should be followed by a check on the card state through
756
  *         HAL_MMC_GetCardState().
757
  * @param  hmmc: Pointer to MMC handle
758
  * @param  pData: pointer to the buffer that will contain the data to transmit
9 mjames 759
  * @param  BlockAdd: Block Address where data will be written
2 mjames 760
  * @param  NumberOfBlocks: Number of MMC blocks to write
761
  * @param  Timeout: Specify timeout value
762
  * @retval HAL status
763
  */
764
HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
765
{
766
  SDIO_DataInitTypeDef config;
9 mjames 767
  uint32_t errorstate;
2 mjames 768
  uint32_t tickstart = HAL_GetTick();
9 mjames 769
  uint32_t count, data, dataremaining;
770
  uint32_t add = BlockAdd;
771
  uint8_t *tempbuff = pData;
772
 
2 mjames 773
  if(NULL == pData)
774
  {
775
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
776
    return HAL_ERROR;
777
  }
778
 
779
  if(hmmc->State == HAL_MMC_STATE_READY)
780
  {
9 mjames 781
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
782
 
2 mjames 783
    if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
784
    {
785
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
786
      return HAL_ERROR;
787
    }
9 mjames 788
 
2 mjames 789
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 790
 
2 mjames 791
    /* Initialize data control register */
792
    hmmc->Instance->DCTRL = 0U;
9 mjames 793
 
794
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 795
    {
9 mjames 796
      add *= 512U;
2 mjames 797
    }
9 mjames 798
 
799
    /* Set Block Size for Card */
800
    errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
2 mjames 801
    if(errorstate != HAL_MMC_ERROR_NONE)
802
    {
803
      /* Clear all the static flags */
9 mjames 804
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 805
      hmmc->ErrorCode |= errorstate;
806
      hmmc->State = HAL_MMC_STATE_READY;
807
      return HAL_ERROR;
808
    }
9 mjames 809
 
2 mjames 810
    /* Write Blocks in Polling mode */
811
    if(NumberOfBlocks > 1U)
812
    {
813
      hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
9 mjames 814
 
815
      /* Write Multi Block command */
816
      errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
2 mjames 817
    }
818
    else
819
    {
820
      hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
9 mjames 821
 
2 mjames 822
      /* Write Single Block command */
9 mjames 823
      errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
2 mjames 824
    }
825
    if(errorstate != HAL_MMC_ERROR_NONE)
826
    {
827
      /* Clear all the static flags */
9 mjames 828
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 829
      hmmc->ErrorCode |= errorstate;
830
      hmmc->State = HAL_MMC_STATE_READY;
831
      return HAL_ERROR;
832
    }
9 mjames 833
 
834
    /* Configure the MMC DPSM (Data Path State Machine) */
2 mjames 835
    config.DataTimeOut   = SDMMC_DATATIMEOUT;
9 mjames 836
    config.DataLength    = NumberOfBlocks * MMC_BLOCKSIZE;
2 mjames 837
    config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
838
    config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
839
    config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
840
    config.DPSM          = SDIO_DPSM_ENABLE;
9 mjames 841
    (void)SDIO_ConfigData(hmmc->Instance, &config);
842
 
2 mjames 843
    /* Write block(s) in polling mode */
9 mjames 844
    dataremaining = config.DataLength;
2 mjames 845
    while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
846
    {
9 mjames 847
      if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U))
2 mjames 848
      {
849
        /* Write data to SDIO Tx FIFO */
850
        for(count = 0U; count < 8U; count++)
851
        {
9 mjames 852
          data = (uint32_t)(*tempbuff);
853
          tempbuff++;
854
          dataremaining--;
855
          data |= ((uint32_t)(*tempbuff) << 8U);
856
          tempbuff++;
857
          dataremaining--;
858
          data |= ((uint32_t)(*tempbuff) << 16U);
859
          tempbuff++;
860
          dataremaining--;
861
          data |= ((uint32_t)(*tempbuff) << 24U);
862
          tempbuff++;
863
          dataremaining--;
864
          (void)SDIO_WriteFIFO(hmmc->Instance, &data);
2 mjames 865
        }
866
      }
9 mjames 867
 
868
      if(((HAL_GetTick()-tickstart) >=  Timeout) || (Timeout == 0U))
2 mjames 869
      {
870
        /* Clear all the static flags */
9 mjames 871
        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 872
        hmmc->ErrorCode |= errorstate;
873
        hmmc->State = HAL_MMC_STATE_READY;
874
        return HAL_TIMEOUT;
875
      }
876
    }
9 mjames 877
 
2 mjames 878
    /* Send stop transmission command in case of multiblock write */
879
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
9 mjames 880
    {
2 mjames 881
      /* Send stop transmission command */
882
      errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
883
      if(errorstate != HAL_MMC_ERROR_NONE)
884
      {
885
        /* Clear all the static flags */
9 mjames 886
        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 887
        hmmc->ErrorCode |= errorstate;
888
        hmmc->State = HAL_MMC_STATE_READY;
889
        return HAL_ERROR;
890
      }
891
    }
9 mjames 892
 
2 mjames 893
    /* Get error state */
894
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
895
    {
896
      /* Clear all the static flags */
897
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
898
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
899
      hmmc->State = HAL_MMC_STATE_READY;
900
      return HAL_ERROR;
901
    }
902
    else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
903
    {
904
      /* Clear all the static flags */
905
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
9 mjames 906
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
2 mjames 907
      hmmc->State = HAL_MMC_STATE_READY;
908
      return HAL_ERROR;
909
    }
910
    else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR))
911
    {
912
      /* Clear all the static flags */
913
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
914
      hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
915
      hmmc->State = HAL_MMC_STATE_READY;
916
      return HAL_ERROR;
917
    }
9 mjames 918
    else
919
    {
920
      /* Nothing to do */
921
    }
922
 
2 mjames 923
    /* Clear all the static flags */
9 mjames 924
    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
925
 
2 mjames 926
    hmmc->State = HAL_MMC_STATE_READY;
9 mjames 927
 
2 mjames 928
    return HAL_OK;
929
  }
930
  else
931
  {
932
    hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
933
    return HAL_ERROR;
934
  }
935
}
936
 
937
/**
9 mjames 938
  * @brief  Reads block(s) from a specified address in a card. The Data transfer
939
  *         is managed in interrupt mode.
2 mjames 940
  * @note   This API should be followed by a check on the card state through
941
  *         HAL_MMC_GetCardState().
9 mjames 942
  * @note   You could also check the IT transfer process through the MMC Rx
2 mjames 943
  *         interrupt event.
9 mjames 944
  * @param  hmmc: Pointer to MMC handle
2 mjames 945
  * @param  pData: Pointer to the buffer that will contain the received data
9 mjames 946
  * @param  BlockAdd: Block Address from where data is to be read
2 mjames 947
  * @param  NumberOfBlocks: Number of blocks to read.
948
  * @retval HAL status
949
  */
950
HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
951
{
952
  SDIO_DataInitTypeDef config;
9 mjames 953
  uint32_t errorstate;
954
  uint32_t add = BlockAdd;
955
 
2 mjames 956
  if(NULL == pData)
957
  {
958
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
959
    return HAL_ERROR;
960
  }
9 mjames 961
 
2 mjames 962
  if(hmmc->State == HAL_MMC_STATE_READY)
963
  {
9 mjames 964
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
965
 
2 mjames 966
    if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
967
    {
968
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
969
      return HAL_ERROR;
970
    }
9 mjames 971
 
2 mjames 972
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 973
 
2 mjames 974
    /* Initialize data control register */
975
    hmmc->Instance->DCTRL = 0U;
976
 
9 mjames 977
    hmmc->pRxBuffPtr = pData;
978
    hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
979
 
980
    __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF | SDIO_IT_STBITERR));
981
 
982
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 983
    {
9 mjames 984
      add *= 512U;
2 mjames 985
    }
9 mjames 986
 
987
    /* Set Block Size for Card */
988
    errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
2 mjames 989
    if(errorstate != HAL_MMC_ERROR_NONE)
990
    {
991
      /* Clear all the static flags */
9 mjames 992
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 993
      hmmc->ErrorCode |= errorstate;
994
      hmmc->State = HAL_MMC_STATE_READY;
995
      return HAL_ERROR;
996
    }
997
 
9 mjames 998
    /* Configure the MMC DPSM (Data Path State Machine) */
999
    config.DataTimeOut   = SDMMC_DATATIMEOUT;
1000
    config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1001
    config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1002
    config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
1003
    config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1004
    config.DPSM          = SDIO_DPSM_ENABLE;
1005
    (void)SDIO_ConfigData(hmmc->Instance, &config);
1006
 
2 mjames 1007
    /* Read Blocks in IT mode */
1008
    if(NumberOfBlocks > 1U)
1009
    {
1010
      hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
9 mjames 1011
 
2 mjames 1012
      /* Read Multi Block command */
9 mjames 1013
      errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
2 mjames 1014
    }
1015
    else
1016
    {
1017
      hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
9 mjames 1018
 
2 mjames 1019
      /* Read Single Block command */
9 mjames 1020
      errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
2 mjames 1021
    }
9 mjames 1022
 
2 mjames 1023
    if(errorstate != HAL_MMC_ERROR_NONE)
1024
    {
1025
      /* Clear all the static flags */
9 mjames 1026
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1027
      hmmc->ErrorCode |= errorstate;
1028
      hmmc->State = HAL_MMC_STATE_READY;
1029
      return HAL_ERROR;
1030
    }
9 mjames 1031
 
2 mjames 1032
    return HAL_OK;
1033
  }
1034
  else
1035
  {
1036
    return HAL_BUSY;
1037
  }
1038
}
1039
 
1040
/**
9 mjames 1041
  * @brief  Writes block(s) to a specified address in a card. The Data transfer
1042
  *         is managed in interrupt mode.
2 mjames 1043
  * @note   This API should be followed by a check on the card state through
1044
  *         HAL_MMC_GetCardState().
9 mjames 1045
  * @note   You could also check the IT transfer process through the MMC Tx
1046
  *         interrupt event.
2 mjames 1047
  * @param  hmmc: Pointer to MMC handle
1048
  * @param  pData: Pointer to the buffer that will contain the data to transmit
9 mjames 1049
  * @param  BlockAdd: Block Address where data will be written
2 mjames 1050
  * @param  NumberOfBlocks: Number of blocks to write
1051
  * @retval HAL status
1052
  */
1053
HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1054
{
1055
  SDIO_DataInitTypeDef config;
9 mjames 1056
  uint32_t errorstate;
1057
  uint32_t add = BlockAdd;
1058
 
2 mjames 1059
  if(NULL == pData)
1060
  {
1061
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1062
    return HAL_ERROR;
1063
  }
9 mjames 1064
 
2 mjames 1065
  if(hmmc->State == HAL_MMC_STATE_READY)
1066
  {
9 mjames 1067
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1068
 
2 mjames 1069
    if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1070
    {
1071
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1072
      return HAL_ERROR;
1073
    }
9 mjames 1074
 
2 mjames 1075
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 1076
 
2 mjames 1077
    /* Initialize data control register */
1078
    hmmc->Instance->DCTRL = 0U;
9 mjames 1079
 
1080
    hmmc->pTxBuffPtr = pData;
1081
    hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
1082
 
2 mjames 1083
    /* Enable transfer interrupts */
9 mjames 1084
    __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE | SDIO_IT_STBITERR));
1085
 
1086
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 1087
    {
9 mjames 1088
      add *= 512U;
2 mjames 1089
    }
9 mjames 1090
 
1091
    /* Set Block Size for Card */
1092
    errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
2 mjames 1093
    if(errorstate != HAL_MMC_ERROR_NONE)
1094
    {
1095
      /* Clear all the static flags */
9 mjames 1096
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1097
      hmmc->ErrorCode |= errorstate;
1098
      hmmc->State = HAL_MMC_STATE_READY;
1099
      return HAL_ERROR;
1100
    }
9 mjames 1101
 
2 mjames 1102
    /* Write Blocks in Polling mode */
1103
    if(NumberOfBlocks > 1U)
1104
    {
1105
      hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
9 mjames 1106
 
1107
      /* Write Multi Block command */
1108
      errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
2 mjames 1109
    }
1110
    else
1111
    {
1112
      hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
9 mjames 1113
 
1114
      /* Write Single Block command */
1115
      errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
2 mjames 1116
    }
1117
    if(errorstate != HAL_MMC_ERROR_NONE)
1118
    {
1119
      /* Clear all the static flags */
9 mjames 1120
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1121
      hmmc->ErrorCode |= errorstate;
1122
      hmmc->State = HAL_MMC_STATE_READY;
1123
      return HAL_ERROR;
1124
    }
9 mjames 1125
 
2 mjames 1126
    /* Configure the MMC DPSM (Data Path State Machine) */
1127
    config.DataTimeOut   = SDMMC_DATATIMEOUT;
9 mjames 1128
    config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
2 mjames 1129
    config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1130
    config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
1131
    config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1132
    config.DPSM          = SDIO_DPSM_ENABLE;
9 mjames 1133
    (void)SDIO_ConfigData(hmmc->Instance, &config);
2 mjames 1134
 
1135
    return HAL_OK;
1136
  }
1137
  else
1138
  {
1139
    return HAL_BUSY;
1140
  }
1141
}
1142
 
1143
/**
9 mjames 1144
  * @brief  Reads block(s) from a specified address in a card. The Data transfer
1145
  *         is managed by DMA mode.
2 mjames 1146
  * @note   This API should be followed by a check on the card state through
1147
  *         HAL_MMC_GetCardState().
9 mjames 1148
  * @note   You could also check the DMA transfer process through the MMC Rx
2 mjames 1149
  *         interrupt event.
9 mjames 1150
  * @param  hmmc: Pointer MMC handle
2 mjames 1151
  * @param  pData: Pointer to the buffer that will contain the received data
9 mjames 1152
  * @param  BlockAdd: Block Address from where data is to be read
2 mjames 1153
  * @param  NumberOfBlocks: Number of blocks to read.
1154
  * @retval HAL status
1155
  */
1156
HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1157
{
1158
  SDIO_DataInitTypeDef config;
9 mjames 1159
  uint32_t errorstate;
1160
  uint32_t add = BlockAdd;
1161
 
2 mjames 1162
  if(NULL == pData)
1163
  {
1164
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1165
    return HAL_ERROR;
1166
  }
9 mjames 1167
 
2 mjames 1168
  if(hmmc->State == HAL_MMC_STATE_READY)
1169
  {
1170
    hmmc->ErrorCode = HAL_DMA_ERROR_NONE;
9 mjames 1171
 
2 mjames 1172
    if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1173
    {
1174
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1175
      return HAL_ERROR;
1176
    }
9 mjames 1177
 
2 mjames 1178
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 1179
 
2 mjames 1180
    /* Initialize data control register */
1181
    hmmc->Instance->DCTRL = 0U;
9 mjames 1182
 
2 mjames 1183
    __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_IT_STBITERR));
9 mjames 1184
 
2 mjames 1185
    /* Set the DMA transfer complete callback */
1186
    hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt;
9 mjames 1187
 
2 mjames 1188
    /* Set the DMA error callback */
1189
    hmmc->hdmarx->XferErrorCallback = MMC_DMAError;
9 mjames 1190
 
2 mjames 1191
    /* Set the DMA Abort callback */
1192
    hmmc->hdmarx->XferAbortCallback = NULL;
9 mjames 1193
 
1194
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 1195
    {
9 mjames 1196
      add *= 512U;
2 mjames 1197
    }
1198
 
1199
    /* Set Block Size for Card */
9 mjames 1200
    errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
2 mjames 1201
    if(errorstate != HAL_MMC_ERROR_NONE)
1202
    {
1203
      /* Clear all the static flags */
1204
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
9 mjames 1205
      hmmc->ErrorCode = errorstate;
2 mjames 1206
      hmmc->State = HAL_MMC_STATE_READY;
1207
      return HAL_ERROR;
1208
    }
9 mjames 1209
 
1210
    /* Enable the DMA Channel */
1211
    if(HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
2 mjames 1212
    {
9 mjames 1213
      __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
1214
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1215
      hmmc->ErrorCode = HAL_MMC_ERROR_DMA;
1216
      hmmc->State = HAL_MMC_STATE_READY;
1217
      return HAL_ERROR;
2 mjames 1218
    }
1219
    else
1220
    {
9 mjames 1221
      /* Enable MMC DMA transfer */
1222
      __HAL_MMC_DMA_ENABLE(hmmc);
1223
 
1224
      /* Configure the MMC DPSM (Data Path State Machine) */
1225
      config.DataTimeOut   = SDMMC_DATATIMEOUT;
1226
      config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1227
      config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1228
      config.TransferDir   = SDIO_TRANSFER_DIR_TO_SDIO;
1229
      config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1230
      config.DPSM          = SDIO_DPSM_ENABLE;
1231
      (void)SDIO_ConfigData(hmmc->Instance, &config);
1232
 
1233
      /* Read Blocks in DMA mode */
1234
      if(NumberOfBlocks > 1U)
1235
      {
1236
        hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
1237
 
1238
        /* Read Multi Block command */
1239
        errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
1240
      }
1241
      else
1242
      {
1243
        hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
1244
 
1245
        /* Read Single Block command */
1246
        errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
1247
      }
1248
      if(errorstate != HAL_MMC_ERROR_NONE)
1249
      {
1250
        /* Clear all the static flags */
1251
        __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1252
        __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
1253
        hmmc->ErrorCode = errorstate;
1254
        hmmc->State = HAL_MMC_STATE_READY;
1255
        return HAL_ERROR;
1256
      }
1257
 
1258
      return HAL_OK;
2 mjames 1259
    }
1260
  }
1261
  else
1262
  {
1263
    return HAL_BUSY;
1264
  }
1265
}
1266
 
1267
/**
9 mjames 1268
  * @brief  Writes block(s) to a specified address in a card. The Data transfer
1269
  *         is managed by DMA mode.
2 mjames 1270
  * @note   This API should be followed by a check on the card state through
1271
  *         HAL_MMC_GetCardState().
9 mjames 1272
  * @note   You could also check the DMA transfer process through the MMC Tx
2 mjames 1273
  *         interrupt event.
1274
  * @param  hmmc: Pointer to MMC handle
1275
  * @param  pData: Pointer to the buffer that will contain the data to transmit
9 mjames 1276
  * @param  BlockAdd: Block Address where data will be written
2 mjames 1277
  * @param  NumberOfBlocks: Number of blocks to write
1278
  * @retval HAL status
1279
  */
1280
HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
1281
{
1282
  SDIO_DataInitTypeDef config;
9 mjames 1283
  uint32_t errorstate;
1284
  uint32_t add = BlockAdd;
1285
 
2 mjames 1286
  if(NULL == pData)
1287
  {
1288
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1289
    return HAL_ERROR;
1290
  }
9 mjames 1291
 
2 mjames 1292
  if(hmmc->State == HAL_MMC_STATE_READY)
1293
  {
9 mjames 1294
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1295
 
2 mjames 1296
    if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
1297
    {
1298
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1299
      return HAL_ERROR;
1300
    }
9 mjames 1301
 
2 mjames 1302
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 1303
 
2 mjames 1304
    /* Initialize data control register */
1305
    hmmc->Instance->DCTRL = 0U;
9 mjames 1306
 
2 mjames 1307
    /* Enable MMC Error interrupts */
9 mjames 1308
        __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_STBITERR));
1309
 
2 mjames 1310
    /* Set the DMA transfer complete callback */
1311
    hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt;
9 mjames 1312
 
2 mjames 1313
    /* Set the DMA error callback */
1314
    hmmc->hdmatx->XferErrorCallback = MMC_DMAError;
9 mjames 1315
 
2 mjames 1316
    /* Set the DMA Abort callback */
1317
    hmmc->hdmatx->XferAbortCallback = NULL;
9 mjames 1318
 
1319
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 1320
    {
9 mjames 1321
      add *= 512U;
2 mjames 1322
    }
9 mjames 1323
 
1324
    /* Set Block Size for Card */
1325
    errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
2 mjames 1326
    if(errorstate != HAL_MMC_ERROR_NONE)
1327
    {
1328
      /* Clear all the static flags */
9 mjames 1329
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1330
      hmmc->ErrorCode |= errorstate;
1331
      hmmc->State = HAL_MMC_STATE_READY;
1332
      return HAL_ERROR;
1333
    }
9 mjames 1334
 
2 mjames 1335
    /* Write Blocks in Polling mode */
1336
    if(NumberOfBlocks > 1U)
1337
    {
1338
      hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
9 mjames 1339
 
1340
      /* Write Multi Block command */
1341
      errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
2 mjames 1342
    }
1343
    else
1344
    {
1345
      hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
9 mjames 1346
 
2 mjames 1347
      /* Write Single Block command */
9 mjames 1348
      errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
2 mjames 1349
    }
1350
    if(errorstate != HAL_MMC_ERROR_NONE)
1351
    {
1352
      /* Clear all the static flags */
9 mjames 1353
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1354
      __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
2 mjames 1355
      hmmc->ErrorCode |= errorstate;
1356
      hmmc->State = HAL_MMC_STATE_READY;
1357
      return HAL_ERROR;
1358
    }
9 mjames 1359
 
2 mjames 1360
    /* Enable SDIO DMA transfer */
1361
    __HAL_MMC_DMA_ENABLE(hmmc);
9 mjames 1362
 
2 mjames 1363
    /* Enable the DMA Channel */
9 mjames 1364
    if(HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
1365
    {
1366
      __HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
1367
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1368
      hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
1369
      hmmc->State = HAL_MMC_STATE_READY;
1370
      return HAL_ERROR;
1371
    }
1372
    else
1373
    {    
1374
      /* Configure the MMC DPSM (Data Path State Machine) */
1375
      config.DataTimeOut   = SDMMC_DATATIMEOUT;
1376
      config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
1377
      config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
1378
      config.TransferDir   = SDIO_TRANSFER_DIR_TO_CARD;
1379
      config.TransferMode  = SDIO_TRANSFER_MODE_BLOCK;
1380
      config.DPSM          = SDIO_DPSM_ENABLE;
1381
      (void)SDIO_ConfigData(hmmc->Instance, &config);
1382
 
1383
      return HAL_OK;
1384
    }
2 mjames 1385
  }
1386
  else
1387
  {
1388
    return HAL_BUSY;
1389
  }
1390
}
1391
 
1392
/**
1393
  * @brief  Erases the specified memory area of the given MMC card.
1394
  * @note   This API should be followed by a check on the card state through
1395
  *         HAL_MMC_GetCardState().
9 mjames 1396
  * @param  hmmc: Pointer to MMC handle
2 mjames 1397
  * @param  BlockStartAdd: Start Block address
1398
  * @param  BlockEndAdd: End Block address
1399
  * @retval HAL status
1400
  */
1401
HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
1402
{
9 mjames 1403
  uint32_t errorstate;
1404
  uint32_t start_add = BlockStartAdd;
1405
  uint32_t end_add = BlockEndAdd;
1406
 
2 mjames 1407
  if(hmmc->State == HAL_MMC_STATE_READY)
1408
  {
9 mjames 1409
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1410
 
1411
    if(end_add < start_add)
2 mjames 1412
    {
1413
      hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
1414
      return HAL_ERROR;
1415
    }
9 mjames 1416
 
1417
    if(end_add > (hmmc->MmcCard.LogBlockNbr))
2 mjames 1418
    {
1419
      hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
1420
      return HAL_ERROR;
1421
    }
9 mjames 1422
 
2 mjames 1423
    hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 1424
 
2 mjames 1425
    /* Check if the card command class supports erase command */
1426
    if(((hmmc->MmcCard.Class) & SDIO_CCCC_ERASE) == 0U)
1427
    {
1428
      /* Clear all the static flags */
1429
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
1430
      hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
1431
      hmmc->State = HAL_MMC_STATE_READY;
1432
      return HAL_ERROR;
1433
    }
9 mjames 1434
 
2 mjames 1435
    if((SDIO_GetResponse(hmmc->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
1436
    {
1437
      /* Clear all the static flags */
9 mjames 1438
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1439
      hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
1440
      hmmc->State = HAL_MMC_STATE_READY;
1441
      return HAL_ERROR;
1442
    }
9 mjames 1443
 
1444
    if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
2 mjames 1445
    {
9 mjames 1446
      start_add *= 512U;
1447
      end_add   *= 512U;
2 mjames 1448
    }
1449
 
1450
    /* Send CMD35 MMC_ERASE_GRP_START with argument as addr  */
9 mjames 1451
    errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
2 mjames 1452
    if(errorstate != HAL_MMC_ERROR_NONE)
1453
    {
1454
      /* Clear all the static flags */
9 mjames 1455
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1456
      hmmc->ErrorCode |= errorstate;
1457
      hmmc->State = HAL_MMC_STATE_READY;
1458
      return HAL_ERROR;
1459
    }
9 mjames 1460
 
2 mjames 1461
    /* Send CMD36 MMC_ERASE_GRP_END with argument as addr  */
9 mjames 1462
    errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
2 mjames 1463
    if(errorstate != HAL_MMC_ERROR_NONE)
1464
    {
1465
      /* Clear all the static flags */
9 mjames 1466
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1467
      hmmc->ErrorCode |= errorstate;
1468
      hmmc->State = HAL_MMC_STATE_READY;
1469
      return HAL_ERROR;
1470
    }
9 mjames 1471
 
2 mjames 1472
    /* Send CMD38 ERASE */
1473
    errorstate = SDMMC_CmdErase(hmmc->Instance);
1474
    if(errorstate != HAL_MMC_ERROR_NONE)
1475
    {
1476
      /* Clear all the static flags */
9 mjames 1477
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2 mjames 1478
      hmmc->ErrorCode |= errorstate;
1479
      hmmc->State = HAL_MMC_STATE_READY;
1480
      return HAL_ERROR;
1481
    }
9 mjames 1482
 
2 mjames 1483
    hmmc->State = HAL_MMC_STATE_READY;
9 mjames 1484
 
2 mjames 1485
    return HAL_OK;
1486
  }
1487
  else
1488
  {
1489
    return HAL_BUSY;
1490
  }
1491
}
1492
 
1493
/**
1494
  * @brief  This function handles MMC card interrupt request.
1495
  * @param  hmmc: Pointer to MMC handle
1496
  * @retval None
1497
  */
1498
void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
1499
{
9 mjames 1500
  uint32_t errorstate;
1501
  uint32_t context = hmmc->Context;
1502
 
2 mjames 1503
  /* Check for SDIO interrupt flags */
9 mjames 1504
  if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
2 mjames 1505
  {
9 mjames 1506
    MMC_Read_IT(hmmc);
1507
  }
1508
 
1509
  else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) != RESET)
1510
  {
1511
    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_DATAEND);
1512
 
2 mjames 1513
    __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
9 mjames 1514
                             SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
2 mjames 1515
 
9 mjames 1516
    hmmc->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN);
1517
 
1518
    if((context & MMC_CONTEXT_DMA) != 0U)
2 mjames 1519
    {
9 mjames 1520
      if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
2 mjames 1521
      {
1522
        errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1523
        if(errorstate != HAL_MMC_ERROR_NONE)
1524
        {
1525
          hmmc->ErrorCode |= errorstate;
9 mjames 1526
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1527
          hmmc->ErrorCallback(hmmc);
1528
#else
2 mjames 1529
          HAL_MMC_ErrorCallback(hmmc);
9 mjames 1530
#endif
2 mjames 1531
        }
1532
      }
9 mjames 1533
      if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
2 mjames 1534
      {
9 mjames 1535
        /* Disable the DMA transfer for transmit request by setting the DMAEN bit
1536
        in the MMC DCTRL register */
1537
        hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
1538
 
1539
        hmmc->State = HAL_MMC_STATE_READY;
1540
 
1541
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1542
        hmmc->TxCpltCallback(hmmc);
1543
#else
2 mjames 1544
        HAL_MMC_TxCpltCallback(hmmc);
9 mjames 1545
#endif
2 mjames 1546
      }
1547
    }
9 mjames 1548
    else if((context & MMC_CONTEXT_IT) != 0U)
2 mjames 1549
    {
9 mjames 1550
      /* Stop Transfer for Write Multi blocks or Read Multi blocks */
1551
      if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
2 mjames 1552
      {
1553
        errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
1554
        if(errorstate != HAL_MMC_ERROR_NONE)
1555
        {
1556
          hmmc->ErrorCode |= errorstate;
9 mjames 1557
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1558
          hmmc->ErrorCallback(hmmc);
1559
#else
2 mjames 1560
          HAL_MMC_ErrorCallback(hmmc);
9 mjames 1561
#endif
2 mjames 1562
        }
1563
      }
9 mjames 1564
 
1565
      /* Clear all the static flags */
1566
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
1567
 
1568
      hmmc->State = HAL_MMC_STATE_READY;
1569
      if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
2 mjames 1570
      {
9 mjames 1571
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1572
        hmmc->RxCpltCallback(hmmc);
1573
#else
1574
        HAL_MMC_RxCpltCallback(hmmc);
1575
#endif
1576
      }
1577
      else
1578
      {
1579
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1580
        hmmc->TxCpltCallback(hmmc);
1581
#else
2 mjames 1582
        HAL_MMC_TxCpltCallback(hmmc);
9 mjames 1583
#endif
2 mjames 1584
      }
1585
    }
9 mjames 1586
    else
1587
    {
1588
      /* Nothing to do */
1589
    }
2 mjames 1590
  }
9 mjames 1591
 
1592
  else if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
2 mjames 1593
  {
1594
    MMC_Write_IT(hmmc);
1595
  }
9 mjames 1596
 
1597
  else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR | SDIO_FLAG_STBITERR) != RESET)
2 mjames 1598
  {
1599
    /* Set Error code */
9 mjames 1600
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL) != RESET)
2 mjames 1601
    {
9 mjames 1602
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
2 mjames 1603
    }
9 mjames 1604
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT) != RESET)
2 mjames 1605
    {
9 mjames 1606
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
2 mjames 1607
    }
9 mjames 1608
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR) != RESET)
2 mjames 1609
    {
9 mjames 1610
      hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
2 mjames 1611
    }
9 mjames 1612
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR) != RESET)
2 mjames 1613
    {
9 mjames 1614
      hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
2 mjames 1615
    }
9 mjames 1616
    if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_STBITERR) != RESET)
2 mjames 1617
    {
1618
      hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
1619
    }
1620
 
1621
    /* Clear All flags */
9 mjames 1622
    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR);
1623
 
2 mjames 1624
    /* Disable all interrupts */
1625
    __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
9 mjames 1626
                               SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
1627
 
1628
    hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
1629
 
1630
    if((context & MMC_CONTEXT_IT) != 0U)
2 mjames 1631
    {
1632
      /* Set the MMC state to ready to be able to start again the process */
1633
      hmmc->State = HAL_MMC_STATE_READY;
9 mjames 1634
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1635
      hmmc->ErrorCallback(hmmc);
1636
#else
2 mjames 1637
      HAL_MMC_ErrorCallback(hmmc);
9 mjames 1638
#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
2 mjames 1639
    }
9 mjames 1640
    else if((context & MMC_CONTEXT_DMA) != 0U)
2 mjames 1641
    {
1642
      /* Abort the MMC DMA Streams */
1643
      if(hmmc->hdmatx != NULL)
1644
      {
1645
        /* Set the DMA Tx abort callback */
1646
        hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
1647
        /* Abort DMA in IT mode */
1648
        if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
1649
        {
1650
          MMC_DMATxAbort(hmmc->hdmatx);
1651
        }
1652
      }
1653
      else if(hmmc->hdmarx != NULL)
1654
      {
1655
        /* Set the DMA Rx abort callback */
1656
        hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
1657
        /* Abort DMA in IT mode */
1658
        if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
1659
        {
1660
          MMC_DMARxAbort(hmmc->hdmarx);
1661
        }
1662
      }
1663
      else
1664
      {
1665
        hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
1666
        hmmc->State = HAL_MMC_STATE_READY;
9 mjames 1667
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1668
        hmmc->AbortCpltCallback(hmmc);
1669
#else
2 mjames 1670
        HAL_MMC_AbortCallback(hmmc);
9 mjames 1671
#endif
2 mjames 1672
      }
1673
    }
9 mjames 1674
    else
2 mjames 1675
    {
9 mjames 1676
      /* Nothing to do */
2 mjames 1677
    }
1678
  }
9 mjames 1679
 
1680
  else
1681
  {
1682
    /* Nothing to do */
1683
  }
2 mjames 1684
}
1685
 
1686
/**
1687
  * @brief return the MMC state
1688
  * @param hmmc: Pointer to mmc handle
1689
  * @retval HAL state
1690
  */
1691
HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
1692
{
1693
  return hmmc->State;
1694
}
1695
 
1696
/**
1697
* @brief  Return the MMC error code
1698
* @param  hmmc : Pointer to a MMC_HandleTypeDef structure that contains
1699
  *              the configuration information.
1700
* @retval MMC Error Code
1701
*/
1702
uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
1703
{
1704
  return hmmc->ErrorCode;
1705
}
1706
 
1707
/**
1708
  * @brief Tx Transfer completed callbacks
1709
  * @param hmmc: Pointer to MMC handle
1710
  * @retval None
1711
  */
9 mjames 1712
__weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
2 mjames 1713
{
1714
  /* Prevent unused argument(s) compilation warning */
1715
  UNUSED(hmmc);
1716
 
1717
  /* NOTE : This function should not be modified, when the callback is needed,
1718
            the HAL_MMC_TxCpltCallback can be implemented in the user file
1719
   */
1720
}
1721
 
1722
/**
1723
  * @brief Rx Transfer completed callbacks
1724
  * @param hmmc: Pointer MMC handle
1725
  * @retval None
1726
  */
1727
__weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
1728
{
1729
  /* Prevent unused argument(s) compilation warning */
1730
  UNUSED(hmmc);
9 mjames 1731
 
2 mjames 1732
  /* NOTE : This function should not be modified, when the callback is needed,
1733
            the HAL_MMC_RxCpltCallback can be implemented in the user file
1734
   */
1735
}
1736
 
1737
/**
1738
  * @brief MMC error callbacks
1739
  * @param hmmc: Pointer MMC handle
1740
  * @retval None
1741
  */
1742
__weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
1743
{
1744
  /* Prevent unused argument(s) compilation warning */
1745
  UNUSED(hmmc);
9 mjames 1746
 
2 mjames 1747
  /* NOTE : This function should not be modified, when the callback is needed,
1748
            the HAL_MMC_ErrorCallback can be implemented in the user file
9 mjames 1749
   */
2 mjames 1750
}
1751
 
1752
/**
1753
  * @brief MMC Abort callbacks
1754
  * @param hmmc: Pointer MMC handle
1755
  * @retval None
1756
  */
1757
__weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
1758
{
1759
  /* Prevent unused argument(s) compilation warning */
1760
  UNUSED(hmmc);
9 mjames 1761
 
2 mjames 1762
  /* NOTE : This function should not be modified, when the callback is needed,
9 mjames 1763
            the HAL_MMC_AbortCallback can be implemented in the user file
1764
   */
2 mjames 1765
}
1766
 
9 mjames 1767
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
1768
/**
1769
  * @brief  Register a User MMC Callback
1770
  *         To be used instead of the weak (surcharged) predefined callback
1771
  * @param hmmc : MMC handle
1772
  * @param CallbackId : ID of the callback to be registered
1773
  *        This parameter can be one of the following values:
1774
  *          @arg @ref HAL_MMC_TX_CPLT_CB_ID    MMC Tx Complete Callback ID
1775
  *          @arg @ref HAL_MMC_RX_CPLT_CB_ID    MMC Rx Complete Callback ID
1776
  *          @arg @ref HAL_MMC_ERROR_CB_ID      MMC Error Callback ID
1777
  *          @arg @ref HAL_MMC_ABORT_CB_ID      MMC Abort Callback ID
1778
  *          @arg @ref HAL_MMC_MSP_INIT_CB_ID   MMC MspInit Callback ID
1779
  *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1780
  * @param pCallback : pointer to the Callback function
1781
  * @retval status
1782
  */
1783
HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
1784
{
1785
  HAL_StatusTypeDef status = HAL_OK;
2 mjames 1786
 
9 mjames 1787
  if(pCallback == NULL)
1788
  {
1789
    /* Update the error code */
1790
    hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1791
    return HAL_ERROR;
1792
  }
1793
 
1794
  /* Process locked */
1795
  __HAL_LOCK(hmmc);
1796
 
1797
  if(hmmc->State == HAL_MMC_STATE_READY)
1798
  {
1799
    switch (CallbackId)
1800
    {
1801
    case HAL_MMC_TX_CPLT_CB_ID :
1802
      hmmc->TxCpltCallback = pCallback;
1803
      break;
1804
    case HAL_MMC_RX_CPLT_CB_ID :
1805
      hmmc->RxCpltCallback = pCallback;
1806
      break;
1807
    case HAL_MMC_ERROR_CB_ID :
1808
      hmmc->ErrorCallback = pCallback;
1809
      break;
1810
    case HAL_MMC_ABORT_CB_ID :
1811
      hmmc->AbortCpltCallback = pCallback;
1812
      break;
1813
    case HAL_MMC_MSP_INIT_CB_ID :
1814
      hmmc->MspInitCallback = pCallback;
1815
      break;
1816
    case HAL_MMC_MSP_DEINIT_CB_ID :
1817
      hmmc->MspDeInitCallback = pCallback;
1818
      break;
1819
    default :
1820
      /* Update the error code */
1821
      hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1822
      /* update return status */
1823
      status =  HAL_ERROR;
1824
      break;
1825
    }
1826
  }
1827
  else if (hmmc->State == HAL_MMC_STATE_RESET)
1828
  {
1829
    switch (CallbackId)
1830
    {
1831
    case HAL_MMC_MSP_INIT_CB_ID :
1832
      hmmc->MspInitCallback = pCallback;
1833
      break;
1834
    case HAL_MMC_MSP_DEINIT_CB_ID :
1835
      hmmc->MspDeInitCallback = pCallback;
1836
      break;
1837
    default :
1838
      /* Update the error code */
1839
      hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1840
      /* update return status */
1841
      status =  HAL_ERROR;
1842
      break;
1843
    }
1844
  }
1845
  else
1846
  {
1847
    /* Update the error code */
1848
    hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1849
    /* update return status */
1850
    status =  HAL_ERROR;
1851
  }
1852
 
1853
  /* Release Lock */
1854
  __HAL_UNLOCK(hmmc);
1855
  return status;
1856
}
1857
 
2 mjames 1858
/**
9 mjames 1859
  * @brief  Unregister a User MMC Callback
1860
  *         MMC Callback is redirected to the weak (surcharged) predefined callback
1861
  * @param hmmc : MMC handle
1862
  * @param CallbackId : ID of the callback to be unregistered
1863
  *        This parameter can be one of the following values:
1864
  *          @arg @ref HAL_MMC_TX_CPLT_CB_ID    MMC Tx Complete Callback ID
1865
  *          @arg @ref HAL_MMC_RX_CPLT_CB_ID    MMC Rx Complete Callback ID
1866
  *          @arg @ref HAL_MMC_ERROR_CB_ID      MMC Error Callback ID
1867
  *          @arg @ref HAL_MMC_ABORT_CB_ID      MMC Abort Callback ID
1868
  *          @arg @ref HAL_MMC_MSP_INIT_CB_ID   MMC MspInit Callback ID
1869
  *          @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
1870
  * @retval status
1871
  */
1872
HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
1873
{
1874
  HAL_StatusTypeDef status = HAL_OK;
1875
 
1876
  /* Process locked */
1877
  __HAL_LOCK(hmmc);
1878
 
1879
  if(hmmc->State == HAL_MMC_STATE_READY)
1880
  {
1881
    switch (CallbackId)
1882
    {
1883
    case HAL_MMC_TX_CPLT_CB_ID :
1884
      hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
1885
      break;
1886
    case HAL_MMC_RX_CPLT_CB_ID :
1887
      hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
1888
      break;
1889
    case HAL_MMC_ERROR_CB_ID :
1890
      hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
1891
      break;
1892
    case HAL_MMC_ABORT_CB_ID :
1893
      hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
1894
      break;
1895
    case HAL_MMC_MSP_INIT_CB_ID :
1896
      hmmc->MspInitCallback = HAL_MMC_MspInit;
1897
      break;
1898
    case HAL_MMC_MSP_DEINIT_CB_ID :
1899
      hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1900
      break;
1901
    default :
1902
      /* Update the error code */
1903
      hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1904
      /* update return status */
1905
      status =  HAL_ERROR;
1906
      break;
1907
    }
1908
  }
1909
  else if (hmmc->State == HAL_MMC_STATE_RESET)
1910
  {
1911
    switch (CallbackId)
1912
    {
1913
    case HAL_MMC_MSP_INIT_CB_ID :
1914
      hmmc->MspInitCallback = HAL_MMC_MspInit;
1915
      break;
1916
    case HAL_MMC_MSP_DEINIT_CB_ID :
1917
      hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
1918
      break;
1919
    default :
1920
      /* Update the error code */
1921
      hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1922
      /* update return status */
1923
      status =  HAL_ERROR;
1924
      break;
1925
    }
1926
  }
1927
  else
1928
  {
1929
    /* Update the error code */
1930
    hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
1931
    /* update return status */
1932
    status =  HAL_ERROR;
1933
  }
1934
 
1935
  /* Release Lock */
1936
  __HAL_UNLOCK(hmmc);
1937
  return status;
1938
}
1939
#endif
1940
 
1941
/**
2 mjames 1942
  * @}
1943
  */
1944
 
1945
/** @addtogroup MMC_Exported_Functions_Group3
9 mjames 1946
 *  @brief   management functions
2 mjames 1947
 *
9 mjames 1948
@verbatim
2 mjames 1949
  ==============================================================================
1950
                      ##### Peripheral Control functions #####
9 mjames 1951
  ==============================================================================
2 mjames 1952
  [..]
9 mjames 1953
    This subsection provides a set of functions allowing to control the MMC card
2 mjames 1954
    operations and get the related information
1955
 
1956
@endverbatim
1957
  * @{
1958
  */
1959
 
1960
/**
1961
  * @brief  Returns information the information of the card which are stored on
1962
  *         the CID register.
1963
  * @param  hmmc: Pointer to MMC handle
9 mjames 1964
  * @param  pCID: Pointer to a HAL_MMC_CIDTypedef structure that
1965
  *         contains all CID register parameters
2 mjames 1966
  * @retval HAL status
1967
  */
1968
HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
1969
{
9 mjames 1970
  pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
1971
 
1972
  pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
1973
 
1974
  pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
1975
 
1976
  pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
1977
 
1978
  pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
1979
 
1980
  pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
1981
 
1982
  pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
1983
 
1984
  pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
1985
 
1986
  pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
1987
 
2 mjames 1988
  pCID->Reserved2 = 1U;
1989
 
1990
  return HAL_OK;
1991
}
1992
 
1993
/**
1994
  * @brief  Returns information the information of the card which are stored on
1995
  *         the CSD register.
1996
  * @param  hmmc: Pointer to MMC handle
9 mjames 1997
  * @param  pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
1998
  *         contains all CSD register parameters
2 mjames 1999
  * @retval HAL status
2000
  */
2001
HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
2002
{
9 mjames 2003
  pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
2004
 
2005
  pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
2006
 
2007
  pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
2008
 
2009
  pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
2010
 
2011
  pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
2012
 
2013
  pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
2014
 
2015
  pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
2016
 
2017
  pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
2018
 
2019
  pCSD->PartBlockRead   = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
2020
 
2021
  pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
2022
 
2023
  pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
2024
 
2025
  pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
2026
 
2027
  pCSD->Reserved2 = 0U; /*!< Reserved */
2028
 
2029
  pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
2030
 
2031
  pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
2032
 
2033
  pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
2034
 
2035
  pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
2036
 
2037
  pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
2038
 
2039
  pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
2040
 
2 mjames 2041
  hmmc->MmcCard.BlockNbr  = (pCSD->DeviceSize + 1U) ;
9 mjames 2042
  hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
2043
  hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
2044
 
2045
  hmmc->MmcCard.LogBlockNbr =  (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
2 mjames 2046
  hmmc->MmcCard.LogBlockSize = 512U;
2047
 
9 mjames 2048
  pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
2049
 
2050
  pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
2051
 
2052
  pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
2053
 
2054
  pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
2055
 
2056
  pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
2057
 
2058
  pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
2059
 
2060
  pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
2061
 
2062
  pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
2063
 
2064
  pCSD->Reserved3 = 0;
2065
 
2066
  pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
2067
 
2068
  pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
2069
 
2070
  pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
2071
 
2072
  pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
2073
 
2074
  pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
2075
 
2076
  pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
2077
 
2078
  pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
2079
 
2080
  pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
2081
 
2082
  pCSD->Reserved4 = 1;
2083
 
2 mjames 2084
  return HAL_OK;
2085
}
2086
 
2087
/**
2088
  * @brief  Gets the MMC card info.
9 mjames 2089
  * @param  hmmc: Pointer to MMC handle
2090
  * @param  pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
2091
  *         will contain the MMC card status information
2 mjames 2092
  * @retval HAL status
2093
  */
2094
HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
2095
{
2096
  pCardInfo->CardType     = (uint32_t)(hmmc->MmcCard.CardType);
2097
  pCardInfo->Class        = (uint32_t)(hmmc->MmcCard.Class);
2098
  pCardInfo->RelCardAdd   = (uint32_t)(hmmc->MmcCard.RelCardAdd);
2099
  pCardInfo->BlockNbr     = (uint32_t)(hmmc->MmcCard.BlockNbr);
2100
  pCardInfo->BlockSize    = (uint32_t)(hmmc->MmcCard.BlockSize);
2101
  pCardInfo->LogBlockNbr  = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
2102
  pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
9 mjames 2103
 
2 mjames 2104
  return HAL_OK;
2105
}
2106
 
2107
/**
9 mjames 2108
  * @brief  Enables wide bus operation for the requested card if supported by
2 mjames 2109
  *         card.
9 mjames 2110
  * @param  hmmc: Pointer to MMC handle
2111
  * @param  WideMode: Specifies the MMC card wide bus mode
2 mjames 2112
  *          This parameter can be one of the following values:
2113
  *            @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
2114
  *            @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
2115
  *            @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
2116
  * @retval HAL status
2117
  */
2118
HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
2119
{
2120
  __IO uint32_t count = 0U;
2121
  SDIO_InitTypeDef Init;
9 mjames 2122
  uint32_t errorstate;
2 mjames 2123
  uint32_t response = 0U, busy = 0U;
9 mjames 2124
 
2 mjames 2125
  /* Check the parameters */
2126
  assert_param(IS_SDIO_BUS_WIDE(WideMode));
9 mjames 2127
 
2 mjames 2128
  /* Chnage Satte */
2129
  hmmc->State = HAL_MMC_STATE_BUSY;
9 mjames 2130
 
2 mjames 2131
  /* Update Clock for Bus mode update */
2132
  Init.ClockEdge           = SDIO_CLOCK_EDGE_RISING;
2133
  Init.ClockBypass         = SDIO_CLOCK_BYPASS_DISABLE;
2134
  Init.ClockPowerSave      = SDIO_CLOCK_POWER_SAVE_DISABLE;
2135
  Init.BusWide             = WideMode;
2136
  Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
2137
  Init.ClockDiv            = SDIO_INIT_CLK_DIV;
2138
  /* Initialize SDIO*/
9 mjames 2139
  (void)SDIO_Init(hmmc->Instance, Init);
2140
 
2 mjames 2141
  if(WideMode == SDIO_BUS_WIDE_8B)
2142
  {
2143
    errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
2144
    if(errorstate != HAL_MMC_ERROR_NONE)
2145
    {
2146
      hmmc->ErrorCode |= errorstate;
2147
    }
2148
  }
2149
  else if(WideMode == SDIO_BUS_WIDE_4B)
2150
  {
2151
    errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
2152
    if(errorstate != HAL_MMC_ERROR_NONE)
2153
    {
2154
      hmmc->ErrorCode |= errorstate;
2155
    }
2156
  }
2157
  else if(WideMode == SDIO_BUS_WIDE_1B)
2158
  {
2159
    errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
2160
    if(errorstate != HAL_MMC_ERROR_NONE)
2161
    {
2162
      hmmc->ErrorCode |= errorstate;
2163
    }
2164
  }
2165
  else
2166
  {
2167
    /* WideMode is not a valid argument*/
2168
    hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
2169
  }
9 mjames 2170
 
2 mjames 2171
  /* Check for switch error and violation of the trial number of sending CMD 13 */
2172
  while(busy == 0U)
2173
  {
9 mjames 2174
    if(count == SDMMC_MAX_TRIAL)
2 mjames 2175
    {
2176
      hmmc->State = HAL_MMC_STATE_READY;
2177
      hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2178
      return HAL_ERROR;
2179
    }
9 mjames 2180
    count++;
2181
 
2 mjames 2182
    /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2183
    errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2184
    if(errorstate != HAL_MMC_ERROR_NONE)
2185
    {
2186
      hmmc->ErrorCode |= errorstate;
2187
    }
9 mjames 2188
 
2 mjames 2189
    /* Get command response */
2190
    response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
9 mjames 2191
 
2 mjames 2192
    /* Get operating voltage*/
2193
    busy = (((response >> 7U) == 1U) ? 0U : 1U);
2194
  }
9 mjames 2195
 
2 mjames 2196
  /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2197
  count = SDMMC_DATATIMEOUT;
2198
  while((response & 0x00000100U) == 0U)
2199
  {
9 mjames 2200
    if(count == 0U)
2 mjames 2201
    {
2202
      hmmc->State = HAL_MMC_STATE_READY;
2203
      hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2204
      return HAL_ERROR;
2205
    }
9 mjames 2206
    count--;
2207
 
2 mjames 2208
    /* While card is not ready for data and trial number for sending CMD13 is not exceeded */
2209
    errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2210
    if(errorstate != HAL_MMC_ERROR_NONE)
2211
    {
2212
      hmmc->ErrorCode |= errorstate;
2213
    }
9 mjames 2214
 
2 mjames 2215
    /* Get command response */
2216
    response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2217
  }
9 mjames 2218
 
2 mjames 2219
  if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2220
  {
2221
    /* Clear all the static flags */
2222
    __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2223
    hmmc->State = HAL_MMC_STATE_READY;
2224
    return HAL_ERROR;
2225
  }
2226
  else
2227
  {
2228
    /* Configure the SDIO peripheral */
2229
    Init.ClockEdge           = hmmc->Init.ClockEdge;
2230
    Init.ClockBypass         = hmmc->Init.ClockBypass;
2231
    Init.ClockPowerSave      = hmmc->Init.ClockPowerSave;
2232
    Init.BusWide             = WideMode;
2233
    Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl;
2234
    Init.ClockDiv            = hmmc->Init.ClockDiv;
9 mjames 2235
    (void)SDIO_Init(hmmc->Instance, Init);
2 mjames 2236
  }
2237
 
2238
  /* Change State */
2239
  hmmc->State = HAL_MMC_STATE_READY;
9 mjames 2240
 
2 mjames 2241
  return HAL_OK;
2242
}
2243
 
2244
/**
2245
  * @brief  Gets the current mmc card data state.
2246
  * @param  hmmc: pointer to MMC handle
2247
  * @retval Card state
2248
  */
2249
HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
2250
{
9 mjames 2251
  uint32_t cardstate;
2252
  uint32_t errorstate;
2 mjames 2253
  uint32_t resp1 = 0U;
9 mjames 2254
 
2 mjames 2255
  errorstate = MMC_SendStatus(hmmc, &resp1);
9 mjames 2256
  if(errorstate != HAL_MMC_ERROR_NONE)
2 mjames 2257
  {
2258
    hmmc->ErrorCode |= errorstate;
2259
  }
2260
 
9 mjames 2261
  cardstate = ((resp1 >> 9U) & 0x0FU);
2262
 
2263
  return (HAL_MMC_CardStateTypeDef)cardstate;
2 mjames 2264
}
2265
 
2266
/**
2267
  * @brief  Abort the current transfer and disable the MMC.
2268
  * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2269
  *                the configuration information for MMC module.
2270
  * @retval HAL status
2271
  */
2272
HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
2273
{
2274
  HAL_MMC_CardStateTypeDef CardState;
9 mjames 2275
 
2 mjames 2276
  /* DIsable All interrupts */
2277
  __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
9 mjames 2278
                             SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
2279
 
2 mjames 2280
  /* Clear All flags */
9 mjames 2281
  __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2282
 
2 mjames 2283
  if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2284
  {
2285
    /* Disable the MMC DMA request */
2286
    hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
2287
 
2288
    /* Abort the MMC DMA Tx Stream */
2289
    if(hmmc->hdmatx != NULL)
2290
    {
9 mjames 2291
      if(HAL_DMA_Abort(hmmc->hdmatx) != HAL_OK)
2292
      {
2293
        hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2294
      }
2 mjames 2295
    }
2296
    /* Abort the MMC DMA Rx Stream */
2297
    if(hmmc->hdmarx != NULL)
2298
    {
9 mjames 2299
      if(HAL_DMA_Abort(hmmc->hdmarx) != HAL_OK)
2300
      {
2301
        hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2302
      }
2 mjames 2303
    }
2304
  }
9 mjames 2305
 
2 mjames 2306
  hmmc->State = HAL_MMC_STATE_READY;
9 mjames 2307
 
2308
  /* Initialize the MMC operation */
2309
  hmmc->Context = MMC_CONTEXT_NONE;
2310
 
2 mjames 2311
  CardState = HAL_MMC_GetCardState(hmmc);
2312
  if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2313
  {
2314
    hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2315
  }
2316
  if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2317
  {
2318
    return HAL_ERROR;
2319
  }
2320
  return HAL_OK;
2321
}
2322
 
2323
/**
2324
  * @brief  Abort the current transfer and disable the MMC (IT mode).
2325
  * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2326
  *                the configuration information for MMC module.
2327
  * @retval HAL status
2328
  */
2329
HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
2330
{
2331
  HAL_MMC_CardStateTypeDef CardState;
9 mjames 2332
 
2 mjames 2333
  /* DIsable All interrupts */
2334
  __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
2335
                           SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
9 mjames 2336
 
2 mjames 2337
  /* Clear All flags */
9 mjames 2338
  __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2339
 
2 mjames 2340
  if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
2341
  {
2342
    /* Disable the MMC DMA request */
2343
    hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
2344
 
2345
    /* Abort the MMC DMA Tx Stream */
2346
    if(hmmc->hdmatx != NULL)
2347
    {
2348
      hmmc->hdmatx->XferAbortCallback =  MMC_DMATxAbort;
2349
      if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
2350
      {
2351
        hmmc->hdmatx = NULL;
2352
      }
2353
    }
2354
    /* Abort the MMC DMA Rx Stream */
2355
    if(hmmc->hdmarx != NULL)
2356
    {
2357
      hmmc->hdmarx->XferAbortCallback =  MMC_DMARxAbort;
2358
      if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
2359
      {
2360
        hmmc->hdmarx = NULL;
2361
      }
2362
    }
2363
  }
2364
 
2365
  /* No transfer ongoing on both DMA channels*/
2366
  if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
2367
  {
2368
    CardState = HAL_MMC_GetCardState(hmmc);
2369
    hmmc->State = HAL_MMC_STATE_READY;
9 mjames 2370
 
2 mjames 2371
    if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2372
    {
2373
      hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
2374
    }
2375
    if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2376
    {
2377
      return HAL_ERROR;
2378
    }
2379
    else
2380
    {
9 mjames 2381
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2382
      hmmc->AbortCpltCallback(hmmc);
2383
#else
2 mjames 2384
      HAL_MMC_AbortCallback(hmmc);
9 mjames 2385
#endif
2 mjames 2386
    }
2387
  }
9 mjames 2388
 
2 mjames 2389
  return HAL_OK;
2390
}
2391
 
2392
/**
2393
  * @}
2394
  */
9 mjames 2395
 
2 mjames 2396
/**
2397
  * @}
2398
  */
9 mjames 2399
 
2400
/* Private function ----------------------------------------------------------*/
2 mjames 2401
/** @addtogroup MMC_Private_Functions
2402
  * @{
2403
  */
2404
 
2405
/**
2406
  * @brief  DMA MMC transmit process complete callback
2407
  * @param  hdma: DMA handle
2408
  * @retval None
2409
  */
2410
static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)    
2411
{
2412
  MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2413
 
2414
  /* Enable DATAEND Interrupt */
2415
  __HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DATAEND));
2416
}
2417
 
2418
/**
2419
  * @brief  DMA MMC receive process complete callback
2420
  * @param  hdma: DMA handle
2421
  * @retval None
2422
  */
2423
static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)  
2424
{
2425
  MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
9 mjames 2426
  uint32_t errorstate;
2 mjames 2427
 
2428
  /* Send stop command in multiblock write */
2429
  if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
2430
  {
2431
    errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
2432
    if(errorstate != HAL_MMC_ERROR_NONE)
2433
    {
2434
      hmmc->ErrorCode |= errorstate;
9 mjames 2435
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2436
      hmmc->ErrorCallback(hmmc);
2437
#else
2 mjames 2438
      HAL_MMC_ErrorCallback(hmmc);
9 mjames 2439
#endif
2 mjames 2440
    }
2441
  }
2442
 
2443
  /* Disable the DMA transfer for transmit request by setting the DMAEN bit
2444
  in the MMC DCTRL register */
2445
  hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
2446
 
2447
  /* Clear all the static flags */
9 mjames 2448
  __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
2 mjames 2449
 
2450
  hmmc->State = HAL_MMC_STATE_READY;
2451
 
9 mjames 2452
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2453
  hmmc->RxCpltCallback(hmmc);
2454
#else
2 mjames 2455
  HAL_MMC_RxCpltCallback(hmmc);
9 mjames 2456
#endif
2 mjames 2457
}
2458
 
2459
/**
2460
  * @brief  DMA MMC communication error callback
2461
  * @param  hdma: DMA handle
2462
  * @retval None
2463
  */
2464
static void MMC_DMAError(DMA_HandleTypeDef *hdma)  
2465
{
2466
  MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2467
  HAL_MMC_CardStateTypeDef CardState;
9 mjames 2468
  uint32_t RxErrorCode, TxErrorCode;
2 mjames 2469
 
9 mjames 2470
    RxErrorCode = hmmc->hdmarx->ErrorCode;
2471
    TxErrorCode = hmmc->hdmatx->ErrorCode;  
2472
    if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
2 mjames 2473
    {
9 mjames 2474
      /* Clear All flags */
2475
      __HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
2476
 
2477
      /* Disable All interrupts */
2478
      __HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
2479
        SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
2480
 
2481
      hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
2482
      CardState = HAL_MMC_GetCardState(hmmc);
2483
      if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2484
      {
2485
        hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2486
      }
2487
 
2488
      hmmc->State= HAL_MMC_STATE_READY;
2 mjames 2489
    }
2490
 
9 mjames 2491
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2492
    hmmc->ErrorCallback(hmmc);
2493
#else
2494
    HAL_MMC_ErrorCallback(hmmc);
2495
#endif
2 mjames 2496
}
2497
 
2498
/**
2499
  * @brief  DMA MMC Tx Abort callback
2500
  * @param  hdma: DMA handle
2501
  * @retval None
2502
  */
2503
static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)  
2504
{
2505
  MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2506
  HAL_MMC_CardStateTypeDef CardState;
2507
 
2508
  if(hmmc->hdmatx != NULL)
2509
  {
2510
    hmmc->hdmatx = NULL;
2511
  }
2512
 
2513
  /* All DMA channels are aborted */
2514
  if(hmmc->hdmarx == NULL)
2515
  {
2516
    CardState = HAL_MMC_GetCardState(hmmc);
2517
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2518
    hmmc->State = HAL_MMC_STATE_READY;
2519
    if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2520
    {
2521
      hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2522
 
2523
      if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2524
      {
9 mjames 2525
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2526
        hmmc->AbortCpltCallback(hmmc);
2527
#else
2 mjames 2528
        HAL_MMC_AbortCallback(hmmc);
9 mjames 2529
#endif
2 mjames 2530
      }
2531
      else
2532
      {
9 mjames 2533
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2534
        hmmc->ErrorCallback(hmmc);
2535
#else
2 mjames 2536
        HAL_MMC_ErrorCallback(hmmc);
9 mjames 2537
#endif
2 mjames 2538
      }
2539
    }
2540
  }
2541
}
2542
 
2543
/**
2544
  * @brief  DMA MMC Rx Abort callback
2545
  * @param  hdma: DMA handle
2546
  * @retval None
2547
  */
2548
static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)  
2549
{
2550
  MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
2551
  HAL_MMC_CardStateTypeDef CardState;
2552
 
2553
  if(hmmc->hdmarx != NULL)
2554
  {
2555
    hmmc->hdmarx = NULL;
2556
  }
2557
 
2558
  /* All DMA channels are aborted */
2559
  if(hmmc->hdmatx == NULL)
2560
  {
2561
    CardState = HAL_MMC_GetCardState(hmmc);
2562
    hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
2563
    hmmc->State = HAL_MMC_STATE_READY;
2564
    if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
2565
    {
2566
      hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
2567
 
2568
      if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
2569
      {
9 mjames 2570
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2571
        hmmc->AbortCpltCallback(hmmc);
2572
#else
2 mjames 2573
        HAL_MMC_AbortCallback(hmmc);
9 mjames 2574
#endif
2 mjames 2575
      }
2576
      else
2577
      {
9 mjames 2578
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
2579
        hmmc->ErrorCallback(hmmc);
2580
#else
2 mjames 2581
        HAL_MMC_ErrorCallback(hmmc);
9 mjames 2582
#endif
2 mjames 2583
      }
2584
    }
2585
  }
2586
}
2587
 
2588
/**
2589
  * @brief  Initializes the mmc card.
2590
  * @param  hmmc: Pointer to MMC handle
2591
  * @retval MMC Card error state
2592
  */
2593
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
2594
{
2595
  HAL_MMC_CardCSDTypeDef CSD;
9 mjames 2596
  uint32_t errorstate;
2597
  uint16_t mmc_rca = 1U;
2598
 
2 mjames 2599
  /* Check the power State */
9 mjames 2600
  if(SDIO_GetPowerState(hmmc->Instance) == 0U)
2 mjames 2601
  {
2602
    /* Power off */
2603
    return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
2604
  }
9 mjames 2605
 
2 mjames 2606
  /* Send CMD2 ALL_SEND_CID */
2607
  errorstate = SDMMC_CmdSendCID(hmmc->Instance);
2608
  if(errorstate != HAL_MMC_ERROR_NONE)
2609
  {
2610
    return errorstate;
2611
  }
2612
  else
2613
  {
2614
    /* Get Card identification number data */
2615
    hmmc->CID[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2616
    hmmc->CID[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
2617
    hmmc->CID[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
2618
    hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
2619
  }
9 mjames 2620
 
2 mjames 2621
  /* Send CMD3 SET_REL_ADDR with argument 0 */
2622
  /* MMC Card publishes its RCA. */
2623
  errorstate = SDMMC_CmdSetRelAdd(hmmc->Instance, &mmc_rca);
2624
  if(errorstate != HAL_MMC_ERROR_NONE)
2625
  {
2626
    return errorstate;
2627
  }
9 mjames 2628
 
2 mjames 2629
  /* Get the MMC card RCA */
2630
  hmmc->MmcCard.RelCardAdd = mmc_rca;
9 mjames 2631
 
2 mjames 2632
  /* Send CMD9 SEND_CSD with argument as card's RCA */
2633
  errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
2634
  if(errorstate != HAL_MMC_ERROR_NONE)
2635
  {
2636
    return errorstate;
2637
  }
2638
  else
2639
  {
2640
    /* Get Card Specific Data */
2641
    hmmc->CSD[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
2642
    hmmc->CSD[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
2643
    hmmc->CSD[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
2644
    hmmc->CSD[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
2645
  }
9 mjames 2646
 
2 mjames 2647
  /* Get the Card Class */
2648
  hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U);
9 mjames 2649
 
2 mjames 2650
  /* Get CSD parameters */
9 mjames 2651
  if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
2652
  {
2653
    return hmmc->ErrorCode;
2654
  }
2 mjames 2655
 
2656
  /* Select the Card */
9 mjames 2657
  errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
2658
  if(errorstate != HAL_MMC_ERROR_NONE)
2659
  {
2660
    return errorstate;
2661
  }
2 mjames 2662
 
2663
  /* Configure SDIO peripheral interface */
9 mjames 2664
  (void)SDIO_Init(hmmc->Instance, hmmc->Init);
2 mjames 2665
 
2666
  /* All cards are initialized */
2667
  return HAL_MMC_ERROR_NONE;
2668
}
2669
 
2670
/**
2671
  * @brief  Enquires cards about their operating voltage and configures clock
2672
  *         controls and stores MMC information that will be needed in future
2673
  *         in the MMC handle.
2674
  * @param  hmmc: Pointer to MMC handle
2675
  * @retval error state
2676
  */
2677
static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
2678
{
2679
  __IO uint32_t count = 0U;
2680
  uint32_t response = 0U, validvoltage = 0U;
9 mjames 2681
  uint32_t errorstate;
2682
 
2 mjames 2683
  /* CMD0: GO_IDLE_STATE */
2684
  errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
2685
  if(errorstate != HAL_MMC_ERROR_NONE)
2686
  {
2687
    return errorstate;
2688
  }
2689
 
2690
  while(validvoltage == 0U)
2691
  {
2692
    if(count++ == SDMMC_MAX_VOLT_TRIAL)
2693
    {
2694
      return HAL_MMC_ERROR_INVALID_VOLTRANGE;
2695
    }
9 mjames 2696
 
2 mjames 2697
    /* SEND CMD1 APP_CMD with MMC_HIGH_VOLTAGE_RANGE(0xC0FF8000) as argument */
2698
    errorstate = SDMMC_CmdOpCondition(hmmc->Instance, eMMC_HIGH_VOLTAGE_RANGE);
2699
    if(errorstate != HAL_MMC_ERROR_NONE)
2700
    {
2701
      return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
2702
    }
9 mjames 2703
 
2 mjames 2704
    /* Get command response */
2705
    response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
9 mjames 2706
 
2 mjames 2707
    /* Get operating voltage*/
2708
    validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
2709
  }
9 mjames 2710
 
2 mjames 2711
  /* When power routine is finished and command returns valid voltage */
9 mjames 2712
  if (((response & (0xFF000000U)) >> 24) == 0xC0U)
2 mjames 2713
  {
9 mjames 2714
    hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
2 mjames 2715
  }
2716
  else
2717
  {
9 mjames 2718
    hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
2 mjames 2719
  }
9 mjames 2720
 
2 mjames 2721
  return HAL_MMC_ERROR_NONE;
2722
}
2723
 
2724
/**
2725
  * @brief  Turns the SDIO output signals off.
2726
  * @param  hmmc: Pointer to MMC handle
9 mjames 2727
  * @retval None
2 mjames 2728
  */
9 mjames 2729
static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
2 mjames 2730
{
2731
  /* Set Power State to OFF */
9 mjames 2732
  (void)SDIO_PowerState_OFF(hmmc->Instance);
2 mjames 2733
}
2734
 
2735
/**
2736
  * @brief  Returns the current card's status.
2737
  * @param  hmmc: Pointer to MMC handle
9 mjames 2738
  * @param  pCardStatus: pointer to the buffer that will contain the MMC card
2739
  *         status (Card Status register)
2 mjames 2740
  * @retval error state
2741
  */
2742
static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
2743
{
9 mjames 2744
  uint32_t errorstate;
2745
 
2 mjames 2746
  if(pCardStatus == NULL)
2747
  {
2748
    return HAL_MMC_ERROR_PARAM;
2749
  }
9 mjames 2750
 
2 mjames 2751
  /* Send Status command */
2752
  errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
9 mjames 2753
  if(errorstate != HAL_MMC_ERROR_NONE)
2 mjames 2754
  {
2755
    return errorstate;
2756
  }
9 mjames 2757
 
2 mjames 2758
  /* Get MMC card status */
2759
  *pCardStatus = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
9 mjames 2760
 
2 mjames 2761
  return HAL_MMC_ERROR_NONE;
2762
}
2763
 
2764
/**
2765
  * @brief  Wrap up reading in non-blocking mode.
2766
  * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2767
  *              the configuration information.
9 mjames 2768
  * @retval None
2 mjames 2769
  */
9 mjames 2770
static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
2 mjames 2771
{
9 mjames 2772
  uint32_t count, data, dataremaining;
2773
  uint8_t* tmp;
2 mjames 2774
 
9 mjames 2775
  tmp = hmmc->pRxBuffPtr;
2776
  dataremaining = hmmc->RxXferSize;
2777
 
2778
  if (dataremaining > 0U)
2 mjames 2779
  {
9 mjames 2780
    /* Read data from SDIO Rx FIFO */
2781
    for(count = 0U; count < 8U; count++)
2782
    {
2783
      data = SDIO_ReadFIFO(hmmc->Instance);
2784
      *tmp = (uint8_t)(data & 0xFFU);
2785
      tmp++;
2786
      dataremaining--;
2787
      *tmp = (uint8_t)((data >> 8U) & 0xFFU);
2788
      tmp++;
2789
      dataremaining--;
2790
      *tmp = (uint8_t)((data >> 16U) & 0xFFU);
2791
      tmp++;
2792
      dataremaining--;
2793
      *tmp = (uint8_t)((data >> 24U) & 0xFFU);
2794
      tmp++;
2795
      dataremaining--;
2796
    }
2797
 
2798
    hmmc->pRxBuffPtr = tmp;
2799
    hmmc->RxXferSize = dataremaining;
2 mjames 2800
  }
2801
}
2802
 
2803
/**
2804
  * @brief  Wrap up writing in non-blocking mode.
2805
  * @param  hmmc: pointer to a MMC_HandleTypeDef structure that contains
2806
  *              the configuration information.
9 mjames 2807
  * @retval None
2 mjames 2808
  */
9 mjames 2809
static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
2 mjames 2810
{
9 mjames 2811
  uint32_t count, data, dataremaining;
2812
  uint8_t* tmp;
2813
 
2814
  tmp = hmmc->pTxBuffPtr;
2815
  dataremaining = hmmc->TxXferSize;
2816
 
2817
  if (dataremaining > 0U)
2 mjames 2818
  {
9 mjames 2819
    /* Write data to SDIO Tx FIFO */
2820
    for(count = 0U; count < 8U; count++)
2821
    {
2822
      data = (uint32_t)(*tmp);
2823
      tmp++;
2824
      dataremaining--;
2825
      data |= ((uint32_t)(*tmp) << 8U);
2826
      tmp++;
2827
      dataremaining--;
2828
      data |= ((uint32_t)(*tmp) << 16U);
2829
      tmp++;
2830
      dataremaining--;
2831
      data |= ((uint32_t)(*tmp) << 24U);
2832
      tmp++;
2833
      dataremaining--;
2834
      (void)SDIO_WriteFIFO(hmmc->Instance, &data);
2835
    }
2836
 
2837
    hmmc->pTxBuffPtr = tmp;
2838
    hmmc->TxXferSize = dataremaining;
2 mjames 2839
  }
2840
}
2841
 
2842
/**
2843
  * @}
2844
  */
2845
 
9 mjames 2846
#endif /* SDIO */
2 mjames 2847
 
2848
#endif /* HAL_MMC_MODULE_ENABLED */
2849
 
2850
/**
2851
  * @}
2852
  */
2853
 
2854
/**
2855
  * @}
2856
  */
2857
 
2858
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/