STM32L443xx HAL User Manual
stm32l4xx_hal_mmc_ex.c
Go to the documentation of this file.
00001 /**
00002   ******************************************************************************
00003   * @file    stm32l4xx_hal_mmc_ex.c
00004   * @author  MCD Application Team
00005   * @brief   MMC card Extended HAL module driver.
00006   *          This file provides firmware functions to manage the following
00007   *          functionalities of the Secure Digital (MMC) peripheral:
00008   *           + Extended features functions
00009   *
00010   ******************************************************************************
00011   * @attention
00012   *
00013   * Copyright (c) 2017 STMicroelectronics.
00014   * All rights reserved.
00015   *
00016   * This software is licensed under terms that can be found in the LICENSE file
00017   * in the root directory of this software component.
00018   * If no LICENSE file comes with this software, it is provided AS-IS.
00019   *
00020   ******************************************************************************
00021   @verbatim
00022   ==============================================================================
00023                         ##### How to use this driver #####
00024   ==============================================================================
00025   [..]
00026    The MMC Extension HAL driver can be used as follows:
00027    (+) Configure Buffer0 and Buffer1 start address and Buffer size using HAL_MMCEx_ConfigDMAMultiBuffer() function.
00028 
00029    (+) Start Read and Write for multibuffer mode using HAL_MMCEx_ReadBlocksDMAMultiBuffer() and HAL_MMCEx_WriteBlocksDMAMultiBuffer() functions.
00030 
00031   @endverbatim
00032   ******************************************************************************
00033   */
00034 
00035 /* Includes ------------------------------------------------------------------*/
00036 #include "stm32l4xx_hal.h"
00037 
00038 #if defined(STM32L4P5xx) || defined(STM32L4Q5xx) || defined(STM32L4R5xx) || defined(STM32L4R7xx) || defined(STM32L4R9xx) || defined(STM32L4S5xx) || defined(STM32L4S7xx) || defined(STM32L4S9xx)
00039 
00040 /** @addtogroup STM32L4xx_HAL_Driver
00041   * @{
00042   */
00043 
00044 /** @defgroup MMCEx MMCEx
00045   * @brief MMC Extended HAL module driver
00046   * @{
00047   */
00048 
00049 #ifdef HAL_MMC_MODULE_ENABLED
00050 
00051 /* Private typedef -----------------------------------------------------------*/
00052 /* Private define ------------------------------------------------------------*/
00053 /* Private macro -------------------------------------------------------------*/
00054 /* Private variables ---------------------------------------------------------*/
00055 /* Private function prototypes -----------------------------------------------*/
00056 /* Private functions ---------------------------------------------------------*/
00057 /* Exported functions --------------------------------------------------------*/
00058 /** @defgroup MMCEx_Exported_Types MMCEx Exported Types
00059   * @{
00060   */
00061 
00062 /** @defgroup MMCEx_Exported_Types_Group1 MMC Internal DMA Buffer structure
00063  *  @brief   Multibuffer functions
00064  *
00065 @verbatim
00066   ==============================================================================
00067           ##### Multibuffer functions #####
00068   ==============================================================================
00069   [..]
00070     This section provides functions allowing to configure the multibuffer mode and start read and write
00071     multibuffer mode for MMC HAL driver.
00072 
00073 @endverbatim
00074   * @{
00075   */
00076 
00077 /**
00078   * @brief  Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA.
00079   * @param  hmmc MMC handle
00080   * @param  pDataBuffer0 Pointer to the buffer0 that will contain/receive the transfered data
00081   * @param  pDataBuffer1 Pointer to the buffer1 that will contain/receive the transfered data
00082   * @param  BufferSize Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size.
00083   * @retval HAL status
00084   */
00085 HAL_StatusTypeDef HAL_MMCEx_ConfigDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t * pDataBuffer0, uint32_t * pDataBuffer1, uint32_t BufferSize)
00086 {
00087   if(hmmc->State == HAL_MMC_STATE_READY)
00088   {
00089     hmmc->Instance->IDMABASE0= (uint32_t) pDataBuffer0 ;
00090     hmmc->Instance->IDMABASE1= (uint32_t) pDataBuffer1 ;
00091     hmmc->Instance->IDMABSIZE= (uint32_t) (MMC_BLOCKSIZE * BufferSize);
00092 
00093     return HAL_OK;
00094   }
00095   else
00096   {
00097     return HAL_BUSY;
00098   }
00099 }
00100 
00101 /**
00102   * @brief  Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1.
00103   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before call this function.
00104   * @param  hmmc MMC handle
00105   * @param  BlockAdd Block Address from where data is to be read
00106   * @param  NumberOfBlocks Total number of blocks to read
00107   * @retval HAL status
00108   */
00109 HAL_StatusTypeDef HAL_MMCEx_ReadBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd, uint32_t NumberOfBlocks)
00110 {
00111   SDMMC_DataInitTypeDef config;
00112   uint32_t DmaBase0_reg, DmaBase1_reg;
00113   uint32_t errorstate;
00114   uint32_t add = BlockAdd;
00115 
00116   if(hmmc->State == HAL_MMC_STATE_READY)
00117   {
00118     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00119     {
00120       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00121       return HAL_ERROR;
00122     }
00123 
00124     DmaBase0_reg = hmmc->Instance->IDMABASE0;
00125     DmaBase1_reg = hmmc->Instance->IDMABASE1;
00126     if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
00127     {
00128       hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00129       return HAL_ERROR;
00130     }
00131 
00132     /* Initialize data control register */
00133     hmmc->Instance->DCTRL = 0;
00134 
00135     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
00136     hmmc->State = HAL_MMC_STATE_BUSY;
00137 
00138     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
00139     {
00140       add *= 512U;
00141     }
00142 
00143     /* Configure the MMC DPSM (Data Path State Machine) */
00144     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00145     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
00146     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
00147     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
00148     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
00149     config.DPSM          = SDMMC_DPSM_DISABLE;
00150     (void)SDMMC_ConfigData(hmmc->Instance, &config);
00151 
00152     hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
00153 
00154     __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
00155 
00156     hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
00157 
00158     /* Read Blocks in DMA mode */
00159     hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
00160 
00161     /* Read Multi Block command */
00162     errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
00163     if(errorstate != HAL_MMC_ERROR_NONE)
00164     {
00165       hmmc->State = HAL_MMC_STATE_READY;
00166       hmmc->ErrorCode |= errorstate;
00167       return HAL_ERROR;
00168     }
00169 
00170      __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC));
00171 
00172     return HAL_OK;
00173   }
00174   else
00175   {
00176     return HAL_BUSY;
00177   }
00178 
00179 }
00180 
00181 /**
00182   * @brief  Write block(s) to a specified address in a card. The transfered Data are stored in Buffer0 and Buffer1.
00183   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before call this function.
00184   * @param  hmmc MMC handle
00185   * @param  BlockAdd Block Address from where data is to be read
00186   * @param  NumberOfBlocks Total number of blocks to read
00187   * @retval HAL status
00188 */
00189 HAL_StatusTypeDef HAL_MMCEx_WriteBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd, uint32_t NumberOfBlocks)
00190 {
00191   SDMMC_DataInitTypeDef config;
00192   uint32_t errorstate;
00193   uint32_t DmaBase0_reg, DmaBase1_reg;
00194   uint32_t add = BlockAdd;
00195 
00196   if(hmmc->State == HAL_MMC_STATE_READY)
00197   {
00198     if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
00199     {
00200       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00201       return HAL_ERROR;
00202     }
00203 
00204     DmaBase0_reg = hmmc->Instance->IDMABASE0;
00205     DmaBase1_reg = hmmc->Instance->IDMABASE1;
00206     if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
00207     {
00208       hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
00209       return HAL_ERROR;
00210     }
00211 
00212     /* Initialize data control register */
00213     hmmc->Instance->DCTRL = 0;
00214 
00215     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
00216 
00217     hmmc->State = HAL_MMC_STATE_BUSY;
00218 
00219     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
00220     {
00221       add *= 512U;
00222     }
00223 
00224     /* Configure the MMC DPSM (Data Path State Machine) */
00225     config.DataTimeOut   = SDMMC_DATATIMEOUT;
00226     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
00227     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
00228     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
00229     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
00230     config.DPSM          = SDMMC_DPSM_DISABLE;
00231     (void)SDMMC_ConfigData(hmmc->Instance, &config);
00232 
00233     __SDMMC_CMDTRANS_ENABLE( hmmc->Instance);
00234 
00235     hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
00236 
00237     /* Write Blocks in DMA mode */
00238     hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
00239 
00240     /* Write Multi Block command */
00241     errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
00242     if(errorstate != HAL_MMC_ERROR_NONE)
00243     {
00244       hmmc->State = HAL_MMC_STATE_READY;
00245       hmmc->ErrorCode |= errorstate;
00246       return HAL_ERROR;
00247     }
00248 
00249     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC));
00250 
00251     return HAL_OK;
00252   }
00253   else
00254   {
00255     return HAL_BUSY;
00256   }
00257 }
00258 
00259 
00260 /**
00261   * @brief  Change the DMA Buffer0 or Buffer1 address on the fly.
00262   * @param  hmmc           pointer to a MMC_HandleTypeDef structure.
00263   * @param  Buffer         the buffer to be changed, This parameter can be one of
00264   *                        the following values: MMC_DMA_BUFFER0 or MMC_DMA_BUFFER1
00265   * @param  pDataBuffer    The new address
00266   * @note   The BUFFER0 address can be changed only when the current transfer use
00267   *         BUFFER1 and the BUFFER1 address can be changed only when the current
00268   *         transfer use BUFFER0.
00269   * @retval HAL status
00270   */
00271 HAL_StatusTypeDef HAL_MMCEx_ChangeDMABuffer(MMC_HandleTypeDef *hmmc, HAL_MMCEx_DMABuffer_MemoryTypeDef Buffer, uint32_t *pDataBuffer)
00272 {
00273   if(Buffer == MMC_DMA_BUFFER0)
00274   {
00275     /* change the buffer0 address */
00276     hmmc->Instance->IDMABASE0 = (uint32_t)pDataBuffer;
00277   }
00278   else
00279   {
00280     /* change the memory1 address */
00281     hmmc->Instance->IDMABASE1 = (uint32_t)pDataBuffer;
00282   }
00283 
00284   return HAL_OK;
00285 }
00286 
00287 /**
00288   * @brief Read DMA Buffer 0 Transfer completed callbacks
00289   * @param hmmc MMC handle
00290   * @retval None
00291   */
00292 __weak void HAL_MMCEx_Read_DMADoubleBuffer0CpltCallback(MMC_HandleTypeDef *hmmc)
00293 {
00294   /* Prevent unused argument(s) compilation warning */
00295   UNUSED(hmmc);
00296 
00297   /* NOTE : This function should not be modified, when the callback is needed,
00298             the HAL_MMCEx_Read_DMADoubleBuffer0CpltCallback can be implemented in the user file
00299    */
00300 }
00301 
00302 /**
00303   * @brief Read DMA Buffer 1 Transfer completed callbacks
00304   * @param hmmc MMC handle
00305   * @retval None
00306   */
00307 __weak void HAL_MMCEx_Read_DMADoubleBuffer1CpltCallback(MMC_HandleTypeDef *hmmc)
00308 {
00309   /* Prevent unused argument(s) compilation warning */
00310   UNUSED(hmmc);
00311 
00312   /* NOTE : This function should not be modified, when the callback is needed,
00313             the HAL_MMCEx_Read_DMADoubleBuffer1CpltCallback can be implemented in the user file
00314    */
00315 }
00316 
00317 /**
00318   * @brief Write DMA Buffer 0 Transfer completed callbacks
00319   * @param hmmc MMC handle
00320   * @retval None
00321   */
00322 __weak void HAL_MMCEx_Write_DMADoubleBuffer0CpltCallback(MMC_HandleTypeDef *hmmc)
00323 {
00324   /* Prevent unused argument(s) compilation warning */
00325   UNUSED(hmmc);
00326 
00327   /* NOTE : This function should not be modified, when the callback is needed,
00328             the HAL_MMCEx_Write_DMADoubleBuffer0CpltCallback can be implemented in the user file
00329    */
00330 }
00331 
00332 /**
00333   * @brief Write DMA Buffer 1 Transfer completed callbacks
00334   * @param hmmc MMC handle
00335   * @retval None
00336   */
00337 __weak void HAL_MMCEx_Write_DMADoubleBuffer1CpltCallback(MMC_HandleTypeDef *hmmc)
00338 {
00339   /* Prevent unused argument(s) compilation warning */
00340   UNUSED(hmmc);
00341 
00342   /* NOTE : This function should not be modified, when the callback is needed,
00343             the HAL_MMCEx_Write_DMADoubleBuffer0CpltCallback can be implemented in the user file
00344    */
00345 }
00346 
00347 /**
00348   * @}
00349   */
00350 
00351 /**
00352   * @}
00353   */
00354 
00355 #endif /* HAL_MMC_MODULE_ENABLED */
00356 
00357 /**
00358   * @}
00359   */
00360 
00361 /**
00362   * @}
00363   */
00364 
00365 #endif /* STM32L4P5xx || STM32L4Q5xx || STM32L4R5xx || STM32L4R7xx || STM32L4R9xx || STM32L4S5xx || STM32L4S7xx || STM32L4S9xx */