STM32H735xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h7xx_hal_mmc.c 00004 * @author MCD Application Team 00005 * @brief MMC card HAL module driver. 00006 * This file provides firmware functions to manage the following 00007 * functionalities of the Secure Digital (MMC) peripheral: 00008 * + Initialization and de-initialization functions 00009 * + IO operation functions 00010 * + Peripheral Control functions 00011 * + MMC card Control functions 00012 * 00013 ****************************************************************************** 00014 * @attention 00015 * 00016 * Copyright (c) 2017 STMicroelectronics. 00017 * All rights reserved. 00018 * 00019 * This software is licensed under terms that can be found in the LICENSE file 00020 * in the root directory of this software component. 00021 * If no LICENSE file comes with this software, it is provided AS-IS. 00022 * 00023 ****************************************************************************** 00024 @verbatim 00025 ============================================================================== 00026 ##### How to use this driver ##### 00027 ============================================================================== 00028 [..] 00029 This driver implements a high level communication layer for read and write from/to 00030 this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by 00031 the user in HAL_MMC_MspInit() function (MSP layer). 00032 Basically, the MSP layer configuration should be the same as we provide in the 00033 examples. 00034 You can easily tailor this configuration according to hardware resources. 00035 00036 [..] 00037 This driver is a generic layered driver for SDMMC memories which uses the HAL 00038 SDMMC driver functions to interface with MMC and eMMC cards devices. 00039 It is used as follows: 00040 00041 (#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API: 00042 (##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE(); 00043 (##) SDMMC pins configuration for MMC card 00044 (+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE(); 00045 (+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init() 00046 and according to your pin assignment; 00047 (##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT() 00048 and HAL_MMC_WriteBlocks_IT() APIs). 00049 (+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority(); 00050 (+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ() 00051 (+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT() 00052 and __HAL_MMC_DISABLE_IT() inside the communication process. 00053 (+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT() 00054 and __HAL_MMC_CLEAR_IT() 00055 (##) No general propose DMA Configuration is needed, an Internal DMA for SDMMC Peripheral are used. 00056 00057 (#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization 00058 00059 00060 *** MMC Card Initialization and configuration *** 00061 ================================================ 00062 [..] 00063 To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes 00064 SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer). 00065 This function provide the following operations: 00066 00067 (#) Initialize the SDMMC peripheral interface with defaullt configuration. 00068 The initialization process is done at 400KHz. You can change or adapt 00069 this frequency by adjusting the "ClockDiv" field. 00070 The MMC Card frequency (SDMMC_CK) is computed as follows: 00071 00072 SDMMC_CK = SDMMCCLK / (2 * ClockDiv) 00073 00074 In initialization mode and according to the MMC Card standard, 00075 make sure that the SDMMC_CK frequency doesn't exceed 400KHz. 00076 00077 This phase of initialization is done through SDMMC_Init() and 00078 SDMMC_PowerState_ON() SDMMC low level APIs. 00079 00080 (#) Initialize the MMC card. The API used is HAL_MMC_InitCard(). 00081 This phase allows the card initialization and identification 00082 and check the MMC Card type (Standard Capacity or High Capacity) 00083 The initialization flow is compatible with MMC standard. 00084 00085 This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case 00086 of plug-off plug-in. 00087 00088 (#) Configure the MMC Card Data transfer frequency. By Default, the card transfer 00089 frequency by adjusting the "ClockDiv" field. 00090 In transfer mode and according to the MMC Card standard, make sure that the 00091 SDMMC_CK frequency doesn't exceed 25MHz and 100MHz in High-speed mode switch. 00092 00093 (#) Select the corresponding MMC Card according to the address read with the step 2. 00094 00095 (#) Configure the MMC Card in wide bus mode: 4-bits data. 00096 00097 *** MMC Card Read operation *** 00098 ============================== 00099 [..] 00100 (+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks(). 00101 This function support only 512-bytes block length (the block size should be 00102 chosen as 512 bytes). 00103 You can choose either one block read operation or multiple block read operation 00104 by adjusting the "NumberOfBlocks" parameter. 00105 After this, you have to ensure that the transfer is done correctly. The check is done 00106 through HAL_MMC_GetCardState() function for MMC card state. 00107 00108 (+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA(). 00109 This function support only 512-bytes block length (the block size should be 00110 chosen as 512 bytes). 00111 You can choose either one block read operation or multiple block read operation 00112 by adjusting the "NumberOfBlocks" parameter. 00113 After this, you have to ensure that the transfer is done correctly. The check is done 00114 through HAL_MMC_GetCardState() function for MMC card state. 00115 You could also check the DMA transfer process through the MMC Rx interrupt event. 00116 00117 (+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT(). 00118 This function allows the read of 512 bytes blocks. 00119 You can choose either one block read operation or multiple block read operation 00120 by adjusting the "NumberOfBlocks" parameter. 00121 After this, you have to ensure that the transfer is done correctly. The check is done 00122 through HAL_MMC_GetCardState() function for MMC card state. 00123 You could also check the IT transfer process through the MMC Rx interrupt event. 00124 00125 *** MMC Card Write operation *** 00126 =============================== 00127 [..] 00128 (+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks(). 00129 This function support only 512-bytes block length (the block size should be 00130 chosen as 512 bytes). 00131 You can choose either one block read operation or multiple block read operation 00132 by adjusting the "NumberOfBlocks" parameter. 00133 After this, you have to ensure that the transfer is done correctly. The check is done 00134 through HAL_MMC_GetCardState() function for MMC card state. 00135 00136 (+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA(). 00137 This function support only 512-bytes block length (the block size should be 00138 chosen as 512 byte). 00139 You can choose either one block read operation or multiple block read operation 00140 by adjusting the "NumberOfBlocks" parameter. 00141 After this, you have to ensure that the transfer is done correctly. The check is done 00142 through HAL_MMC_GetCardState() function for MMC card state. 00143 You could also check the DMA transfer process through the MMC Tx interrupt event. 00144 00145 (+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT(). 00146 This function allows the read of 512 bytes blocks. 00147 You can choose either one block read operation or multiple block read operation 00148 by adjusting the "NumberOfBlocks" parameter. 00149 After this, you have to ensure that the transfer is done correctly. The check is done 00150 through HAL_MMC_GetCardState() function for MMC card state. 00151 You could also check the IT transfer process through the MMC Tx interrupt event. 00152 00153 *** MMC card information *** 00154 =========================== 00155 [..] 00156 (+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo(). 00157 It returns useful information about the MMC card such as block size, card type, 00158 block number ... 00159 00160 *** MMC card CSD register *** 00161 ============================ 00162 [..] 00163 (+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register. 00164 Some of the CSD parameters are useful for card initialization and identification. 00165 00166 *** MMC card CID register *** 00167 ============================ 00168 [..] 00169 (+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register. 00170 Some of the CID parameters are useful for card initialization and identification. 00171 00172 *** MMC HAL driver macros list *** 00173 ================================== 00174 [..] 00175 Below the list of most used macros in MMC HAL driver. 00176 00177 (+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt 00178 (+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt 00179 (+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not 00180 (+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags 00181 00182 [..] 00183 (@) You can refer to the MMC HAL driver header file for more useful macros 00184 00185 *** Callback registration *** 00186 ============================================= 00187 [..] 00188 The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1 00189 allows the user to configure dynamically the driver callbacks. 00190 00191 Use Functions HAL_MMC_RegisterCallback() to register a user callback, 00192 it allows to register following callbacks: 00193 (+) TxCpltCallback : callback when a transmission transfer is completed. 00194 (+) RxCpltCallback : callback when a reception transfer is completed. 00195 (+) ErrorCallback : callback when error occurs. 00196 (+) AbortCpltCallback : callback when abort is completed. 00197 (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed. 00198 (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed. 00199 (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed. 00200 (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed. 00201 (+) MspInitCallback : MMC MspInit. 00202 (+) MspDeInitCallback : MMC MspDeInit. 00203 This function takes as parameters the HAL peripheral handle, the Callback ID 00204 and a pointer to the user callback function. 00205 00206 Use function HAL_MMC_UnRegisterCallback() to reset a callback to the default 00207 weak (surcharged) function. It allows to reset following callbacks: 00208 (+) TxCpltCallback : callback when a transmission transfer is completed. 00209 (+) RxCpltCallback : callback when a reception transfer is completed. 00210 (+) ErrorCallback : callback when error occurs. 00211 (+) AbortCpltCallback : callback when abort is completed. 00212 (+) Read_DMADblBuf0CpltCallback : callback when the DMA reception of first buffer is completed. 00213 (+) Read_DMADblBuf1CpltCallback : callback when the DMA reception of second buffer is completed. 00214 (+) Write_DMADblBuf0CpltCallback : callback when the DMA transmission of first buffer is completed. 00215 (+) Write_DMADblBuf1CpltCallback : callback when the DMA transmission of second buffer is completed. 00216 (+) MspInitCallback : MMC MspInit. 00217 (+) MspDeInitCallback : MMC MspDeInit. 00218 This function) takes as parameters the HAL peripheral handle and the Callback ID. 00219 00220 By default, after the HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET 00221 all callbacks are reset to the corresponding legacy weak (surcharged) functions. 00222 Exception done for MspInit and MspDeInit callbacks that are respectively 00223 reset to the legacy weak (surcharged) functions in the HAL_MMC_Init 00224 and HAL_MMC_DeInit only when these callbacks are null (not registered beforehand). 00225 If not, MspInit or MspDeInit are not null, the HAL_MMC_Init and HAL_MMC_DeInit 00226 keep and use the user MspInit/MspDeInit callbacks (registered beforehand) 00227 00228 Callbacks can be registered/unregistered in READY state only. 00229 Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered 00230 in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used 00231 during the Init/DeInit. 00232 In that case first register the MspInit/MspDeInit user callbacks 00233 using HAL_MMC_RegisterCallback before calling HAL_MMC_DeInit 00234 or HAL_MMC_Init function. 00235 00236 When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or 00237 not defined, the callback registering feature is not available 00238 and weak (surcharged) callbacks are used. 00239 00240 @endverbatim 00241 ****************************************************************************** 00242 */ 00243 00244 /* Includes ------------------------------------------------------------------*/ 00245 #include "stm32h7xx_hal.h" 00246 00247 /** @addtogroup STM32H7xx_HAL_Driver 00248 * @{ 00249 */ 00250 00251 /** @defgroup MMC MMC 00252 * @brief MMC HAL module driver 00253 * @{ 00254 */ 00255 00256 #ifdef HAL_MMC_MODULE_ENABLED 00257 00258 /* Private typedef -----------------------------------------------------------*/ 00259 /* Private define ------------------------------------------------------------*/ 00260 /** @addtogroup MMC_Private_Defines 00261 * @{ 00262 */ 00263 #if defined (VDD_VALUE) && (VDD_VALUE <= 1950U) 00264 #define MMC_VOLTAGE_RANGE EMMC_LOW_VOLTAGE_RANGE 00265 00266 #define MMC_EXT_CSD_PWR_CL_26_INDEX 201 00267 #define MMC_EXT_CSD_PWR_CL_52_INDEX 200 00268 #define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238 00269 00270 #define MMC_EXT_CSD_PWR_CL_26_POS 8 00271 #define MMC_EXT_CSD_PWR_CL_52_POS 0 00272 #define MMC_EXT_CSD_PWR_CL_DDR_52_POS 16 00273 #else 00274 #define MMC_VOLTAGE_RANGE EMMC_HIGH_VOLTAGE_RANGE 00275 00276 #define MMC_EXT_CSD_PWR_CL_26_INDEX 203 00277 #define MMC_EXT_CSD_PWR_CL_52_INDEX 202 00278 #define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239 00279 00280 #define MMC_EXT_CSD_PWR_CL_26_POS 24 00281 #define MMC_EXT_CSD_PWR_CL_52_POS 16 00282 #define MMC_EXT_CSD_PWR_CL_DDR_52_POS 24 00283 #endif /* (VDD_VALUE) && (VDD_VALUE <= 1950U)*/ 00284 00285 #define MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_INDEX 216 00286 #define MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_POS 0 00287 #define MMC_EXT_CSD_S_A_TIMEOUT_INDEX 217 00288 #define MMC_EXT_CSD_S_A_TIMEOUT_POS 8 00289 00290 /* Frequencies used in the driver for clock divider calculation */ 00291 #define MMC_INIT_FREQ 400000U /* Initialization phase : 400 kHz max */ 00292 #define MMC_HIGH_SPEED_FREQ 52000000U /* High speed phase : 52 MHz max */ 00293 /** 00294 * @} 00295 */ 00296 00297 /* Private macro -------------------------------------------------------------*/ 00298 /* Private variables ---------------------------------------------------------*/ 00299 /* Private function prototypes -----------------------------------------------*/ 00300 /* Private functions ---------------------------------------------------------*/ 00301 /** @defgroup MMC_Private_Functions MMC Private Functions 00302 * @{ 00303 */ 00304 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc); 00305 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc); 00306 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus); 00307 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc); 00308 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc); 00309 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc); 00310 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state); 00311 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state); 00312 static HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, 00313 uint32_t Timeout); 00314 static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide, uint32_t Speed); 00315 00316 /** 00317 * @} 00318 */ 00319 /* Exported functions --------------------------------------------------------*/ 00320 /** @addtogroup MMC_Exported_Functions 00321 * @{ 00322 */ 00323 00324 /** @addtogroup MMC_Exported_Functions_Group1 00325 * @brief Initialization and de-initialization functions 00326 * 00327 @verbatim 00328 ============================================================================== 00329 ##### Initialization and de-initialization functions ##### 00330 ============================================================================== 00331 [..] 00332 This section provides functions allowing to initialize/de-initialize the MMC 00333 card device to be ready for use. 00334 00335 @endverbatim 00336 * @{ 00337 */ 00338 00339 /** 00340 * @brief Initializes the MMC according to the specified parameters in the 00341 MMC_HandleTypeDef and create the associated handle. 00342 * @param hmmc: Pointer to the MMC handle 00343 * @retval HAL status 00344 */ 00345 HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc) 00346 { 00347 /* Check the MMC handle allocation */ 00348 if (hmmc == NULL) 00349 { 00350 return HAL_ERROR; 00351 } 00352 00353 /* Check the parameters */ 00354 assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance)); 00355 assert_param(IS_SDMMC_CLOCK_EDGE(hmmc->Init.ClockEdge)); 00356 assert_param(IS_SDMMC_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave)); 00357 assert_param(IS_SDMMC_BUS_WIDE(hmmc->Init.BusWide)); 00358 assert_param(IS_SDMMC_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl)); 00359 assert_param(IS_SDMMC_CLKDIV(hmmc->Init.ClockDiv)); 00360 00361 if (hmmc->State == HAL_MMC_STATE_RESET) 00362 { 00363 /* Allocate lock resource and initialize it */ 00364 hmmc->Lock = HAL_UNLOCKED; 00365 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 00366 /* Reset Callback pointers in HAL_MMC_STATE_RESET only */ 00367 hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback; 00368 hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback; 00369 hmmc->ErrorCallback = HAL_MMC_ErrorCallback; 00370 hmmc->AbortCpltCallback = HAL_MMC_AbortCallback; 00371 hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback; 00372 hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback; 00373 hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback; 00374 hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback; 00375 00376 if (hmmc->MspInitCallback == NULL) 00377 { 00378 hmmc->MspInitCallback = HAL_MMC_MspInit; 00379 } 00380 00381 /* Init the low level hardware */ 00382 hmmc->MspInitCallback(hmmc); 00383 #else 00384 /* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */ 00385 HAL_MMC_MspInit(hmmc); 00386 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 00387 } 00388 00389 hmmc->State = HAL_MMC_STATE_BUSY; 00390 00391 /* Initialize the Card parameters */ 00392 if (HAL_MMC_InitCard(hmmc) == HAL_ERROR) 00393 { 00394 return HAL_ERROR; 00395 } 00396 00397 /* Initialize the error code */ 00398 hmmc->ErrorCode = HAL_DMA_ERROR_NONE; 00399 00400 /* Initialize the MMC operation */ 00401 hmmc->Context = MMC_CONTEXT_NONE; 00402 00403 /* Initialize the MMC state */ 00404 hmmc->State = HAL_MMC_STATE_READY; 00405 00406 /* Configure bus width */ 00407 if (hmmc->Init.BusWide != SDMMC_BUS_WIDE_1B) 00408 { 00409 if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK) 00410 { 00411 return HAL_ERROR; 00412 } 00413 } 00414 00415 return HAL_OK; 00416 } 00417 00418 /** 00419 * @brief Initializes the MMC Card. 00420 * @param hmmc: Pointer to MMC handle 00421 * @note This function initializes the MMC card. It could be used when a card 00422 re-initialization is needed. 00423 * @retval HAL status 00424 */ 00425 HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc) 00426 { 00427 uint32_t errorstate; 00428 MMC_InitTypeDef Init; 00429 uint32_t sdmmc_clk; 00430 00431 /* Default SDMMC peripheral configuration for MMC card initialization */ 00432 Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; 00433 Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE; 00434 Init.BusWide = SDMMC_BUS_WIDE_1B; 00435 Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE; 00436 00437 /* Init Clock should be less or equal to 400Khz*/ 00438 sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC); 00439 if (sdmmc_clk == 0U) 00440 { 00441 hmmc->State = HAL_MMC_STATE_READY; 00442 hmmc->ErrorCode = SDMMC_ERROR_INVALID_PARAMETER; 00443 return HAL_ERROR; 00444 } 00445 Init.ClockDiv = sdmmc_clk / (2U * MMC_INIT_FREQ); 00446 00447 #if (USE_SD_TRANSCEIVER != 0U) 00448 Init.TranceiverPresent = SDMMC_TRANSCEIVER_NOT_PRESENT; 00449 #endif /* USE_SD_TRANSCEIVER */ 00450 00451 /* Initialize SDMMC peripheral interface with default configuration */ 00452 (void)SDMMC_Init(hmmc->Instance, Init); 00453 00454 /* Set Power State to ON */ 00455 (void)SDMMC_PowerState_ON(hmmc->Instance); 00456 00457 /* wait 74 Cycles: required power up waiting time before starting 00458 the MMC initialization sequence */ 00459 sdmmc_clk = sdmmc_clk / (2U * Init.ClockDiv); 00460 HAL_Delay(1U + (74U * 1000U / (sdmmc_clk))); 00461 00462 /* Identify card operating voltage */ 00463 errorstate = MMC_PowerON(hmmc); 00464 if (errorstate != HAL_MMC_ERROR_NONE) 00465 { 00466 hmmc->State = HAL_MMC_STATE_READY; 00467 hmmc->ErrorCode |= errorstate; 00468 return HAL_ERROR; 00469 } 00470 00471 /* Card initialization */ 00472 errorstate = MMC_InitCard(hmmc); 00473 if (errorstate != HAL_MMC_ERROR_NONE) 00474 { 00475 hmmc->State = HAL_MMC_STATE_READY; 00476 hmmc->ErrorCode |= errorstate; 00477 return HAL_ERROR; 00478 } 00479 00480 /* Set Block Size for Card */ 00481 errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE); 00482 if (errorstate != HAL_MMC_ERROR_NONE) 00483 { 00484 /* Clear all the static flags */ 00485 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00486 hmmc->ErrorCode |= errorstate; 00487 hmmc->State = HAL_MMC_STATE_READY; 00488 return HAL_ERROR; 00489 } 00490 00491 return HAL_OK; 00492 } 00493 00494 /** 00495 * @brief De-Initializes the MMC card. 00496 * @param hmmc: Pointer to MMC handle 00497 * @retval HAL status 00498 */ 00499 HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc) 00500 { 00501 /* Check the MMC handle allocation */ 00502 if (hmmc == NULL) 00503 { 00504 return HAL_ERROR; 00505 } 00506 00507 /* Check the parameters */ 00508 assert_param(IS_SDMMC_ALL_INSTANCE(hmmc->Instance)); 00509 00510 hmmc->State = HAL_MMC_STATE_BUSY; 00511 00512 /* Set MMC power state to off */ 00513 MMC_PowerOFF(hmmc); 00514 00515 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 00516 if (hmmc->MspDeInitCallback == NULL) 00517 { 00518 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit; 00519 } 00520 00521 /* DeInit the low level hardware */ 00522 hmmc->MspDeInitCallback(hmmc); 00523 #else 00524 /* De-Initialize the MSP layer */ 00525 HAL_MMC_MspDeInit(hmmc); 00526 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 00527 00528 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 00529 hmmc->State = HAL_MMC_STATE_RESET; 00530 00531 return HAL_OK; 00532 } 00533 00534 00535 /** 00536 * @brief Initializes the MMC MSP. 00537 * @param hmmc: Pointer to MMC handle 00538 * @retval None 00539 */ 00540 __weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc) 00541 { 00542 /* Prevent unused argument(s) compilation warning */ 00543 UNUSED(hmmc); 00544 00545 /* NOTE : This function Should not be modified, when the callback is needed, 00546 the HAL_MMC_MspInit could be implemented in the user file 00547 */ 00548 } 00549 00550 /** 00551 * @brief De-Initialize MMC MSP. 00552 * @param hmmc: Pointer to MMC handle 00553 * @retval None 00554 */ 00555 __weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc) 00556 { 00557 /* Prevent unused argument(s) compilation warning */ 00558 UNUSED(hmmc); 00559 00560 /* NOTE : This function Should not be modified, when the callback is needed, 00561 the HAL_MMC_MspDeInit could be implemented in the user file 00562 */ 00563 } 00564 00565 /** 00566 * @} 00567 */ 00568 00569 /** @addtogroup MMC_Exported_Functions_Group2 00570 * @brief Data transfer functions 00571 * 00572 @verbatim 00573 ============================================================================== 00574 ##### IO operation functions ##### 00575 ============================================================================== 00576 [..] 00577 This subsection provides a set of functions allowing to manage the data 00578 transfer from/to MMC card. 00579 00580 @endverbatim 00581 * @{ 00582 */ 00583 00584 /** 00585 * @brief Reads block(s) from a specified address in a card. The Data transfer 00586 * is managed by polling mode. 00587 * @note This API should be followed by a check on the card state through 00588 * HAL_MMC_GetCardState(). 00589 * @param hmmc: Pointer to MMC handle 00590 * @param pData: pointer to the buffer that will contain the received data 00591 * @param BlockAdd: Block Address from where data is to be read 00592 * @param NumberOfBlocks: Number of MMC blocks to read 00593 * @param Timeout: Specify timeout value 00594 * @retval HAL status 00595 */ 00596 HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, 00597 uint32_t NumberOfBlocks, uint32_t Timeout) 00598 { 00599 SDMMC_DataInitTypeDef config; 00600 uint32_t errorstate; 00601 uint32_t tickstart = HAL_GetTick(); 00602 uint32_t count; 00603 uint32_t data; 00604 uint32_t dataremaining; 00605 uint32_t add = BlockAdd; 00606 uint8_t *tempbuff = pData; 00607 00608 if (NULL == pData) 00609 { 00610 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 00611 return HAL_ERROR; 00612 } 00613 00614 if (hmmc->State == HAL_MMC_STATE_READY) 00615 { 00616 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 00617 00618 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 00619 { 00620 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 00621 return HAL_ERROR; 00622 } 00623 00624 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 00625 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) 00626 & 0x000000FFU) != 0x0U) 00627 { 00628 if ((NumberOfBlocks % 8U) != 0U) 00629 { 00630 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 00631 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 00632 return HAL_ERROR; 00633 } 00634 00635 if ((BlockAdd % 8U) != 0U) 00636 { 00637 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 00638 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 00639 return HAL_ERROR; 00640 } 00641 } 00642 00643 hmmc->State = HAL_MMC_STATE_BUSY; 00644 00645 /* Initialize data control register */ 00646 hmmc->Instance->DCTRL = 0U; 00647 00648 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 00649 { 00650 add *= 512U; 00651 } 00652 00653 /* Configure the MMC DPSM (Data Path State Machine) */ 00654 config.DataTimeOut = SDMMC_DATATIMEOUT; 00655 config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE; 00656 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 00657 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC; 00658 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 00659 config.DPSM = SDMMC_DPSM_DISABLE; 00660 (void)SDMMC_ConfigData(hmmc->Instance, &config); 00661 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 00662 00663 /* Read block(s) in polling mode */ 00664 if (NumberOfBlocks > 1U) 00665 { 00666 hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK; 00667 00668 /* Read Multi Block command */ 00669 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); 00670 } 00671 else 00672 { 00673 hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK; 00674 00675 /* Read Single Block command */ 00676 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add); 00677 } 00678 if (errorstate != HAL_MMC_ERROR_NONE) 00679 { 00680 /* Clear all the static flags */ 00681 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00682 hmmc->ErrorCode |= errorstate; 00683 hmmc->State = HAL_MMC_STATE_READY; 00684 return HAL_ERROR; 00685 } 00686 00687 /* Poll on SDMMC flags */ 00688 dataremaining = config.DataLength; 00689 while (!__HAL_MMC_GET_FLAG(hmmc, 00690 SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND)) 00691 { 00692 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) && (dataremaining >= 32U)) 00693 { 00694 /* Read data from SDMMC Rx FIFO */ 00695 for (count = 0U; count < 8U; count++) 00696 { 00697 data = SDMMC_ReadFIFO(hmmc->Instance); 00698 *tempbuff = (uint8_t)(data & 0xFFU); 00699 tempbuff++; 00700 *tempbuff = (uint8_t)((data >> 8U) & 0xFFU); 00701 tempbuff++; 00702 *tempbuff = (uint8_t)((data >> 16U) & 0xFFU); 00703 tempbuff++; 00704 *tempbuff = (uint8_t)((data >> 24U) & 0xFFU); 00705 tempbuff++; 00706 } 00707 dataremaining -= 32U; 00708 } 00709 00710 if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U)) 00711 { 00712 /* Clear all the static flags */ 00713 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00714 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; 00715 hmmc->State = HAL_MMC_STATE_READY; 00716 return HAL_TIMEOUT; 00717 } 00718 } 00719 __SDMMC_CMDTRANS_DISABLE(hmmc->Instance); 00720 00721 /* Send stop transmission command in case of multiblock read */ 00722 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U)) 00723 { 00724 /* Send stop transmission command */ 00725 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); 00726 if (errorstate != HAL_MMC_ERROR_NONE) 00727 { 00728 /* Clear all the static flags */ 00729 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00730 hmmc->ErrorCode |= errorstate; 00731 hmmc->State = HAL_MMC_STATE_READY; 00732 return HAL_ERROR; 00733 } 00734 } 00735 00736 /* Get error state */ 00737 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT)) 00738 { 00739 /* Clear all the static flags */ 00740 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00741 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 00742 hmmc->State = HAL_MMC_STATE_READY; 00743 return HAL_ERROR; 00744 } 00745 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL)) 00746 { 00747 /* Clear all the static flags */ 00748 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00749 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 00750 hmmc->State = HAL_MMC_STATE_READY; 00751 return HAL_ERROR; 00752 } 00753 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR)) 00754 { 00755 /* Clear all the static flags */ 00756 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00757 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; 00758 hmmc->State = HAL_MMC_STATE_READY; 00759 return HAL_ERROR; 00760 } 00761 else 00762 { 00763 /* Nothing to do */ 00764 } 00765 00766 /* Clear all the static flags */ 00767 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 00768 00769 hmmc->State = HAL_MMC_STATE_READY; 00770 00771 return HAL_OK; 00772 } 00773 else 00774 { 00775 hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY; 00776 return HAL_ERROR; 00777 } 00778 } 00779 00780 /** 00781 * @brief Allows to write block(s) to a specified address in a card. The Data 00782 * transfer is managed by polling mode. 00783 * @note This API should be followed by a check on the card state through 00784 * HAL_MMC_GetCardState(). 00785 * @param hmmc: Pointer to MMC handle 00786 * @param pData: pointer to the buffer that will contain the data to transmit 00787 * @param BlockAdd: Block Address where data will be written 00788 * @param NumberOfBlocks: Number of MMC blocks to write 00789 * @param Timeout: Specify timeout value 00790 * @retval HAL status 00791 */ 00792 HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, 00793 uint32_t NumberOfBlocks, uint32_t Timeout) 00794 { 00795 SDMMC_DataInitTypeDef config; 00796 uint32_t errorstate; 00797 uint32_t tickstart = HAL_GetTick(); 00798 uint32_t count; 00799 uint32_t data; 00800 uint32_t dataremaining; 00801 uint32_t add = BlockAdd; 00802 uint8_t *tempbuff = pData; 00803 00804 if (NULL == pData) 00805 { 00806 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 00807 return HAL_ERROR; 00808 } 00809 00810 if (hmmc->State == HAL_MMC_STATE_READY) 00811 { 00812 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 00813 00814 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 00815 { 00816 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 00817 return HAL_ERROR; 00818 } 00819 00820 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 00821 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 00822 { 00823 if ((NumberOfBlocks % 8U) != 0U) 00824 { 00825 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 00826 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 00827 return HAL_ERROR; 00828 } 00829 00830 if ((BlockAdd % 8U) != 0U) 00831 { 00832 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 00833 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 00834 return HAL_ERROR; 00835 } 00836 } 00837 00838 hmmc->State = HAL_MMC_STATE_BUSY; 00839 00840 /* Initialize data control register */ 00841 hmmc->Instance->DCTRL = 0U; 00842 00843 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 00844 { 00845 add *= 512U; 00846 } 00847 00848 /* Configure the MMC DPSM (Data Path State Machine) */ 00849 config.DataTimeOut = SDMMC_DATATIMEOUT; 00850 config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE; 00851 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 00852 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD; 00853 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 00854 config.DPSM = SDMMC_DPSM_DISABLE; 00855 (void)SDMMC_ConfigData(hmmc->Instance, &config); 00856 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 00857 00858 /* Write Blocks in Polling mode */ 00859 if (NumberOfBlocks > 1U) 00860 { 00861 hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK; 00862 00863 /* Write Multi Block command */ 00864 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); 00865 } 00866 else 00867 { 00868 hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK; 00869 00870 /* Write Single Block command */ 00871 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add); 00872 } 00873 if (errorstate != HAL_MMC_ERROR_NONE) 00874 { 00875 /* Clear all the static flags */ 00876 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00877 hmmc->ErrorCode |= errorstate; 00878 hmmc->State = HAL_MMC_STATE_READY; 00879 return HAL_ERROR; 00880 } 00881 00882 /* Write block(s) in polling mode */ 00883 dataremaining = config.DataLength; 00884 while (!__HAL_MMC_GET_FLAG(hmmc, 00885 SDMMC_FLAG_TXUNDERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND)) 00886 { 00887 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) && (dataremaining >= 32U)) 00888 { 00889 /* Write data to SDMMC Tx FIFO */ 00890 for (count = 0U; count < 8U; count++) 00891 { 00892 data = (uint32_t)(*tempbuff); 00893 tempbuff++; 00894 data |= ((uint32_t)(*tempbuff) << 8U); 00895 tempbuff++; 00896 data |= ((uint32_t)(*tempbuff) << 16U); 00897 tempbuff++; 00898 data |= ((uint32_t)(*tempbuff) << 24U); 00899 tempbuff++; 00900 (void)SDMMC_WriteFIFO(hmmc->Instance, &data); 00901 } 00902 dataremaining -= 32U; 00903 } 00904 00905 if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U)) 00906 { 00907 /* Clear all the static flags */ 00908 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00909 hmmc->ErrorCode |= errorstate; 00910 hmmc->State = HAL_MMC_STATE_READY; 00911 return HAL_TIMEOUT; 00912 } 00913 } 00914 __SDMMC_CMDTRANS_DISABLE(hmmc->Instance); 00915 00916 /* Send stop transmission command in case of multiblock write */ 00917 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) && (NumberOfBlocks > 1U)) 00918 { 00919 /* Send stop transmission command */ 00920 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); 00921 if (errorstate != HAL_MMC_ERROR_NONE) 00922 { 00923 /* Clear all the static flags */ 00924 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00925 hmmc->ErrorCode |= errorstate; 00926 hmmc->State = HAL_MMC_STATE_READY; 00927 return HAL_ERROR; 00928 } 00929 } 00930 00931 /* Get error state */ 00932 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT)) 00933 { 00934 /* Clear all the static flags */ 00935 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00936 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 00937 hmmc->State = HAL_MMC_STATE_READY; 00938 return HAL_ERROR; 00939 } 00940 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL)) 00941 { 00942 /* Clear all the static flags */ 00943 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00944 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 00945 hmmc->State = HAL_MMC_STATE_READY; 00946 return HAL_ERROR; 00947 } 00948 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXUNDERR)) 00949 { 00950 /* Clear all the static flags */ 00951 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 00952 hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN; 00953 hmmc->State = HAL_MMC_STATE_READY; 00954 return HAL_ERROR; 00955 } 00956 else 00957 { 00958 /* Nothing to do */ 00959 } 00960 00961 /* Clear all the static flags */ 00962 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 00963 00964 hmmc->State = HAL_MMC_STATE_READY; 00965 00966 return HAL_OK; 00967 } 00968 else 00969 { 00970 hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY; 00971 return HAL_ERROR; 00972 } 00973 } 00974 00975 /** 00976 * @brief Reads block(s) from a specified address in a card. The Data transfer 00977 * is managed in interrupt mode. 00978 * @note This API should be followed by a check on the card state through 00979 * HAL_MMC_GetCardState(). 00980 * @note You could also check the IT transfer process through the MMC Rx 00981 * interrupt event. 00982 * @param hmmc: Pointer to MMC handle 00983 * @param pData: Pointer to the buffer that will contain the received data 00984 * @param BlockAdd: Block Address from where data is to be read 00985 * @param NumberOfBlocks: Number of blocks to read. 00986 * @retval HAL status 00987 */ 00988 HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, 00989 uint32_t BlockAdd, uint32_t NumberOfBlocks) 00990 { 00991 SDMMC_DataInitTypeDef config; 00992 uint32_t errorstate; 00993 uint32_t add = BlockAdd; 00994 00995 if (NULL == pData) 00996 { 00997 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 00998 return HAL_ERROR; 00999 } 01000 01001 if (hmmc->State == HAL_MMC_STATE_READY) 01002 { 01003 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 01004 01005 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 01006 { 01007 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 01008 return HAL_ERROR; 01009 } 01010 01011 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 01012 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 01013 { 01014 if ((NumberOfBlocks % 8U) != 0U) 01015 { 01016 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 01017 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 01018 return HAL_ERROR; 01019 } 01020 01021 if ((BlockAdd % 8U) != 0U) 01022 { 01023 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 01024 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 01025 return HAL_ERROR; 01026 } 01027 } 01028 01029 hmmc->State = HAL_MMC_STATE_BUSY; 01030 01031 /* Initialize data control register */ 01032 hmmc->Instance->DCTRL = 0U; 01033 01034 hmmc->pRxBuffPtr = pData; 01035 hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks; 01036 01037 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 01038 { 01039 add *= 512U; 01040 } 01041 01042 /* Configure the MMC DPSM (Data Path State Machine) */ 01043 config.DataTimeOut = SDMMC_DATATIMEOUT; 01044 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; 01045 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 01046 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC; 01047 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 01048 config.DPSM = SDMMC_DPSM_DISABLE; 01049 (void)SDMMC_ConfigData(hmmc->Instance, &config); 01050 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 01051 01052 /* Read Blocks in IT mode */ 01053 if (NumberOfBlocks > 1U) 01054 { 01055 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT); 01056 01057 /* Read Multi Block command */ 01058 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); 01059 } 01060 else 01061 { 01062 hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT); 01063 01064 /* Read Single Block command */ 01065 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add); 01066 } 01067 01068 if (errorstate != HAL_MMC_ERROR_NONE) 01069 { 01070 /* Clear all the static flags */ 01071 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01072 hmmc->ErrorCode |= errorstate; 01073 hmmc->State = HAL_MMC_STATE_READY; 01074 return HAL_ERROR; 01075 } 01076 01077 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | 01078 SDMMC_FLAG_RXFIFOHF)); 01079 01080 return HAL_OK; 01081 } 01082 else 01083 { 01084 return HAL_BUSY; 01085 } 01086 } 01087 01088 /** 01089 * @brief Writes block(s) to a specified address in a card. The Data transfer 01090 * is managed in interrupt mode. 01091 * @note This API should be followed by a check on the card state through 01092 * HAL_MMC_GetCardState(). 01093 * @note You could also check the IT transfer process through the MMC Tx 01094 * interrupt event. 01095 * @param hmmc: Pointer to MMC handle 01096 * @param pData: Pointer to the buffer that will contain the data to transmit 01097 * @param BlockAdd: Block Address where data will be written 01098 * @param NumberOfBlocks: Number of blocks to write 01099 * @retval HAL status 01100 */ 01101 HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, 01102 uint32_t BlockAdd, uint32_t NumberOfBlocks) 01103 { 01104 SDMMC_DataInitTypeDef config; 01105 uint32_t errorstate; 01106 uint32_t add = BlockAdd; 01107 01108 if (NULL == pData) 01109 { 01110 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 01111 return HAL_ERROR; 01112 } 01113 01114 if (hmmc->State == HAL_MMC_STATE_READY) 01115 { 01116 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 01117 01118 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 01119 { 01120 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 01121 return HAL_ERROR; 01122 } 01123 01124 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 01125 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 01126 { 01127 if ((NumberOfBlocks % 8U) != 0U) 01128 { 01129 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 01130 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 01131 return HAL_ERROR; 01132 } 01133 01134 if ((BlockAdd % 8U) != 0U) 01135 { 01136 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 01137 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 01138 return HAL_ERROR; 01139 } 01140 } 01141 01142 hmmc->State = HAL_MMC_STATE_BUSY; 01143 01144 /* Initialize data control register */ 01145 hmmc->Instance->DCTRL = 0U; 01146 01147 hmmc->pTxBuffPtr = pData; 01148 hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks; 01149 01150 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 01151 { 01152 add *= 512U; 01153 } 01154 01155 /* Configure the MMC DPSM (Data Path State Machine) */ 01156 config.DataTimeOut = SDMMC_DATATIMEOUT; 01157 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; 01158 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 01159 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD; 01160 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 01161 config.DPSM = SDMMC_DPSM_DISABLE; 01162 (void)SDMMC_ConfigData(hmmc->Instance, &config); 01163 01164 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 01165 01166 /* Write Blocks in Polling mode */ 01167 if (NumberOfBlocks > 1U) 01168 { 01169 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_IT); 01170 01171 /* Write Multi Block command */ 01172 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); 01173 } 01174 else 01175 { 01176 hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT); 01177 01178 /* Write Single Block command */ 01179 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add); 01180 } 01181 if (errorstate != HAL_MMC_ERROR_NONE) 01182 { 01183 /* Clear all the static flags */ 01184 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01185 hmmc->ErrorCode |= errorstate; 01186 hmmc->State = HAL_MMC_STATE_READY; 01187 return HAL_ERROR; 01188 } 01189 01190 /* Enable transfer interrupts */ 01191 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | 01192 SDMMC_FLAG_TXFIFOHE)); 01193 01194 return HAL_OK; 01195 } 01196 else 01197 { 01198 return HAL_BUSY; 01199 } 01200 } 01201 01202 /** 01203 * @brief Reads block(s) from a specified address in a card. The Data transfer 01204 * is managed by DMA mode. 01205 * @note This API should be followed by a check on the card state through 01206 * HAL_MMC_GetCardState(). 01207 * @note You could also check the DMA transfer process through the MMC Rx 01208 * interrupt event. 01209 * @param hmmc: Pointer MMC handle 01210 * @param pData: Pointer to the buffer that will contain the received data 01211 * @param BlockAdd: Block Address from where data is to be read 01212 * @param NumberOfBlocks: Number of blocks to read. 01213 * @retval HAL status 01214 */ 01215 HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, 01216 uint32_t BlockAdd, uint32_t NumberOfBlocks) 01217 { 01218 SDMMC_DataInitTypeDef config; 01219 uint32_t errorstate; 01220 uint32_t add = BlockAdd; 01221 01222 if (NULL == pData) 01223 { 01224 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 01225 return HAL_ERROR; 01226 } 01227 01228 if (hmmc->State == HAL_MMC_STATE_READY) 01229 { 01230 hmmc->ErrorCode = HAL_DMA_ERROR_NONE; 01231 01232 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 01233 { 01234 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 01235 return HAL_ERROR; 01236 } 01237 01238 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 01239 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 01240 { 01241 if ((NumberOfBlocks % 8U) != 0U) 01242 { 01243 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 01244 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 01245 return HAL_ERROR; 01246 } 01247 01248 if ((BlockAdd % 8U) != 0U) 01249 { 01250 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 01251 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 01252 return HAL_ERROR; 01253 } 01254 } 01255 01256 hmmc->State = HAL_MMC_STATE_BUSY; 01257 01258 /* Initialize data control register */ 01259 hmmc->Instance->DCTRL = 0U; 01260 01261 hmmc->pRxBuffPtr = pData; 01262 hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks; 01263 01264 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 01265 { 01266 add *= 512U; 01267 } 01268 01269 /* Configure the MMC DPSM (Data Path State Machine) */ 01270 config.DataTimeOut = SDMMC_DATATIMEOUT; 01271 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; 01272 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 01273 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC; 01274 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 01275 config.DPSM = SDMMC_DPSM_DISABLE; 01276 (void)SDMMC_ConfigData(hmmc->Instance, &config); 01277 01278 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 01279 hmmc->Instance->IDMABASE0 = (uint32_t) pData ; 01280 hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF; 01281 01282 /* Read Blocks in DMA mode */ 01283 if (NumberOfBlocks > 1U) 01284 { 01285 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA); 01286 01287 /* Read Multi Block command */ 01288 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); 01289 } 01290 else 01291 { 01292 hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA); 01293 01294 /* Read Single Block command */ 01295 errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add); 01296 } 01297 if (errorstate != HAL_MMC_ERROR_NONE) 01298 { 01299 /* Clear all the static flags */ 01300 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01301 hmmc->ErrorCode = errorstate; 01302 hmmc->State = HAL_MMC_STATE_READY; 01303 return HAL_ERROR; 01304 } 01305 01306 /* Enable transfer interrupts */ 01307 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND)); 01308 01309 return HAL_OK; 01310 } 01311 else 01312 { 01313 return HAL_BUSY; 01314 } 01315 } 01316 01317 /** 01318 * @brief Writes block(s) to a specified address in a card. The Data transfer 01319 * is managed by DMA mode. 01320 * @note This API should be followed by a check on the card state through 01321 * HAL_MMC_GetCardState(). 01322 * @note You could also check the DMA transfer process through the MMC Tx 01323 * interrupt event. 01324 * @param hmmc: Pointer to MMC handle 01325 * @param pData: Pointer to the buffer that will contain the data to transmit 01326 * @param BlockAdd: Block Address where data will be written 01327 * @param NumberOfBlocks: Number of blocks to write 01328 * @retval HAL status 01329 */ 01330 HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, 01331 uint32_t BlockAdd, uint32_t NumberOfBlocks) 01332 { 01333 SDMMC_DataInitTypeDef config; 01334 uint32_t errorstate; 01335 uint32_t add = BlockAdd; 01336 01337 if (NULL == pData) 01338 { 01339 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 01340 return HAL_ERROR; 01341 } 01342 01343 if (hmmc->State == HAL_MMC_STATE_READY) 01344 { 01345 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 01346 01347 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 01348 { 01349 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 01350 return HAL_ERROR; 01351 } 01352 01353 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 01354 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 01355 { 01356 if ((NumberOfBlocks % 8U) != 0U) 01357 { 01358 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 01359 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 01360 return HAL_ERROR; 01361 } 01362 01363 if ((BlockAdd % 8U) != 0U) 01364 { 01365 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 01366 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 01367 return HAL_ERROR; 01368 } 01369 } 01370 01371 hmmc->State = HAL_MMC_STATE_BUSY; 01372 01373 /* Initialize data control register */ 01374 hmmc->Instance->DCTRL = 0U; 01375 01376 hmmc->pTxBuffPtr = pData; 01377 hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks; 01378 01379 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 01380 { 01381 add *= 512U; 01382 } 01383 01384 /* Configure the MMC DPSM (Data Path State Machine) */ 01385 config.DataTimeOut = SDMMC_DATATIMEOUT; 01386 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; 01387 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 01388 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD; 01389 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 01390 config.DPSM = SDMMC_DPSM_DISABLE; 01391 (void)SDMMC_ConfigData(hmmc->Instance, &config); 01392 01393 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 01394 01395 hmmc->Instance->IDMABASE0 = (uint32_t) pData ; 01396 hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_SINGLE_BUFF; 01397 01398 /* Write Blocks in Polling mode */ 01399 if (NumberOfBlocks > 1U) 01400 { 01401 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA); 01402 01403 /* Write Multi Block command */ 01404 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); 01405 } 01406 else 01407 { 01408 hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA); 01409 01410 /* Write Single Block command */ 01411 errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add); 01412 } 01413 if (errorstate != HAL_MMC_ERROR_NONE) 01414 { 01415 /* Clear all the static flags */ 01416 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01417 hmmc->ErrorCode |= errorstate; 01418 hmmc->State = HAL_MMC_STATE_READY; 01419 return HAL_ERROR; 01420 } 01421 01422 /* Enable transfer interrupts */ 01423 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND)); 01424 01425 return HAL_OK; 01426 } 01427 else 01428 { 01429 return HAL_BUSY; 01430 } 01431 } 01432 01433 /** 01434 * @brief Erases the specified memory area of the given MMC card. 01435 * @note This API should be followed by a check on the card state through 01436 * HAL_MMC_GetCardState(). 01437 * @param hmmc: Pointer to MMC handle 01438 * @param BlockStartAdd: Start Block address 01439 * @param BlockEndAdd: End Block address 01440 * @retval HAL status 01441 */ 01442 HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd) 01443 { 01444 uint32_t errorstate; 01445 uint32_t start_add = BlockStartAdd; 01446 uint32_t end_add = BlockEndAdd; 01447 01448 if (hmmc->State == HAL_MMC_STATE_READY) 01449 { 01450 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 01451 01452 if (end_add < start_add) 01453 { 01454 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 01455 return HAL_ERROR; 01456 } 01457 01458 if (end_add > (hmmc->MmcCard.LogBlockNbr)) 01459 { 01460 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 01461 return HAL_ERROR; 01462 } 01463 01464 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 01465 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) 01466 & 0x000000FFU) != 0x0U) 01467 { 01468 if (((start_add % 8U) != 0U) || ((end_add % 8U) != 0U)) 01469 { 01470 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 01471 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 01472 return HAL_ERROR; 01473 } 01474 } 01475 01476 hmmc->State = HAL_MMC_STATE_BUSY; 01477 01478 /* Check if the card command class supports erase command */ 01479 if (((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U) 01480 { 01481 /* Clear all the static flags */ 01482 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01483 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE; 01484 hmmc->State = HAL_MMC_STATE_READY; 01485 return HAL_ERROR; 01486 } 01487 01488 if ((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) 01489 { 01490 /* Clear all the static flags */ 01491 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01492 hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED; 01493 hmmc->State = HAL_MMC_STATE_READY; 01494 return HAL_ERROR; 01495 } 01496 01497 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 01498 { 01499 start_add *= 512U; 01500 end_add *= 512U; 01501 } 01502 01503 /* Send CMD35 MMC_ERASE_GRP_START with argument as addr */ 01504 errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add); 01505 if (errorstate != HAL_MMC_ERROR_NONE) 01506 { 01507 /* Clear all the static flags */ 01508 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01509 hmmc->ErrorCode |= errorstate; 01510 hmmc->State = HAL_MMC_STATE_READY; 01511 return HAL_ERROR; 01512 } 01513 01514 /* Send CMD36 MMC_ERASE_GRP_END with argument as addr */ 01515 errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add); 01516 if (errorstate != HAL_MMC_ERROR_NONE) 01517 { 01518 /* Clear all the static flags */ 01519 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01520 hmmc->ErrorCode |= errorstate; 01521 hmmc->State = HAL_MMC_STATE_READY; 01522 return HAL_ERROR; 01523 } 01524 01525 /* Send CMD38 ERASE */ 01526 errorstate = SDMMC_CmdErase(hmmc->Instance, 0UL); 01527 if (errorstate != HAL_MMC_ERROR_NONE) 01528 { 01529 /* Clear all the static flags */ 01530 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 01531 hmmc->ErrorCode |= errorstate; 01532 hmmc->State = HAL_MMC_STATE_READY; 01533 return HAL_ERROR; 01534 } 01535 01536 hmmc->State = HAL_MMC_STATE_READY; 01537 01538 return HAL_OK; 01539 } 01540 else 01541 { 01542 return HAL_BUSY; 01543 } 01544 } 01545 01546 /** 01547 * @brief This function handles MMC card interrupt request. 01548 * @param hmmc: Pointer to MMC handle 01549 * @retval None 01550 */ 01551 void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc) 01552 { 01553 uint32_t errorstate; 01554 uint32_t context = hmmc->Context; 01555 01556 /* Check for SDMMC interrupt flags */ 01557 if ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U)) 01558 { 01559 MMC_Read_IT(hmmc); 01560 } 01561 01562 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DATAEND) != RESET) 01563 { 01564 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DATAEND); 01565 01566 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \ 01567 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR | SDMMC_IT_TXFIFOHE | \ 01568 SDMMC_IT_RXFIFOHF); 01569 01570 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC); 01571 __SDMMC_CMDTRANS_DISABLE(hmmc->Instance); 01572 01573 if ((context & MMC_CONTEXT_DMA) != 0U) 01574 { 01575 hmmc->Instance->DLEN = 0; 01576 hmmc->Instance->DCTRL = 0; 01577 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA ; 01578 01579 /* Stop Transfer for Write Multi blocks or Read Multi blocks */ 01580 if (((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) 01581 { 01582 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); 01583 if (errorstate != HAL_MMC_ERROR_NONE) 01584 { 01585 hmmc->ErrorCode |= errorstate; 01586 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01587 hmmc->ErrorCallback(hmmc); 01588 #else 01589 HAL_MMC_ErrorCallback(hmmc); 01590 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01591 } 01592 } 01593 01594 /* Clear all the static flags */ 01595 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 01596 01597 hmmc->State = HAL_MMC_STATE_READY; 01598 if (((context & MMC_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) 01599 { 01600 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01601 hmmc->TxCpltCallback(hmmc); 01602 #else 01603 HAL_MMC_TxCpltCallback(hmmc); 01604 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01605 } 01606 if (((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) 01607 { 01608 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01609 hmmc->RxCpltCallback(hmmc); 01610 #else 01611 HAL_MMC_RxCpltCallback(hmmc); 01612 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01613 } 01614 } 01615 else if ((context & MMC_CONTEXT_IT) != 0U) 01616 { 01617 /* Stop Transfer for Write Multi blocks or Read Multi blocks */ 01618 if (((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)) 01619 { 01620 errorstate = SDMMC_CmdStopTransfer(hmmc->Instance); 01621 if (errorstate != HAL_MMC_ERROR_NONE) 01622 { 01623 hmmc->ErrorCode |= errorstate; 01624 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01625 hmmc->ErrorCallback(hmmc); 01626 #else 01627 HAL_MMC_ErrorCallback(hmmc); 01628 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01629 } 01630 } 01631 01632 /* Clear all the static flags */ 01633 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 01634 01635 hmmc->State = HAL_MMC_STATE_READY; 01636 if (((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U)) 01637 { 01638 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01639 hmmc->RxCpltCallback(hmmc); 01640 #else 01641 HAL_MMC_RxCpltCallback(hmmc); 01642 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01643 } 01644 else 01645 { 01646 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01647 hmmc->TxCpltCallback(hmmc); 01648 #else 01649 HAL_MMC_TxCpltCallback(hmmc); 01650 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01651 } 01652 } 01653 else 01654 { 01655 /* Nothing to do */ 01656 } 01657 } 01658 01659 else if ((__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U)) 01660 { 01661 MMC_Write_IT(hmmc); 01662 } 01663 01664 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL | 01665 SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_RXOVERR | SDMMC_FLAG_TXUNDERR) != RESET) 01666 { 01667 /* Set Error code */ 01668 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DCRCFAIL) != RESET) 01669 { 01670 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 01671 } 01672 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_DTIMEOUT) != RESET) 01673 { 01674 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 01675 } 01676 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_RXOVERR) != RESET) 01677 { 01678 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; 01679 } 01680 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_IT_TXUNDERR) != RESET) 01681 { 01682 hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN; 01683 } 01684 01685 /* Clear All flags */ 01686 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 01687 01688 /* Disable all interrupts */ 01689 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \ 01690 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR); 01691 01692 __SDMMC_CMDTRANS_DISABLE(hmmc->Instance); 01693 hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST; 01694 hmmc->Instance->CMD |= SDMMC_CMD_CMDSTOP; 01695 hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance); 01696 hmmc->Instance->CMD &= ~(SDMMC_CMD_CMDSTOP); 01697 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_DABORT); 01698 01699 if ((context & MMC_CONTEXT_IT) != 0U) 01700 { 01701 /* Set the MMC state to ready to be able to start again the process */ 01702 hmmc->State = HAL_MMC_STATE_READY; 01703 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01704 hmmc->ErrorCallback(hmmc); 01705 #else 01706 HAL_MMC_ErrorCallback(hmmc); 01707 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01708 } 01709 else if ((context & MMC_CONTEXT_DMA) != 0U) 01710 { 01711 if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE) 01712 { 01713 /* Disable Internal DMA */ 01714 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_IDMABTC); 01715 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA; 01716 01717 /* Set the MMC state to ready to be able to start again the process */ 01718 hmmc->State = HAL_MMC_STATE_READY; 01719 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01720 hmmc->ErrorCallback(hmmc); 01721 #else 01722 HAL_MMC_ErrorCallback(hmmc); 01723 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01724 } 01725 } 01726 else 01727 { 01728 /* Nothing to do */ 01729 } 01730 } 01731 01732 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_IDMABTC) != RESET) 01733 { 01734 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_IT_IDMABTC); 01735 if (READ_BIT(hmmc->Instance->IDMACTRL, SDMMC_IDMA_IDMABACT) == 0U) 01736 { 01737 /* Current buffer is buffer0, Transfer complete for buffer1 */ 01738 if ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U) 01739 { 01740 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01741 hmmc->Write_DMADblBuf1CpltCallback(hmmc); 01742 #else 01743 HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(hmmc); 01744 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01745 } 01746 else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */ 01747 { 01748 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01749 hmmc->Read_DMADblBuf1CpltCallback(hmmc); 01750 #else 01751 HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(hmmc); 01752 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01753 } 01754 } 01755 else /* MMC_DMA_BUFFER1 */ 01756 { 01757 /* Current buffer is buffer1, Transfer complete for buffer0 */ 01758 if ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U) 01759 { 01760 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01761 hmmc->Write_DMADblBuf0CpltCallback(hmmc); 01762 #else 01763 HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(hmmc); 01764 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01765 } 01766 else /* MMC_CONTEXT_READ_MULTIPLE_BLOCK */ 01767 { 01768 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01769 hmmc->Read_DMADblBuf0CpltCallback(hmmc); 01770 #else 01771 HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(hmmc); 01772 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 01773 } 01774 } 01775 } 01776 01777 else 01778 { 01779 /* Nothing to do */ 01780 } 01781 } 01782 01783 /** 01784 * @brief return the MMC state 01785 * @param hmmc: Pointer to mmc handle 01786 * @retval HAL state 01787 */ 01788 HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc) 01789 { 01790 return hmmc->State; 01791 } 01792 01793 /** 01794 * @brief Return the MMC error code 01795 * @param hmmc : Pointer to a MMC_HandleTypeDef structure that contains 01796 * the configuration information. 01797 * @retval MMC Error Code 01798 */ 01799 uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc) 01800 { 01801 return hmmc->ErrorCode; 01802 } 01803 01804 /** 01805 * @brief Tx Transfer completed callbacks 01806 * @param hmmc: Pointer to MMC handle 01807 * @retval None 01808 */ 01809 __weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc) 01810 { 01811 /* Prevent unused argument(s) compilation warning */ 01812 UNUSED(hmmc); 01813 01814 /* NOTE : This function should not be modified, when the callback is needed, 01815 the HAL_MMC_TxCpltCallback can be implemented in the user file 01816 */ 01817 } 01818 01819 /** 01820 * @brief Rx Transfer completed callbacks 01821 * @param hmmc: Pointer MMC handle 01822 * @retval None 01823 */ 01824 __weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc) 01825 { 01826 /* Prevent unused argument(s) compilation warning */ 01827 UNUSED(hmmc); 01828 01829 /* NOTE : This function should not be modified, when the callback is needed, 01830 the HAL_MMC_RxCpltCallback can be implemented in the user file 01831 */ 01832 } 01833 01834 /** 01835 * @brief MMC error callbacks 01836 * @param hmmc: Pointer MMC handle 01837 * @retval None 01838 */ 01839 __weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc) 01840 { 01841 /* Prevent unused argument(s) compilation warning */ 01842 UNUSED(hmmc); 01843 01844 /* NOTE : This function should not be modified, when the callback is needed, 01845 the HAL_MMC_ErrorCallback can be implemented in the user file 01846 */ 01847 } 01848 01849 /** 01850 * @brief MMC Abort callbacks 01851 * @param hmmc: Pointer MMC handle 01852 * @retval None 01853 */ 01854 __weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc) 01855 { 01856 /* Prevent unused argument(s) compilation warning */ 01857 UNUSED(hmmc); 01858 01859 /* NOTE : This function should not be modified, when the callback is needed, 01860 the HAL_MMC_AbortCallback can be implemented in the user file 01861 */ 01862 } 01863 01864 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 01865 /** 01866 * @brief Register a User MMC Callback 01867 * To be used instead of the weak (surcharged) predefined callback 01868 * @param hmmc : MMC handle 01869 * @param CallbackId : ID of the callback to be registered 01870 * This parameter can be one of the following values: 01871 * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID 01872 * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID 01873 * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID 01874 * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID 01875 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Rx Double buffer 0 Callback ID 01876 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Rx Double buffer 1 Callback ID 01877 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID 01878 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID 01879 * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID 01880 * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID 01881 * @param pCallback : pointer to the Callback function 01882 * @retval status 01883 */ 01884 HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, 01885 pMMC_CallbackTypeDef pCallback) 01886 { 01887 HAL_StatusTypeDef status = HAL_OK; 01888 01889 if (pCallback == NULL) 01890 { 01891 /* Update the error code */ 01892 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 01893 return HAL_ERROR; 01894 } 01895 01896 /* Process locked */ 01897 __HAL_LOCK(hmmc); 01898 01899 if (hmmc->State == HAL_MMC_STATE_READY) 01900 { 01901 switch (CallbackId) 01902 { 01903 case HAL_MMC_TX_CPLT_CB_ID : 01904 hmmc->TxCpltCallback = pCallback; 01905 break; 01906 case HAL_MMC_RX_CPLT_CB_ID : 01907 hmmc->RxCpltCallback = pCallback; 01908 break; 01909 case HAL_MMC_ERROR_CB_ID : 01910 hmmc->ErrorCallback = pCallback; 01911 break; 01912 case HAL_MMC_ABORT_CB_ID : 01913 hmmc->AbortCpltCallback = pCallback; 01914 break; 01915 case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID : 01916 hmmc->Read_DMADblBuf0CpltCallback = pCallback; 01917 break; 01918 case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID : 01919 hmmc->Read_DMADblBuf1CpltCallback = pCallback; 01920 break; 01921 case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID : 01922 hmmc->Write_DMADblBuf0CpltCallback = pCallback; 01923 break; 01924 case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID : 01925 hmmc->Write_DMADblBuf1CpltCallback = pCallback; 01926 break; 01927 case HAL_MMC_MSP_INIT_CB_ID : 01928 hmmc->MspInitCallback = pCallback; 01929 break; 01930 case HAL_MMC_MSP_DEINIT_CB_ID : 01931 hmmc->MspDeInitCallback = pCallback; 01932 break; 01933 default : 01934 /* Update the error code */ 01935 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 01936 /* update return status */ 01937 status = HAL_ERROR; 01938 break; 01939 } 01940 } 01941 else if (hmmc->State == HAL_MMC_STATE_RESET) 01942 { 01943 switch (CallbackId) 01944 { 01945 case HAL_MMC_MSP_INIT_CB_ID : 01946 hmmc->MspInitCallback = pCallback; 01947 break; 01948 case HAL_MMC_MSP_DEINIT_CB_ID : 01949 hmmc->MspDeInitCallback = pCallback; 01950 break; 01951 default : 01952 /* Update the error code */ 01953 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 01954 /* update return status */ 01955 status = HAL_ERROR; 01956 break; 01957 } 01958 } 01959 else 01960 { 01961 /* Update the error code */ 01962 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 01963 /* update return status */ 01964 status = HAL_ERROR; 01965 } 01966 01967 /* Release Lock */ 01968 __HAL_UNLOCK(hmmc); 01969 return status; 01970 } 01971 01972 /** 01973 * @brief Unregister a User MMC Callback 01974 * MMC Callback is redirected to the weak (surcharged) predefined callback 01975 * @param hmmc : MMC handle 01976 * @param CallbackId : ID of the callback to be unregistered 01977 * This parameter can be one of the following values: 01978 * @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID 01979 * @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID 01980 * @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID 01981 * @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID 01982 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Rx Double buffer 0 Callback ID 01983 * @arg @ref HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Rx Double buffer 1 Callback ID 01984 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID MMC DMA Tx Double buffer 0 Callback ID 01985 * @arg @ref HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID MMC DMA Tx Double buffer 1 Callback ID 01986 * @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID 01987 * @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID 01988 * @retval status 01989 */ 01990 HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId) 01991 { 01992 HAL_StatusTypeDef status = HAL_OK; 01993 01994 /* Process locked */ 01995 __HAL_LOCK(hmmc); 01996 01997 if (hmmc->State == HAL_MMC_STATE_READY) 01998 { 01999 switch (CallbackId) 02000 { 02001 case HAL_MMC_TX_CPLT_CB_ID : 02002 hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback; 02003 break; 02004 case HAL_MMC_RX_CPLT_CB_ID : 02005 hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback; 02006 break; 02007 case HAL_MMC_ERROR_CB_ID : 02008 hmmc->ErrorCallback = HAL_MMC_ErrorCallback; 02009 break; 02010 case HAL_MMC_ABORT_CB_ID : 02011 hmmc->AbortCpltCallback = HAL_MMC_AbortCallback; 02012 break; 02013 case HAL_MMC_READ_DMA_DBL_BUF0_CPLT_CB_ID : 02014 hmmc->Read_DMADblBuf0CpltCallback = HAL_MMCEx_Read_DMADoubleBuf0CpltCallback; 02015 break; 02016 case HAL_MMC_READ_DMA_DBL_BUF1_CPLT_CB_ID : 02017 hmmc->Read_DMADblBuf1CpltCallback = HAL_MMCEx_Read_DMADoubleBuf1CpltCallback; 02018 break; 02019 case HAL_MMC_WRITE_DMA_DBL_BUF0_CPLT_CB_ID : 02020 hmmc->Write_DMADblBuf0CpltCallback = HAL_MMCEx_Write_DMADoubleBuf0CpltCallback; 02021 break; 02022 case HAL_MMC_WRITE_DMA_DBL_BUF1_CPLT_CB_ID : 02023 hmmc->Write_DMADblBuf1CpltCallback = HAL_MMCEx_Write_DMADoubleBuf1CpltCallback; 02024 break; 02025 case HAL_MMC_MSP_INIT_CB_ID : 02026 hmmc->MspInitCallback = HAL_MMC_MspInit; 02027 break; 02028 case HAL_MMC_MSP_DEINIT_CB_ID : 02029 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit; 02030 break; 02031 default : 02032 /* Update the error code */ 02033 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 02034 /* update return status */ 02035 status = HAL_ERROR; 02036 break; 02037 } 02038 } 02039 else if (hmmc->State == HAL_MMC_STATE_RESET) 02040 { 02041 switch (CallbackId) 02042 { 02043 case HAL_MMC_MSP_INIT_CB_ID : 02044 hmmc->MspInitCallback = HAL_MMC_MspInit; 02045 break; 02046 case HAL_MMC_MSP_DEINIT_CB_ID : 02047 hmmc->MspDeInitCallback = HAL_MMC_MspDeInit; 02048 break; 02049 default : 02050 /* Update the error code */ 02051 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 02052 /* update return status */ 02053 status = HAL_ERROR; 02054 break; 02055 } 02056 } 02057 else 02058 { 02059 /* Update the error code */ 02060 hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK; 02061 /* update return status */ 02062 status = HAL_ERROR; 02063 } 02064 02065 /* Release Lock */ 02066 __HAL_UNLOCK(hmmc); 02067 return status; 02068 } 02069 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 02070 02071 /** 02072 * @} 02073 */ 02074 02075 /** @addtogroup MMC_Exported_Functions_Group3 02076 * @brief management functions 02077 * 02078 @verbatim 02079 ============================================================================== 02080 ##### Peripheral Control functions ##### 02081 ============================================================================== 02082 [..] 02083 This subsection provides a set of functions allowing to control the MMC card 02084 operations and get the related information 02085 02086 @endverbatim 02087 * @{ 02088 */ 02089 02090 /** 02091 * @brief Returns information the information of the card which are stored on 02092 * the CID register. 02093 * @param hmmc: Pointer to MMC handle 02094 * @param pCID: Pointer to a HAL_MMC_CIDTypedef structure that 02095 * contains all CID register parameters 02096 * @retval HAL status 02097 */ 02098 HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID) 02099 { 02100 pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U); 02101 02102 pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U); 02103 02104 pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U)); 02105 02106 pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU); 02107 02108 pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U); 02109 02110 pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U)); 02111 02112 pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U); 02113 02114 pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U); 02115 02116 pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U); 02117 02118 pCID->Reserved2 = 1U; 02119 02120 return HAL_OK; 02121 } 02122 02123 /** 02124 * @brief Returns information the information of the card which are stored on 02125 * the CSD register. 02126 * @param hmmc: Pointer to MMC handle 02127 * @param pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that 02128 * contains all CSD register parameters 02129 * @retval HAL status 02130 */ 02131 HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD) 02132 { 02133 uint32_t block_nbr = 0; 02134 02135 pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U); 02136 02137 pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U); 02138 02139 pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U); 02140 02141 pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U); 02142 02143 pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U); 02144 02145 pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU); 02146 02147 pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U); 02148 02149 pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U); 02150 02151 pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U); 02152 02153 pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U); 02154 02155 pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U); 02156 02157 pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U); 02158 02159 pCSD->Reserved2 = 0U; /*!< Reserved */ 02160 02161 if (MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */ 02162 { 02163 return HAL_ERROR; 02164 } 02165 02166 if (hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD) 02167 { 02168 pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U)); 02169 02170 pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U); 02171 02172 pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U); 02173 02174 pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U); 02175 02176 pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U); 02177 02178 pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U); 02179 02180 hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ; 02181 hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U)); 02182 hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU)); 02183 02184 hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U); 02185 hmmc->MmcCard.LogBlockSize = 512U; 02186 } 02187 else if (hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD) 02188 { 02189 hmmc->MmcCard.BlockNbr = block_nbr; 02190 hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr; 02191 hmmc->MmcCard.BlockSize = 512U; 02192 hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize; 02193 } 02194 else 02195 { 02196 /* Clear all the static flags */ 02197 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02198 hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE; 02199 hmmc->State = HAL_MMC_STATE_READY; 02200 return HAL_ERROR; 02201 } 02202 02203 pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U); 02204 02205 pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U); 02206 02207 pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU); 02208 02209 pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U); 02210 02211 pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U); 02212 02213 pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U); 02214 02215 pCSD->MaxWrBlockLen = (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U); 02216 02217 pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U); 02218 02219 pCSD->Reserved3 = 0; 02220 02221 pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U); 02222 02223 pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U); 02224 02225 pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U); 02226 02227 pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U); 02228 02229 pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U); 02230 02231 pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U); 02232 02233 pCSD->ECC = (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U); 02234 02235 pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U); 02236 02237 pCSD->Reserved4 = 1; 02238 02239 return HAL_OK; 02240 } 02241 02242 /** 02243 * @brief Gets the MMC card info. 02244 * @param hmmc: Pointer to MMC handle 02245 * @param pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that 02246 * will contain the MMC card status information 02247 * @retval HAL status 02248 */ 02249 HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo) 02250 { 02251 pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType); 02252 pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class); 02253 pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd); 02254 pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr); 02255 pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize); 02256 pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr); 02257 pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize); 02258 02259 return HAL_OK; 02260 } 02261 02262 /** 02263 * @brief Returns information the information of the card which are stored on 02264 * the Extended CSD register. 02265 * @param hmmc Pointer to MMC handle 02266 * @param pExtCSD Pointer to a memory area (512 bytes) that contains all 02267 * Extended CSD register parameters 02268 * @param Timeout Specify timeout value 02269 * @retval HAL status 02270 */ 02271 HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout) 02272 { 02273 SDMMC_DataInitTypeDef config; 02274 uint32_t errorstate; 02275 uint32_t tickstart = HAL_GetTick(); 02276 uint32_t count; 02277 uint32_t *tmp_buf; 02278 02279 if (NULL == pExtCSD) 02280 { 02281 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 02282 return HAL_ERROR; 02283 } 02284 02285 if (hmmc->State == HAL_MMC_STATE_READY) 02286 { 02287 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 02288 02289 hmmc->State = HAL_MMC_STATE_BUSY; 02290 02291 /* Initialize data control register */ 02292 hmmc->Instance->DCTRL = 0; 02293 02294 /* Initiaize the destination pointer */ 02295 tmp_buf = pExtCSD; 02296 02297 /* Configure the MMC DPSM (Data Path State Machine) */ 02298 config.DataTimeOut = SDMMC_DATATIMEOUT; 02299 config.DataLength = 512U; 02300 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 02301 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC; 02302 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 02303 config.DPSM = SDMMC_DPSM_DISABLE; 02304 (void)SDMMC_ConfigData(hmmc->Instance, &config); 02305 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 02306 02307 /* Send ExtCSD Read command to Card */ 02308 errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0); 02309 if (errorstate != HAL_MMC_ERROR_NONE) 02310 { 02311 /* Clear all the static flags */ 02312 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02313 hmmc->ErrorCode |= errorstate; 02314 hmmc->State = HAL_MMC_STATE_READY; 02315 return HAL_ERROR; 02316 } 02317 02318 /* Poll on SDMMC flags */ 02319 while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | 02320 SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | SDMMC_FLAG_DATAEND)) 02321 { 02322 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF)) 02323 { 02324 /* Read data from SDMMC Rx FIFO */ 02325 for (count = 0U; count < 8U; count++) 02326 { 02327 *tmp_buf = SDMMC_ReadFIFO(hmmc->Instance); 02328 tmp_buf++; 02329 } 02330 } 02331 02332 if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U)) 02333 { 02334 /* Clear all the static flags */ 02335 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02336 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; 02337 hmmc->State = HAL_MMC_STATE_READY; 02338 return HAL_TIMEOUT; 02339 } 02340 } 02341 02342 __SDMMC_CMDTRANS_DISABLE(hmmc->Instance); 02343 02344 /* Get error state */ 02345 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT)) 02346 { 02347 /* Clear all the static flags */ 02348 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02349 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 02350 hmmc->State = HAL_MMC_STATE_READY; 02351 return HAL_ERROR; 02352 } 02353 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL)) 02354 { 02355 /* Clear all the static flags */ 02356 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02357 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 02358 hmmc->State = HAL_MMC_STATE_READY; 02359 return HAL_ERROR; 02360 } 02361 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR)) 02362 { 02363 /* Clear all the static flags */ 02364 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02365 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; 02366 hmmc->State = HAL_MMC_STATE_READY; 02367 return HAL_ERROR; 02368 } 02369 else 02370 { 02371 /* Nothing to do */ 02372 } 02373 02374 /* Clear all the static flags */ 02375 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 02376 hmmc->State = HAL_MMC_STATE_READY; 02377 } 02378 02379 return HAL_OK; 02380 } 02381 02382 /** 02383 * @brief Enables wide bus operation for the requested card if supported by 02384 * card. 02385 * @param hmmc: Pointer to MMC handle 02386 * @param WideMode: Specifies the MMC card wide bus mode 02387 * This parameter can be one of the following values: 02388 * @arg SDMMC_BUS_WIDE_8B: 8-bit data transfer 02389 * @arg SDMMC_BUS_WIDE_4B: 4-bit data transfer 02390 * @arg SDMMC_BUS_WIDE_1B: 1-bit data transfer 02391 * @retval HAL status 02392 */ 02393 HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode) 02394 { 02395 uint32_t count; 02396 SDMMC_InitTypeDef Init; 02397 uint32_t errorstate; 02398 uint32_t response = 0U; 02399 02400 /* Check the parameters */ 02401 assert_param(IS_SDMMC_BUS_WIDE(WideMode)); 02402 02403 /* Change State */ 02404 hmmc->State = HAL_MMC_STATE_BUSY; 02405 02406 /* Check and update the power class if needed */ 02407 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) 02408 { 02409 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) 02410 { 02411 errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_DDR); 02412 } 02413 else 02414 { 02415 errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_HIGH); 02416 } 02417 } 02418 else 02419 { 02420 errorstate = MMC_PwrClassUpdate(hmmc, WideMode, SDMMC_SPEED_MODE_DEFAULT); 02421 } 02422 02423 if (errorstate == HAL_MMC_ERROR_NONE) 02424 { 02425 if (WideMode == SDMMC_BUS_WIDE_8B) 02426 { 02427 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U); 02428 } 02429 else if (WideMode == SDMMC_BUS_WIDE_4B) 02430 { 02431 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U); 02432 } 02433 else if (WideMode == SDMMC_BUS_WIDE_1B) 02434 { 02435 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U); 02436 } 02437 else 02438 { 02439 /* WideMode is not a valid argument*/ 02440 errorstate = HAL_MMC_ERROR_PARAM; 02441 } 02442 02443 /* Check for switch error and violation of the trial number of sending CMD 13 */ 02444 if (errorstate == HAL_MMC_ERROR_NONE) 02445 { 02446 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 02447 count = SDMMC_MAX_TRIAL; 02448 do 02449 { 02450 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 02451 if (errorstate != HAL_MMC_ERROR_NONE) 02452 { 02453 break; 02454 } 02455 02456 /* Get command response */ 02457 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 02458 count--; 02459 } while (((response & 0x100U) == 0U) && (count != 0U)); 02460 02461 /* Check the status after the switch command execution */ 02462 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) 02463 { 02464 /* Check the bit SWITCH_ERROR of the device status */ 02465 if ((response & 0x80U) != 0U) 02466 { 02467 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; 02468 } 02469 else 02470 { 02471 /* Configure the SDMMC peripheral */ 02472 Init = hmmc->Init; 02473 Init.BusWide = WideMode; 02474 (void)SDMMC_Init(hmmc->Instance, Init); 02475 } 02476 } 02477 else if (count == 0U) 02478 { 02479 errorstate = SDMMC_ERROR_TIMEOUT; 02480 } 02481 else 02482 { 02483 /* Nothing to do */ 02484 } 02485 } 02486 } 02487 02488 /* Change State */ 02489 hmmc->State = HAL_MMC_STATE_READY; 02490 02491 if (errorstate != HAL_MMC_ERROR_NONE) 02492 { 02493 /* Clear all the static flags */ 02494 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02495 hmmc->ErrorCode |= errorstate; 02496 return HAL_ERROR; 02497 } 02498 02499 return HAL_OK; 02500 } 02501 02502 /** 02503 * @brief Configure the speed bus mode 02504 * @param hmmc: Pointer to the MMC handle 02505 * @param SpeedMode: Specifies the MMC card speed bus mode 02506 * This parameter can be one of the following values: 02507 * @arg SDMMC_SPEED_MODE_AUTO: Max speed mode supported by the card 02508 * @arg SDMMC_SPEED_MODE_DEFAULT: Default Speed (MMC @ 26MHz) 02509 * @arg SDMMC_SPEED_MODE_HIGH: High Speed (MMC @ 52 MHz) 02510 * @arg SDMMC_SPEED_MODE_DDR: High Speed DDR (MMC DDR @ 52 MHz) 02511 * @retval HAL status 02512 */ 02513 02514 HAL_StatusTypeDef HAL_MMC_ConfigSpeedBusOperation(MMC_HandleTypeDef *hmmc, uint32_t SpeedMode) 02515 { 02516 uint32_t tickstart; 02517 HAL_StatusTypeDef status = HAL_OK; 02518 uint32_t device_type; 02519 uint32_t errorstate; 02520 02521 /* Check the parameters */ 02522 assert_param(IS_SDMMC_SPEED_MODE(SpeedMode)); 02523 02524 /* Change State */ 02525 hmmc->State = HAL_MMC_STATE_BUSY; 02526 02527 /* Field DEVICE_TYPE [196 = 49*4] of Extended CSD register */ 02528 device_type = (hmmc->Ext_CSD[49] & 0x000000FFU); 02529 02530 switch (SpeedMode) 02531 { 02532 case SDMMC_SPEED_MODE_AUTO: 02533 { 02534 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U)) 02535 { 02536 /* High Speed DDR mode allowed */ 02537 errorstate = MMC_HighSpeed(hmmc, ENABLE); 02538 if (errorstate != HAL_MMC_ERROR_NONE) 02539 { 02540 hmmc->ErrorCode |= errorstate; 02541 } 02542 else 02543 { 02544 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_CLKDIV) != 0U) 02545 { 02546 /* DDR mode not supported with CLKDIV = 0 */ 02547 errorstate = MMC_DDR_Mode(hmmc, ENABLE); 02548 if (errorstate != HAL_MMC_ERROR_NONE) 02549 { 02550 hmmc->ErrorCode |= errorstate; 02551 } 02552 } 02553 } 02554 } 02555 else if ((device_type & 0x02U) != 0U) 02556 { 02557 /* High Speed mode allowed */ 02558 errorstate = MMC_HighSpeed(hmmc, ENABLE); 02559 if (errorstate != HAL_MMC_ERROR_NONE) 02560 { 02561 hmmc->ErrorCode |= errorstate; 02562 } 02563 } 02564 else 02565 { 02566 /* Nothing to do : keep current speed */ 02567 } 02568 break; 02569 } 02570 case SDMMC_SPEED_MODE_DDR: 02571 { 02572 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS) != 0U) && ((device_type & 0x04U) != 0U)) 02573 { 02574 /* High Speed DDR mode allowed */ 02575 errorstate = MMC_HighSpeed(hmmc, ENABLE); 02576 if (errorstate != HAL_MMC_ERROR_NONE) 02577 { 02578 hmmc->ErrorCode |= errorstate; 02579 } 02580 else 02581 { 02582 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_CLKDIV) != 0U) 02583 { 02584 /* DDR mode not supported with CLKDIV = 0 */ 02585 errorstate = MMC_DDR_Mode(hmmc, ENABLE); 02586 if (errorstate != HAL_MMC_ERROR_NONE) 02587 { 02588 hmmc->ErrorCode |= errorstate; 02589 } 02590 } 02591 } 02592 } 02593 else 02594 { 02595 /* High Speed DDR mode not allowed */ 02596 hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE; 02597 status = HAL_ERROR; 02598 } 02599 break; 02600 } 02601 case SDMMC_SPEED_MODE_HIGH: 02602 { 02603 if ((device_type & 0x02U) != 0U) 02604 { 02605 /* High Speed mode allowed */ 02606 errorstate = MMC_HighSpeed(hmmc, ENABLE); 02607 if (errorstate != HAL_MMC_ERROR_NONE) 02608 { 02609 hmmc->ErrorCode |= errorstate; 02610 } 02611 } 02612 else 02613 { 02614 /* High Speed mode not allowed */ 02615 hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE; 02616 status = HAL_ERROR; 02617 } 02618 break; 02619 } 02620 case SDMMC_SPEED_MODE_DEFAULT: 02621 { 02622 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) 02623 { 02624 /* High Speed DDR mode activated */ 02625 errorstate = MMC_DDR_Mode(hmmc, DISABLE); 02626 if (errorstate != HAL_MMC_ERROR_NONE) 02627 { 02628 hmmc->ErrorCode |= errorstate; 02629 } 02630 } 02631 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) 02632 { 02633 /* High Speed mode activated */ 02634 errorstate = MMC_HighSpeed(hmmc, DISABLE); 02635 if (errorstate != HAL_MMC_ERROR_NONE) 02636 { 02637 hmmc->ErrorCode |= errorstate; 02638 } 02639 } 02640 break; 02641 } 02642 default: 02643 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 02644 status = HAL_ERROR; 02645 break; 02646 } 02647 02648 /* Verify that MMC card is ready to use after Speed mode switch*/ 02649 tickstart = HAL_GetTick(); 02650 while ((HAL_MMC_GetCardState(hmmc) != HAL_MMC_CARD_TRANSFER)) 02651 { 02652 if ((HAL_GetTick() - tickstart) >= SDMMC_DATATIMEOUT) 02653 { 02654 hmmc->ErrorCode = HAL_MMC_ERROR_TIMEOUT; 02655 hmmc->State = HAL_MMC_STATE_READY; 02656 return HAL_TIMEOUT; 02657 } 02658 } 02659 02660 /* Change State */ 02661 hmmc->State = HAL_MMC_STATE_READY; 02662 return status; 02663 } 02664 02665 /** 02666 * @brief Gets the current mmc card data state. 02667 * @param hmmc: pointer to MMC handle 02668 * @retval Card state 02669 */ 02670 HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc) 02671 { 02672 uint32_t cardstate; 02673 uint32_t errorstate; 02674 uint32_t resp1 = 0U; 02675 02676 errorstate = MMC_SendStatus(hmmc, &resp1); 02677 if (errorstate != HAL_MMC_ERROR_NONE) 02678 { 02679 hmmc->ErrorCode |= errorstate; 02680 } 02681 02682 cardstate = ((resp1 >> 9U) & 0x0FU); 02683 02684 return (HAL_MMC_CardStateTypeDef)cardstate; 02685 } 02686 02687 /** 02688 * @brief Abort the current transfer and disable the MMC. 02689 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains 02690 * the configuration information for MMC module. 02691 * @retval HAL status 02692 */ 02693 HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc) 02694 { 02695 HAL_MMC_CardStateTypeDef CardState; 02696 02697 /* DIsable All interrupts */ 02698 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \ 02699 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR); 02700 02701 /* Clear All flags */ 02702 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 02703 02704 /* If IDMA Context, disable Internal DMA */ 02705 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA; 02706 02707 hmmc->State = HAL_MMC_STATE_READY; 02708 02709 /* Initialize the MMC operation */ 02710 hmmc->Context = MMC_CONTEXT_NONE; 02711 02712 CardState = HAL_MMC_GetCardState(hmmc); 02713 if ((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) 02714 { 02715 hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance); 02716 } 02717 if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE) 02718 { 02719 return HAL_ERROR; 02720 } 02721 return HAL_OK; 02722 } 02723 02724 /** 02725 * @brief Abort the current transfer and disable the MMC (IT mode). 02726 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains 02727 * the configuration information for MMC module. 02728 * @retval HAL status 02729 */ 02730 HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc) 02731 { 02732 HAL_MMC_CardStateTypeDef CardState; 02733 02734 /* DIsable All interrupts */ 02735 __HAL_MMC_DISABLE_IT(hmmc, SDMMC_IT_DATAEND | SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | \ 02736 SDMMC_IT_TXUNDERR | SDMMC_IT_RXOVERR); 02737 02738 /* If IDMA Context, disable Internal DMA */ 02739 hmmc->Instance->IDMACTRL = SDMMC_DISABLE_IDMA; 02740 02741 /* Clear All flags */ 02742 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 02743 02744 CardState = HAL_MMC_GetCardState(hmmc); 02745 hmmc->State = HAL_MMC_STATE_READY; 02746 02747 if ((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING)) 02748 { 02749 hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance); 02750 } 02751 if (hmmc->ErrorCode != HAL_MMC_ERROR_NONE) 02752 { 02753 return HAL_ERROR; 02754 } 02755 else 02756 { 02757 #if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U) 02758 hmmc->AbortCpltCallback(hmmc); 02759 #else 02760 HAL_MMC_AbortCallback(hmmc); 02761 #endif /* USE_HAL_MMC_REGISTER_CALLBACKS */ 02762 } 02763 02764 return HAL_OK; 02765 } 02766 02767 /** 02768 * @brief Perform specific commands sequence for the different type of erase. 02769 * @note This API should be followed by a check on the card state through 02770 * HAL_MMC_GetCardState(). 02771 * @param hmmc Pointer to MMC handle 02772 * @param EraseType Specifies the type of erase to be performed 02773 * This parameter can be one of the following values: 02774 * @arg HAL_MMC_TRIM Erase the write blocks identified by CMD35 & 36 02775 * @arg HAL_MMC_ERASE Erase the erase groups identified by CMD35 & 36 02776 * @arg HAL_MMC_DISCARD Discard the write blocks identified by CMD35 & 36 02777 * @arg HAL_MMC_SECURE_ERASE Perform a secure purge according SRT on the erase groups identified 02778 * by CMD35 & 36 02779 * @arg HAL_MMC_SECURE_TRIM_STEP1 Mark the write blocks identified by CMD35 & 36 for secure erase 02780 * @arg HAL_MMC_SECURE_TRIM_STEP2 Perform a secure purge according SRT on the write blocks 02781 * previously identified 02782 * @param BlockStartAdd Start Block address 02783 * @param BlockEndAdd End Block address 02784 * @retval HAL status 02785 */ 02786 HAL_StatusTypeDef HAL_MMC_EraseSequence(MMC_HandleTypeDef *hmmc, uint32_t EraseType, 02787 uint32_t BlockStartAdd, uint32_t BlockEndAdd) 02788 { 02789 uint32_t errorstate; 02790 uint32_t start_add = BlockStartAdd; 02791 uint32_t end_add = BlockEndAdd; 02792 uint32_t tickstart = HAL_GetTick(); 02793 02794 /* Check the erase type value is correct */ 02795 assert_param(IS_MMC_ERASE_TYPE(EraseType)); 02796 02797 /* Check the coherence between start and end address */ 02798 if (end_add < start_add) 02799 { 02800 hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM; 02801 return HAL_ERROR; 02802 } 02803 02804 /* Check that the end address is not out of range of device memory */ 02805 if (end_add > (hmmc->MmcCard.LogBlockNbr)) 02806 { 02807 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 02808 return HAL_ERROR; 02809 } 02810 02811 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 02812 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 02813 { 02814 if (((start_add % 8U) != 0U) || ((end_add % 8U) != 0U)) 02815 { 02816 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 02817 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 02818 return HAL_ERROR; 02819 } 02820 } 02821 02822 /* Check if the card command class supports erase command */ 02823 if (((hmmc->MmcCard.Class) & SDMMC_CCCC_ERASE) == 0U) 02824 { 02825 hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE; 02826 return HAL_ERROR; 02827 } 02828 02829 /* Check the state of the driver */ 02830 if (hmmc->State == HAL_MMC_STATE_READY) 02831 { 02832 /* Change State */ 02833 hmmc->State = HAL_MMC_STATE_BUSY; 02834 02835 /* Check that the card is not locked */ 02836 if ((SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED) 02837 { 02838 hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED; 02839 hmmc->State = HAL_MMC_STATE_READY; 02840 return HAL_ERROR; 02841 } 02842 02843 /* In case of low capacity card, the address is not block number but bytes */ 02844 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 02845 { 02846 start_add *= 512U; 02847 end_add *= 512U; 02848 } 02849 02850 /* Send CMD35 MMC_ERASE_GRP_START with start address as argument */ 02851 errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add); 02852 if (errorstate == HAL_MMC_ERROR_NONE) 02853 { 02854 /* Send CMD36 MMC_ERASE_GRP_END with end address as argument */ 02855 errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add); 02856 if (errorstate == HAL_MMC_ERROR_NONE) 02857 { 02858 /* Send CMD38 ERASE with erase type as argument */ 02859 errorstate = SDMMC_CmdErase(hmmc->Instance, EraseType); 02860 if (errorstate == HAL_MMC_ERROR_NONE) 02861 { 02862 if ((EraseType == HAL_MMC_SECURE_ERASE) || (EraseType == HAL_MMC_SECURE_TRIM_STEP2)) 02863 { 02864 /* Wait that the device is ready by checking the D0 line */ 02865 while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE)) 02866 { 02867 if ((HAL_GetTick() - tickstart) >= SDMMC_MAXERASETIMEOUT) 02868 { 02869 errorstate = HAL_MMC_ERROR_TIMEOUT; 02870 } 02871 } 02872 02873 /* Clear the flag corresponding to end D0 bus line */ 02874 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END); 02875 } 02876 } 02877 } 02878 } 02879 02880 /* Change State */ 02881 hmmc->State = HAL_MMC_STATE_READY; 02882 02883 /* Manage errors */ 02884 if (errorstate != HAL_MMC_ERROR_NONE) 02885 { 02886 /* Clear all the static flags */ 02887 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02888 hmmc->ErrorCode |= errorstate; 02889 02890 if (errorstate != HAL_MMC_ERROR_TIMEOUT) 02891 { 02892 return HAL_ERROR; 02893 } 02894 else 02895 { 02896 return HAL_TIMEOUT; 02897 } 02898 } 02899 else 02900 { 02901 return HAL_OK; 02902 } 02903 } 02904 else 02905 { 02906 return HAL_BUSY; 02907 } 02908 } 02909 02910 /** 02911 * @brief Perform sanitize operation on the device. 02912 * @note This API should be followed by a check on the card state through 02913 * HAL_MMC_GetCardState(). 02914 * @param hmmc Pointer to MMC handle 02915 * @retval HAL status 02916 */ 02917 HAL_StatusTypeDef HAL_MMC_Sanitize(MMC_HandleTypeDef *hmmc) 02918 { 02919 uint32_t errorstate; 02920 uint32_t response = 0U; 02921 uint32_t count; 02922 uint32_t tickstart = HAL_GetTick(); 02923 02924 /* Check the state of the driver */ 02925 if (hmmc->State == HAL_MMC_STATE_READY) 02926 { 02927 /* Change State */ 02928 hmmc->State = HAL_MMC_STATE_BUSY; 02929 02930 /* Index : 165 - Value : 0x01 */ 02931 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03A50100U); 02932 if (errorstate == HAL_MMC_ERROR_NONE) 02933 { 02934 /* Wait that the device is ready by checking the D0 line */ 02935 while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE)) 02936 { 02937 if ((HAL_GetTick() - tickstart) >= SDMMC_MAXERASETIMEOUT) 02938 { 02939 errorstate = HAL_MMC_ERROR_TIMEOUT; 02940 } 02941 } 02942 02943 /* Clear the flag corresponding to end D0 bus line */ 02944 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END); 02945 02946 if (errorstate == HAL_MMC_ERROR_NONE) 02947 { 02948 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 02949 count = SDMMC_MAX_TRIAL; 02950 do 02951 { 02952 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 02953 if (errorstate != HAL_MMC_ERROR_NONE) 02954 { 02955 break; 02956 } 02957 02958 /* Get command response */ 02959 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 02960 count--; 02961 } while (((response & 0x100U) == 0U) && (count != 0U)); 02962 02963 /* Check the status after the switch command execution */ 02964 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) 02965 { 02966 /* Check the bit SWITCH_ERROR of the device status */ 02967 if ((response & 0x80U) != 0U) 02968 { 02969 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; 02970 } 02971 } 02972 else if (count == 0U) 02973 { 02974 errorstate = SDMMC_ERROR_TIMEOUT; 02975 } 02976 else 02977 { 02978 /* Nothing to do */ 02979 } 02980 } 02981 } 02982 02983 /* Change State */ 02984 hmmc->State = HAL_MMC_STATE_READY; 02985 02986 /* Manage errors */ 02987 if (errorstate != HAL_MMC_ERROR_NONE) 02988 { 02989 /* Clear all the static flags */ 02990 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 02991 hmmc->ErrorCode |= errorstate; 02992 02993 if (errorstate != HAL_MMC_ERROR_TIMEOUT) 02994 { 02995 return HAL_ERROR; 02996 } 02997 else 02998 { 02999 return HAL_TIMEOUT; 03000 } 03001 } 03002 else 03003 { 03004 return HAL_OK; 03005 } 03006 } 03007 else 03008 { 03009 return HAL_BUSY; 03010 } 03011 } 03012 03013 /** 03014 * @brief Configure the Secure Removal Type (SRT) in the Extended CSD register. 03015 * @note This API should be followed by a check on the card state through 03016 * HAL_MMC_GetCardState(). 03017 * @param hmmc Pointer to MMC handle 03018 * @param SRTMode Specifies the type of erase to be performed 03019 * This parameter can be one of the following values: 03020 * @arg HAL_MMC_SRT_ERASE Information removed by an erase 03021 * @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character 03022 * followed by an erase 03023 * @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character, 03024 * its complement then a random character 03025 * @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined 03026 * @retval HAL status 03027 */ 03028 HAL_StatusTypeDef HAL_MMC_ConfigSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t SRTMode) 03029 { 03030 uint32_t srt; 03031 uint32_t errorstate; 03032 uint32_t response = 0U; 03033 uint32_t count; 03034 03035 /* Check the erase type value is correct */ 03036 assert_param(IS_MMC_SRT_TYPE(SRTMode)); 03037 03038 /* Check the state of the driver */ 03039 if (hmmc->State == HAL_MMC_STATE_READY) 03040 { 03041 /* Get the supported values by the device */ 03042 if (HAL_MMC_GetSupportedSecRemovalType(hmmc, &srt) == HAL_OK) 03043 { 03044 /* Change State */ 03045 hmmc->State = HAL_MMC_STATE_BUSY; 03046 03047 /* Check the value passed as parameter is supported by the device */ 03048 if ((SRTMode & srt) != 0U) 03049 { 03050 /* Index : 16 - Value : SRTMode */ 03051 srt |= ((POSITION_VAL(SRTMode)) << 4U); 03052 errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03100000U | (srt << 8U))); 03053 if (errorstate == HAL_MMC_ERROR_NONE) 03054 { 03055 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03056 count = SDMMC_MAX_TRIAL; 03057 do 03058 { 03059 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03060 if (errorstate != HAL_MMC_ERROR_NONE) 03061 { 03062 break; 03063 } 03064 03065 /* Get command response */ 03066 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03067 count--; 03068 } while (((response & 0x100U) == 0U) && (count != 0U)); 03069 03070 /* Check the status after the switch command execution */ 03071 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) 03072 { 03073 /* Check the bit SWITCH_ERROR of the device status */ 03074 if ((response & 0x80U) != 0U) 03075 { 03076 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; 03077 } 03078 } 03079 else if (count == 0U) 03080 { 03081 errorstate = SDMMC_ERROR_TIMEOUT; 03082 } 03083 else 03084 { 03085 /* Nothing to do */ 03086 } 03087 } 03088 } 03089 else 03090 { 03091 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 03092 } 03093 03094 /* Change State */ 03095 hmmc->State = HAL_MMC_STATE_READY; 03096 } 03097 else 03098 { 03099 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; 03100 } 03101 03102 /* Manage errors */ 03103 if (errorstate != HAL_MMC_ERROR_NONE) 03104 { 03105 /* Clear all the static flags */ 03106 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03107 hmmc->ErrorCode |= errorstate; 03108 return HAL_ERROR; 03109 } 03110 else 03111 { 03112 return HAL_OK; 03113 } 03114 } 03115 else 03116 { 03117 return HAL_BUSY; 03118 } 03119 } 03120 03121 /** 03122 * @brief Gets the supported values of the the Secure Removal Type (SRT). 03123 * @param hmmc pointer to MMC handle 03124 * @param SupportedSRT pointer for supported SRT value 03125 * This parameter is a bit field of the following values: 03126 * @arg HAL_MMC_SRT_ERASE Information removed by an erase 03127 * @arg HAL_MMC_SRT_WRITE_CHAR_ERASE Information removed by an overwriting with a character followed 03128 * by an erase 03129 * @arg HAL_MMC_SRT_WRITE_CHAR_COMPL_RANDOM Information removed by an overwriting with a character, 03130 * its complement then a random character 03131 * @arg HAL_MMC_SRT_VENDOR_DEFINED Information removed using a vendor defined 03132 * @retval HAL status 03133 */ 03134 HAL_StatusTypeDef HAL_MMC_GetSupportedSecRemovalType(MMC_HandleTypeDef *hmmc, uint32_t *SupportedSRT) 03135 { 03136 /* Check the state of the driver */ 03137 if (hmmc->State == HAL_MMC_STATE_READY) 03138 { 03139 /* Change State */ 03140 hmmc->State = HAL_MMC_STATE_BUSY; 03141 03142 /* Read field SECURE_REMOVAL_TYPE [16 = 4*4] of the Extended CSD register */ 03143 *SupportedSRT = (hmmc->Ext_CSD[4] & 0x0000000FU); /* Bits [3:0] of field 16 */ 03144 03145 /* Change State */ 03146 hmmc->State = HAL_MMC_STATE_READY; 03147 03148 return HAL_OK; 03149 } 03150 else 03151 { 03152 return HAL_BUSY; 03153 } 03154 } 03155 03156 /** 03157 * @brief Switch the device from Standby State to Sleep State. 03158 * @param hmmc pointer to MMC handle 03159 * @retval HAL status 03160 */ 03161 HAL_StatusTypeDef HAL_MMC_SleepDevice(MMC_HandleTypeDef *hmmc) 03162 { 03163 uint32_t errorstate, 03164 sleep_timeout, 03165 timeout, 03166 count, 03167 response = 0U ; 03168 uint32_t tickstart = HAL_GetTick(); 03169 03170 /* Check the state of the driver */ 03171 if (hmmc->State == HAL_MMC_STATE_READY) 03172 { 03173 /* Change State */ 03174 hmmc->State = HAL_MMC_STATE_BUSY; 03175 03176 /* Set the power-off notification to powered-on : Ext_CSD[34] = 1 */ 03177 errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220100U)); 03178 if (errorstate == HAL_MMC_ERROR_NONE) 03179 { 03180 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03181 count = SDMMC_MAX_TRIAL; 03182 do 03183 { 03184 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03185 if (errorstate != HAL_MMC_ERROR_NONE) 03186 { 03187 break; 03188 } 03189 03190 /* Get command response */ 03191 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03192 count--; 03193 } while (((response & 0x100U) == 0U) && (count != 0U)); 03194 03195 /* Check the status after the switch command execution */ 03196 if (count == 0U) 03197 { 03198 errorstate = SDMMC_ERROR_TIMEOUT; 03199 } 03200 else if (errorstate == HAL_MMC_ERROR_NONE) 03201 { 03202 /* Check the bit SWITCH_ERROR of the device status */ 03203 if ((response & 0x80U) != 0U) 03204 { 03205 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 03206 } 03207 else 03208 { 03209 /* Set the power-off notification to sleep notification : Ext_CSD[34] = 4 */ 03210 errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220400U)); 03211 if (errorstate == HAL_MMC_ERROR_NONE) 03212 { 03213 /* Field SLEEP_NOTIFICATION_TIME [216] */ 03214 sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_INDEX / 4)] >> 03215 MMC_EXT_CSD_SLEEP_NOTIFICATION_TIME_POS) & 0x000000FFU); 03216 03217 /* Sleep/Awake Timeout = 10µs * 2^SLEEP_NOTIFICATION_TIME */ 03218 /* In HAL, the tick interrupt occurs each ms */ 03219 if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U)) 03220 { 03221 sleep_timeout = 0x17U; /* Max register value defined is 0x17 */ 03222 } 03223 timeout = (((1UL << sleep_timeout) / 100U) + 1U); 03224 03225 /* Wait that the device is ready by checking the D0 line */ 03226 while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE)) 03227 { 03228 if ((HAL_GetTick() - tickstart) >= timeout) 03229 { 03230 errorstate = SDMMC_ERROR_TIMEOUT; 03231 } 03232 } 03233 03234 /* Clear the flag corresponding to end D0 bus line */ 03235 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END); 03236 03237 if (errorstate == HAL_MMC_ERROR_NONE) 03238 { 03239 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03240 count = SDMMC_MAX_TRIAL; 03241 do 03242 { 03243 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, 03244 (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03245 if (errorstate != HAL_MMC_ERROR_NONE) 03246 { 03247 break; 03248 } 03249 03250 /* Get command response */ 03251 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03252 count--; 03253 } while (((response & 0x100U) == 0U) && (count != 0U)); 03254 03255 /* Check the status after the switch command execution */ 03256 if (count == 0U) 03257 { 03258 errorstate = SDMMC_ERROR_TIMEOUT; 03259 } 03260 else if (errorstate == HAL_MMC_ERROR_NONE) 03261 { 03262 /* Check the bit SWITCH_ERROR of the device status */ 03263 if ((response & 0x80U) != 0U) 03264 { 03265 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 03266 } 03267 else 03268 { 03269 /* Switch the device in stand-by mode */ 03270 (void)SDMMC_CmdSelDesel(hmmc->Instance, 0U); 03271 03272 /* Field S_A_TIEMOUT [217] */ 03273 sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_S_A_TIMEOUT_INDEX / 4)] >> 03274 MMC_EXT_CSD_S_A_TIMEOUT_POS) & 0x000000FFU); 03275 03276 /* Sleep/Awake Timeout = 100ns * 2^S_A_TIMEOUT */ 03277 /* In HAL, the tick interrupt occurs each ms */ 03278 if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U)) 03279 { 03280 sleep_timeout = 0x17U; /* Max register value defined is 0x17 */ 03281 } 03282 timeout = (((1UL << sleep_timeout) / 10000U) + 1U); 03283 03284 if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_STANDBY) 03285 { 03286 /* Send CMD5 CMD_MMC_SLEEP_AWAKE with RCA and SLEEP as argument */ 03287 errorstate = SDMMC_CmdSleepMmc(hmmc->Instance, 03288 ((hmmc->MmcCard.RelCardAdd << 16U) | (0x1U << 15U))); 03289 if (errorstate == HAL_MMC_ERROR_NONE) 03290 { 03291 /* Wait that the device is ready by checking the D0 line */ 03292 while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE)) 03293 { 03294 if ((HAL_GetTick() - tickstart) >= timeout) 03295 { 03296 errorstate = SDMMC_ERROR_TIMEOUT; 03297 } 03298 } 03299 03300 /* Clear the flag corresponding to end D0 bus line */ 03301 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END); 03302 } 03303 } 03304 else 03305 { 03306 errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE; 03307 } 03308 } 03309 } 03310 else 03311 { 03312 /* Nothing to do */ 03313 } 03314 } 03315 } 03316 } 03317 } 03318 else 03319 { 03320 /* Nothing to do */ 03321 } 03322 } 03323 03324 /* Change State */ 03325 hmmc->State = HAL_MMC_STATE_READY; 03326 03327 /* Manage errors */ 03328 if (errorstate != HAL_MMC_ERROR_NONE) 03329 { 03330 /* Clear all the static flags */ 03331 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03332 hmmc->ErrorCode |= errorstate; 03333 03334 if (errorstate != HAL_MMC_ERROR_TIMEOUT) 03335 { 03336 return HAL_ERROR; 03337 } 03338 else 03339 { 03340 return HAL_TIMEOUT; 03341 } 03342 } 03343 else 03344 { 03345 return HAL_OK; 03346 } 03347 } 03348 else 03349 { 03350 return HAL_BUSY; 03351 } 03352 } 03353 03354 /** 03355 * @brief Switch the device from Sleep State to Standby State. 03356 * @param hmmc pointer to MMC handle 03357 * @retval HAL status 03358 */ 03359 HAL_StatusTypeDef HAL_MMC_AwakeDevice(MMC_HandleTypeDef *hmmc) 03360 { 03361 uint32_t errorstate; 03362 uint32_t sleep_timeout; 03363 uint32_t timeout; 03364 uint32_t count; 03365 uint32_t response = 0U; 03366 uint32_t tickstart = HAL_GetTick(); 03367 03368 /* Check the state of the driver */ 03369 if (hmmc->State == HAL_MMC_STATE_READY) 03370 { 03371 /* Change State */ 03372 hmmc->State = HAL_MMC_STATE_BUSY; 03373 03374 /* Field S_A_TIEMOUT [217] */ 03375 sleep_timeout = ((hmmc->Ext_CSD[(MMC_EXT_CSD_S_A_TIMEOUT_INDEX / 4)] >> MMC_EXT_CSD_S_A_TIMEOUT_POS) & 03376 0x000000FFU); 03377 03378 /* Sleep/Awake Timeout = 100ns * 2^S_A_TIMEOUT */ 03379 /* In HAL, the tick interrupt occurs each ms */ 03380 if ((sleep_timeout == 0U) || (sleep_timeout > 0x17U)) 03381 { 03382 sleep_timeout = 0x17U; /* Max register value defined is 0x17 */ 03383 } 03384 timeout = (((1UL << sleep_timeout) / 10000U) + 1U); 03385 03386 /* Send CMD5 CMD_MMC_SLEEP_AWAKE with RCA and AWAKE as argument */ 03387 errorstate = SDMMC_CmdSleepMmc(hmmc->Instance, (hmmc->MmcCard.RelCardAdd << 16U)); 03388 if (errorstate == HAL_MMC_ERROR_NONE) 03389 { 03390 /* Wait that the device is ready by checking the D0 line */ 03391 while ((!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_BUSYD0END)) && (errorstate == HAL_MMC_ERROR_NONE)) 03392 { 03393 if ((HAL_GetTick() - tickstart) >= timeout) 03394 { 03395 errorstate = SDMMC_ERROR_TIMEOUT; 03396 } 03397 } 03398 03399 /* Clear the flag corresponding to end D0 bus line */ 03400 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_FLAG_BUSYD0END); 03401 03402 if (errorstate == HAL_MMC_ERROR_NONE) 03403 { 03404 if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_STANDBY) 03405 { 03406 /* Switch the device in transfer mode */ 03407 errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (hmmc->MmcCard.RelCardAdd << 16U)); 03408 if (errorstate == HAL_MMC_ERROR_NONE) 03409 { 03410 if (HAL_MMC_GetCardState(hmmc) == HAL_MMC_CARD_TRANSFER) 03411 { 03412 /* Set the power-off notification to powered-on : Ext_CSD[34] = 1 */ 03413 errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03220100U)); 03414 if (errorstate == HAL_MMC_ERROR_NONE) 03415 { 03416 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03417 count = SDMMC_MAX_TRIAL; 03418 do 03419 { 03420 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, 03421 (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03422 if (errorstate != HAL_MMC_ERROR_NONE) 03423 { 03424 break; 03425 } 03426 03427 /* Get command response */ 03428 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03429 count--; 03430 } while (((response & 0x100U) == 0U) && (count != 0U)); 03431 03432 /* Check the status after the switch command execution */ 03433 if (count == 0U) 03434 { 03435 errorstate = SDMMC_ERROR_TIMEOUT; 03436 } 03437 else if (errorstate == HAL_MMC_ERROR_NONE) 03438 { 03439 /* Check the bit SWITCH_ERROR of the device status */ 03440 if ((response & 0x80U) != 0U) 03441 { 03442 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 03443 } 03444 } 03445 else 03446 { 03447 /* NOthing to do */ 03448 } 03449 } 03450 } 03451 else 03452 { 03453 errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE; 03454 } 03455 } 03456 } 03457 else 03458 { 03459 errorstate = SDMMC_ERROR_REQUEST_NOT_APPLICABLE; 03460 } 03461 } 03462 } 03463 03464 /* Change State */ 03465 hmmc->State = HAL_MMC_STATE_READY; 03466 03467 /* Manage errors */ 03468 if (errorstate != HAL_MMC_ERROR_NONE) 03469 { 03470 /* Clear all the static flags */ 03471 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03472 hmmc->ErrorCode |= errorstate; 03473 03474 if (errorstate != HAL_MMC_ERROR_TIMEOUT) 03475 { 03476 return HAL_ERROR; 03477 } 03478 else 03479 { 03480 return HAL_TIMEOUT; 03481 } 03482 } 03483 else 03484 { 03485 return HAL_OK; 03486 } 03487 } 03488 else 03489 { 03490 return HAL_BUSY; 03491 } 03492 } 03493 /** 03494 * @} 03495 */ 03496 03497 /** 03498 * @} 03499 */ 03500 03501 /* Private function ----------------------------------------------------------*/ 03502 /** @addtogroup MMC_Private_Functions 03503 * @{ 03504 */ 03505 03506 03507 /** 03508 * @brief Initializes the mmc card. 03509 * @param hmmc: Pointer to MMC handle 03510 * @retval MMC Card error state 03511 */ 03512 static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc) 03513 { 03514 HAL_MMC_CardCSDTypeDef CSD; 03515 uint32_t errorstate; 03516 uint16_t mmc_rca = 2U; 03517 MMC_InitTypeDef Init; 03518 03519 /* Check the power State */ 03520 if (SDMMC_GetPowerState(hmmc->Instance) == 0U) 03521 { 03522 /* Power off */ 03523 return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE; 03524 } 03525 03526 /* Send CMD2 ALL_SEND_CID */ 03527 errorstate = SDMMC_CmdSendCID(hmmc->Instance); 03528 if (errorstate != HAL_MMC_ERROR_NONE) 03529 { 03530 return errorstate; 03531 } 03532 else 03533 { 03534 /* Get Card identification number data */ 03535 hmmc->CID[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03536 hmmc->CID[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2); 03537 hmmc->CID[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3); 03538 hmmc->CID[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4); 03539 } 03540 03541 /* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */ 03542 /* MMC Card publishes its RCA. */ 03543 errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca); 03544 if (errorstate != HAL_MMC_ERROR_NONE) 03545 { 03546 return errorstate; 03547 } 03548 03549 /* Get the MMC card RCA */ 03550 hmmc->MmcCard.RelCardAdd = mmc_rca; 03551 03552 /* Send CMD9 SEND_CSD with argument as card's RCA */ 03553 errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U)); 03554 if (errorstate != HAL_MMC_ERROR_NONE) 03555 { 03556 return errorstate; 03557 } 03558 else 03559 { 03560 /* Get Card Specific Data */ 03561 hmmc->CSD[0U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03562 hmmc->CSD[1U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2); 03563 hmmc->CSD[2U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP3); 03564 hmmc->CSD[3U] = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP4); 03565 } 03566 03567 /* Get the Card Class */ 03568 hmmc->MmcCard.Class = (SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP2) >> 20U); 03569 03570 /* Select the Card */ 03571 errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03572 if (errorstate != HAL_MMC_ERROR_NONE) 03573 { 03574 return errorstate; 03575 } 03576 03577 /* Get CSD parameters */ 03578 if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK) 03579 { 03580 return hmmc->ErrorCode; 03581 } 03582 03583 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03584 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03585 if (errorstate != HAL_MMC_ERROR_NONE) 03586 { 03587 hmmc->ErrorCode |= errorstate; 03588 } 03589 03590 03591 /* Get Extended CSD parameters */ 03592 if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != HAL_OK) 03593 { 03594 return hmmc->ErrorCode; 03595 } 03596 03597 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03598 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03599 if (errorstate != HAL_MMC_ERROR_NONE) 03600 { 03601 hmmc->ErrorCode |= errorstate; 03602 } 03603 03604 /* Configure the SDMMC peripheral */ 03605 Init = hmmc->Init; 03606 Init.BusWide = SDMMC_BUS_WIDE_1B; 03607 (void)SDMMC_Init(hmmc->Instance, Init); 03608 03609 /* All cards are initialized */ 03610 return HAL_MMC_ERROR_NONE; 03611 } 03612 03613 /** 03614 * @brief Enquires cards about their operating voltage and configures clock 03615 * controls and stores MMC information that will be needed in future 03616 * in the MMC handle. 03617 * @param hmmc: Pointer to MMC handle 03618 * @retval error state 03619 */ 03620 static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc) 03621 { 03622 __IO uint32_t count = 0U; 03623 uint32_t response = 0U; 03624 uint32_t validvoltage = 0U; 03625 uint32_t errorstate; 03626 03627 /* CMD0: GO_IDLE_STATE */ 03628 errorstate = SDMMC_CmdGoIdleState(hmmc->Instance); 03629 if (errorstate != HAL_MMC_ERROR_NONE) 03630 { 03631 return errorstate; 03632 } 03633 03634 while (validvoltage == 0U) 03635 { 03636 if (count++ == SDMMC_MAX_VOLT_TRIAL) 03637 { 03638 return HAL_MMC_ERROR_INVALID_VOLTRANGE; 03639 } 03640 03641 /* SEND CMD1 APP_CMD with voltage range as argument */ 03642 errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE); 03643 if (errorstate != HAL_MMC_ERROR_NONE) 03644 { 03645 return HAL_MMC_ERROR_UNSUPPORTED_FEATURE; 03646 } 03647 03648 /* Get command response */ 03649 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03650 03651 /* Get operating voltage*/ 03652 validvoltage = (((response >> 31U) == 1U) ? 1U : 0U); 03653 } 03654 03655 /* When power routine is finished and command returns valid voltage */ 03656 if (((response & (0xFF000000U)) >> 24) == 0xC0U) 03657 { 03658 hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD; 03659 } 03660 else 03661 { 03662 hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD; 03663 } 03664 03665 return HAL_MMC_ERROR_NONE; 03666 } 03667 03668 /** 03669 * @brief Turns the SDMMC output signals off. 03670 * @param hmmc: Pointer to MMC handle 03671 * @retval None 03672 */ 03673 static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc) 03674 { 03675 /* Set Power State to OFF */ 03676 (void)SDMMC_PowerState_OFF(hmmc->Instance); 03677 } 03678 03679 /** 03680 * @brief Returns the current card's status. 03681 * @param hmmc: Pointer to MMC handle 03682 * @param pCardStatus: pointer to the buffer that will contain the MMC card 03683 * status (Card Status register) 03684 * @retval error state 03685 */ 03686 static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus) 03687 { 03688 uint32_t errorstate; 03689 03690 if (pCardStatus == NULL) 03691 { 03692 return HAL_MMC_ERROR_PARAM; 03693 } 03694 03695 /* Send Status command */ 03696 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U)); 03697 if (errorstate != HAL_MMC_ERROR_NONE) 03698 { 03699 return errorstate; 03700 } 03701 03702 /* Get MMC card status */ 03703 *pCardStatus = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03704 03705 return HAL_MMC_ERROR_NONE; 03706 } 03707 03708 /** 03709 * @brief Reads extended CSD register to get the sectors number of the device 03710 * @param hmmc: Pointer to MMC handle 03711 * @param pFieldData: Pointer to the read buffer 03712 * @param FieldIndex: Index of the field to be read 03713 * @param Timeout: Specify timeout value 03714 * @retval HAL status 03715 */ 03716 static HAL_StatusTypeDef MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, 03717 uint16_t FieldIndex, uint32_t Timeout) 03718 { 03719 SDMMC_DataInitTypeDef config; 03720 uint32_t errorstate; 03721 uint32_t tickstart = HAL_GetTick(); 03722 uint32_t count; 03723 uint32_t i = 0; 03724 uint32_t tmp_data; 03725 03726 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 03727 03728 /* Initialize data control register */ 03729 hmmc->Instance->DCTRL = 0; 03730 03731 /* Configure the MMC DPSM (Data Path State Machine) */ 03732 config.DataTimeOut = SDMMC_DATATIMEOUT; 03733 config.DataLength = 512U; 03734 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 03735 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC; 03736 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 03737 config.DPSM = SDMMC_DPSM_ENABLE; 03738 (void)SDMMC_ConfigData(hmmc->Instance, &config); 03739 03740 /* Set Block Size for Card */ 03741 errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0); 03742 if (errorstate != HAL_MMC_ERROR_NONE) 03743 { 03744 /* Clear all the static flags */ 03745 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03746 hmmc->ErrorCode |= errorstate; 03747 hmmc->State = HAL_MMC_STATE_READY; 03748 return HAL_ERROR; 03749 } 03750 03751 /* Poll on SDMMC flags */ 03752 while (!__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR | SDMMC_FLAG_DCRCFAIL | SDMMC_FLAG_DTIMEOUT | 03753 SDMMC_FLAG_DATAEND)) 03754 { 03755 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXFIFOHF)) 03756 { 03757 /* Read data from SDMMC Rx FIFO */ 03758 for (count = 0U; count < 8U; count++) 03759 { 03760 tmp_data = SDMMC_ReadFIFO(hmmc->Instance); 03761 /* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */ 03762 /* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */ 03763 if ((i + count) == ((uint32_t)FieldIndex / 4U)) 03764 { 03765 *pFieldData = tmp_data; 03766 } 03767 } 03768 i += 8U; 03769 } 03770 03771 if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U)) 03772 { 03773 /* Clear all the static flags */ 03774 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03775 hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT; 03776 hmmc->State = HAL_MMC_STATE_READY; 03777 return HAL_TIMEOUT; 03778 } 03779 } 03780 03781 /* Get error state */ 03782 if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DTIMEOUT)) 03783 { 03784 /* Clear all the static flags */ 03785 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03786 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT; 03787 hmmc->State = HAL_MMC_STATE_READY; 03788 return HAL_ERROR; 03789 } 03790 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_DCRCFAIL)) 03791 { 03792 /* Clear all the static flags */ 03793 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03794 hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL; 03795 hmmc->State = HAL_MMC_STATE_READY; 03796 return HAL_ERROR; 03797 } 03798 else if (__HAL_MMC_GET_FLAG(hmmc, SDMMC_FLAG_RXOVERR)) 03799 { 03800 /* Clear all the static flags */ 03801 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_FLAGS); 03802 hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN; 03803 hmmc->State = HAL_MMC_STATE_READY; 03804 return HAL_ERROR; 03805 } 03806 else 03807 { 03808 /* Nothing to do */ 03809 } 03810 03811 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03812 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16)); 03813 if (errorstate != HAL_MMC_ERROR_NONE) 03814 { 03815 hmmc->ErrorCode |= errorstate; 03816 } 03817 03818 /* Clear all the static flags */ 03819 __HAL_MMC_CLEAR_FLAG(hmmc, SDMMC_STATIC_DATA_FLAGS); 03820 03821 hmmc->State = HAL_MMC_STATE_READY; 03822 03823 return HAL_OK; 03824 } 03825 03826 /** 03827 * @brief Wrap up reading in non-blocking mode. 03828 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains 03829 * the configuration information. 03830 * @retval None 03831 */ 03832 static void MMC_Read_IT(MMC_HandleTypeDef *hmmc) 03833 { 03834 uint32_t count; 03835 uint32_t data; 03836 uint8_t *tmp; 03837 03838 tmp = hmmc->pRxBuffPtr; 03839 03840 if (hmmc->RxXferSize >= 32U) 03841 { 03842 /* Read data from SDMMC Rx FIFO */ 03843 for (count = 0U; count < 8U; count++) 03844 { 03845 data = SDMMC_ReadFIFO(hmmc->Instance); 03846 *tmp = (uint8_t)(data & 0xFFU); 03847 tmp++; 03848 *tmp = (uint8_t)((data >> 8U) & 0xFFU); 03849 tmp++; 03850 *tmp = (uint8_t)((data >> 16U) & 0xFFU); 03851 tmp++; 03852 *tmp = (uint8_t)((data >> 24U) & 0xFFU); 03853 tmp++; 03854 } 03855 03856 hmmc->pRxBuffPtr = tmp; 03857 hmmc->RxXferSize -= 32U; 03858 } 03859 } 03860 03861 /** 03862 * @brief Wrap up writing in non-blocking mode. 03863 * @param hmmc: pointer to a MMC_HandleTypeDef structure that contains 03864 * the configuration information. 03865 * @retval None 03866 */ 03867 static void MMC_Write_IT(MMC_HandleTypeDef *hmmc) 03868 { 03869 uint32_t count; 03870 uint32_t data; 03871 uint8_t *tmp; 03872 03873 tmp = hmmc->pTxBuffPtr; 03874 03875 if (hmmc->TxXferSize >= 32U) 03876 { 03877 /* Write data to SDMMC Tx FIFO */ 03878 for (count = 0U; count < 8U; count++) 03879 { 03880 data = (uint32_t)(*tmp); 03881 tmp++; 03882 data |= ((uint32_t)(*tmp) << 8U); 03883 tmp++; 03884 data |= ((uint32_t)(*tmp) << 16U); 03885 tmp++; 03886 data |= ((uint32_t)(*tmp) << 24U); 03887 tmp++; 03888 (void)SDMMC_WriteFIFO(hmmc->Instance, &data); 03889 } 03890 03891 hmmc->pTxBuffPtr = tmp; 03892 hmmc->TxXferSize -= 32U; 03893 } 03894 } 03895 03896 /** 03897 * @brief Switches the MMC card to high speed mode. 03898 * @param hmmc: MMC handle 03899 * @param state: State of high speed mode 03900 * @retval MMC Card error state 03901 */ 03902 static uint32_t MMC_HighSpeed(MMC_HandleTypeDef *hmmc, FunctionalState state) 03903 { 03904 uint32_t errorstate = HAL_MMC_ERROR_NONE; 03905 uint32_t response = 0U; 03906 uint32_t count; 03907 uint32_t sdmmc_clk; 03908 SDMMC_InitTypeDef Init; 03909 03910 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) != 0U) && (state == DISABLE)) 03911 { 03912 errorstate = MMC_PwrClassUpdate(hmmc, (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS), SDMMC_SPEED_MODE_DEFAULT); 03913 if (errorstate == HAL_MMC_ERROR_NONE) 03914 { 03915 /* Index : 185 - Value : 0 */ 03916 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90000U); 03917 } 03918 } 03919 03920 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_BUSSPEED) == 0U) && (state != DISABLE)) 03921 { 03922 errorstate = MMC_PwrClassUpdate(hmmc, (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS), SDMMC_SPEED_MODE_HIGH); 03923 if (errorstate == HAL_MMC_ERROR_NONE) 03924 { 03925 /* Index : 185 - Value : 1 */ 03926 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B90100U); 03927 } 03928 } 03929 03930 if (errorstate == HAL_MMC_ERROR_NONE) 03931 { 03932 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 03933 count = SDMMC_MAX_TRIAL; 03934 do 03935 { 03936 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 03937 if (errorstate != HAL_MMC_ERROR_NONE) 03938 { 03939 break; 03940 } 03941 03942 /* Get command response */ 03943 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 03944 count--; 03945 } while (((response & 0x100U) == 0U) && (count != 0U)); 03946 03947 /* Check the status after the switch command execution */ 03948 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) 03949 { 03950 /* Check the bit SWITCH_ERROR of the device status */ 03951 if ((response & 0x80U) != 0U) 03952 { 03953 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 03954 } 03955 else 03956 { 03957 /* Configure high speed */ 03958 Init.ClockEdge = hmmc->Init.ClockEdge; 03959 Init.ClockPowerSave = hmmc->Init.ClockPowerSave; 03960 Init.BusWide = (hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS); 03961 Init.HardwareFlowControl = hmmc->Init.HardwareFlowControl; 03962 03963 if (state == DISABLE) 03964 { 03965 Init.ClockDiv = hmmc->Init.ClockDiv; 03966 (void)SDMMC_Init(hmmc->Instance, Init); 03967 03968 CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED); 03969 } 03970 else 03971 { 03972 /* High Speed Clock should be less or equal to 52MHz*/ 03973 sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC); 03974 03975 if (sdmmc_clk == 0U) 03976 { 03977 errorstate = SDMMC_ERROR_INVALID_PARAMETER; 03978 } 03979 else 03980 { 03981 if (sdmmc_clk <= MMC_HIGH_SPEED_FREQ) 03982 { 03983 Init.ClockDiv = 0; 03984 } 03985 else 03986 { 03987 Init.ClockDiv = (sdmmc_clk / (2U * MMC_HIGH_SPEED_FREQ)) + 1U; 03988 } 03989 (void)SDMMC_Init(hmmc->Instance, Init); 03990 03991 SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_BUSSPEED); 03992 } 03993 } 03994 } 03995 } 03996 else if (count == 0U) 03997 { 03998 errorstate = SDMMC_ERROR_TIMEOUT; 03999 } 04000 else 04001 { 04002 /* Nothing to do */ 04003 } 04004 } 04005 04006 return errorstate; 04007 } 04008 04009 /** 04010 * @brief Switches the MMC card to Double Data Rate (DDR) mode. 04011 * @param hmmc: MMC handle 04012 * @param state: State of DDR mode 04013 * @retval MMC Card error state 04014 */ 04015 static uint32_t MMC_DDR_Mode(MMC_HandleTypeDef *hmmc, FunctionalState state) 04016 { 04017 uint32_t errorstate = HAL_MMC_ERROR_NONE; 04018 uint32_t response = 0U; 04019 uint32_t count; 04020 04021 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) != 0U) && (state == DISABLE)) 04022 { 04023 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U) 04024 { 04025 errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_4B, SDMMC_SPEED_MODE_HIGH); 04026 if (errorstate == HAL_MMC_ERROR_NONE) 04027 { 04028 /* Index : 183 - Value : 1 */ 04029 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U); 04030 } 04031 } 04032 else 04033 { 04034 errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_8B, SDMMC_SPEED_MODE_HIGH); 04035 if (errorstate == HAL_MMC_ERROR_NONE) 04036 { 04037 /* Index : 183 - Value : 2 */ 04038 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U); 04039 } 04040 } 04041 } 04042 04043 if (((hmmc->Instance->CLKCR & SDMMC_CLKCR_DDR) == 0U) && (state != DISABLE)) 04044 { 04045 if ((hmmc->Instance->CLKCR & SDMMC_CLKCR_WIDBUS_0) != 0U) 04046 { 04047 errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_4B, SDMMC_SPEED_MODE_DDR); 04048 if (errorstate == HAL_MMC_ERROR_NONE) 04049 { 04050 /* Index : 183 - Value : 5 */ 04051 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70500U); 04052 } 04053 } 04054 else 04055 { 04056 errorstate = MMC_PwrClassUpdate(hmmc, SDMMC_BUS_WIDE_8B, SDMMC_SPEED_MODE_DDR); 04057 if (errorstate == HAL_MMC_ERROR_NONE) 04058 { 04059 /* Index : 183 - Value : 6 */ 04060 errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70600U); 04061 } 04062 } 04063 } 04064 04065 if (errorstate == HAL_MMC_ERROR_NONE) 04066 { 04067 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 04068 count = SDMMC_MAX_TRIAL; 04069 do 04070 { 04071 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 04072 if (errorstate != HAL_MMC_ERROR_NONE) 04073 { 04074 break; 04075 } 04076 04077 /* Get command response */ 04078 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 04079 count--; 04080 } while (((response & 0x100U) == 0U) && (count != 0U)); 04081 04082 /* Check the status after the switch command execution */ 04083 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) 04084 { 04085 /* Check the bit SWITCH_ERROR of the device status */ 04086 if ((response & 0x80U) != 0U) 04087 { 04088 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 04089 } 04090 else 04091 { 04092 /* Configure DDR mode */ 04093 if (state == DISABLE) 04094 { 04095 CLEAR_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR); 04096 } 04097 else 04098 { 04099 SET_BIT(hmmc->Instance->CLKCR, SDMMC_CLKCR_DDR); 04100 } 04101 } 04102 } 04103 else if (count == 0U) 04104 { 04105 errorstate = SDMMC_ERROR_TIMEOUT; 04106 } 04107 else 04108 { 04109 /* Nothing to do */ 04110 } 04111 } 04112 04113 return errorstate; 04114 } 04115 04116 /** 04117 * @brief Update the power class of the device. 04118 * @param hmmc MMC handle 04119 * @param Wide Wide of MMC bus 04120 * @param Speed Speed of the MMC bus 04121 * @retval MMC Card error state 04122 */ 04123 static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide, uint32_t Speed) 04124 { 04125 uint32_t count; 04126 uint32_t response = 0U; 04127 uint32_t errorstate = HAL_MMC_ERROR_NONE; 04128 uint32_t power_class; 04129 uint32_t supported_pwr_class; 04130 04131 if ((Wide == SDMMC_BUS_WIDE_8B) || (Wide == SDMMC_BUS_WIDE_4B)) 04132 { 04133 power_class = 0U; /* Default value after power-on or software reset */ 04134 04135 /* Read the PowerClass field of the Extended CSD register */ 04136 if (MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */ 04137 { 04138 errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR; 04139 } 04140 else 04141 { 04142 power_class = ((power_class >> 24U) & 0x000000FFU); 04143 } 04144 04145 /* Get the supported PowerClass field of the Extended CSD register */ 04146 if (Speed == SDMMC_SPEED_MODE_DDR) 04147 { 04148 /* Field PWR_CL_DDR_52_xxx [238 or 239] */ 04149 supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_DDR_52_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_DDR_52_POS) & 04150 0x000000FFU); 04151 } 04152 else if (Speed == SDMMC_SPEED_MODE_HIGH) 04153 { 04154 /* Field PWR_CL_52_xxx [200 or 202] */ 04155 supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_52_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_52_POS) & 04156 0x000000FFU); 04157 } 04158 else 04159 { 04160 /* Field PWR_CL_26_xxx [201 or 203] */ 04161 supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX / 4)] >> MMC_EXT_CSD_PWR_CL_26_POS) & 04162 0x000000FFU); 04163 } 04164 04165 if (errorstate == HAL_MMC_ERROR_NONE) 04166 { 04167 if (Wide == SDMMC_BUS_WIDE_8B) 04168 { 04169 /* Bit [7:4]: power class for 8-bits bus configuration - Bit [3:0]: power class for 4-bits bus configuration */ 04170 supported_pwr_class = (supported_pwr_class >> 4U); 04171 } 04172 04173 if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU)) 04174 { 04175 /* Need to change current power class */ 04176 errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U))); 04177 04178 if (errorstate == HAL_MMC_ERROR_NONE) 04179 { 04180 /* While card is not ready for data and trial number for sending CMD13 is not exceeded */ 04181 count = SDMMC_MAX_TRIAL; 04182 do 04183 { 04184 errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U)); 04185 if (errorstate != HAL_MMC_ERROR_NONE) 04186 { 04187 break; 04188 } 04189 04190 /* Get command response */ 04191 response = SDMMC_GetResponse(hmmc->Instance, SDMMC_RESP1); 04192 count--; 04193 } while (((response & 0x100U) == 0U) && (count != 0U)); 04194 04195 /* Check the status after the switch command execution */ 04196 if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE)) 04197 { 04198 /* Check the bit SWITCH_ERROR of the device status */ 04199 if ((response & 0x80U) != 0U) 04200 { 04201 errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE; 04202 } 04203 } 04204 else if (count == 0U) 04205 { 04206 errorstate = SDMMC_ERROR_TIMEOUT; 04207 } 04208 else 04209 { 04210 /* Nothing to do */ 04211 } 04212 } 04213 } 04214 } 04215 } 04216 04217 return errorstate; 04218 } 04219 04220 /** 04221 * @brief Read DMA Buffer 0 Transfer completed callbacks 04222 * @param hmmc: MMC handle 04223 * @retval None 04224 */ 04225 __weak void HAL_MMCEx_Read_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc) 04226 { 04227 /* Prevent unused argument(s) compilation warning */ 04228 UNUSED(hmmc); 04229 04230 /* NOTE : This function should not be modified, when the callback is needed, 04231 the HAL_MMCEx_Read_DMADoubleBuf0CpltCallback can be implemented in the user file 04232 */ 04233 } 04234 04235 /** 04236 * @brief Read DMA Buffer 1 Transfer completed callbacks 04237 * @param hmmc: MMC handle 04238 * @retval None 04239 */ 04240 __weak void HAL_MMCEx_Read_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc) 04241 { 04242 /* Prevent unused argument(s) compilation warning */ 04243 UNUSED(hmmc); 04244 04245 /* NOTE : This function should not be modified, when the callback is needed, 04246 the HAL_MMCEx_Read_DMADoubleBuf1CpltCallback can be implemented in the user file 04247 */ 04248 } 04249 04250 /** 04251 * @brief Write DMA Buffer 0 Transfer completed callbacks 04252 * @param hmmc: MMC handle 04253 * @retval None 04254 */ 04255 __weak void HAL_MMCEx_Write_DMADoubleBuf0CpltCallback(MMC_HandleTypeDef *hmmc) 04256 { 04257 /* Prevent unused argument(s) compilation warning */ 04258 UNUSED(hmmc); 04259 04260 /* NOTE : This function should not be modified, when the callback is needed, 04261 the HAL_MMCEx_Write_DMADoubleBuf0CpltCallback can be implemented in the user file 04262 */ 04263 } 04264 04265 /** 04266 * @brief Write DMA Buffer 1 Transfer completed callbacks 04267 * @param hmmc: MMC handle 04268 * @retval None 04269 */ 04270 __weak void HAL_MMCEx_Write_DMADoubleBuf1CpltCallback(MMC_HandleTypeDef *hmmc) 04271 { 04272 /* Prevent unused argument(s) compilation warning */ 04273 UNUSED(hmmc); 04274 04275 /* NOTE : This function should not be modified, when the callback is needed, 04276 the HAL_MMCEx_Write_DMADoubleBuf1CpltCallback can be implemented in the user file 04277 */ 04278 } 04279 04280 /** 04281 * @} 04282 */ 04283 04284 #endif /* HAL_MMC_MODULE_ENABLED */ 04285 04286 /** 04287 * @} 04288 */ 04289 04290 /** 04291 * @} 04292 */