Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:08

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_hal_mmc_ex.c
0004   * @author  MCD Application Team
0005   * @brief   MMC card Extended HAL module driver.
0006   *          This file provides firmware functions to manage the following
0007   *          functionalities of the Secure Digital (MMC) peripheral:
0008   *           + Extended features functions
0009   *
0010   ******************************************************************************
0011   * @attention
0012   *
0013   * Copyright (c) 2017 STMicroelectronics.
0014   * All rights reserved.
0015   *
0016   * This software is licensed under terms that can be found in the LICENSE file
0017   * in the root directory of this software component.
0018   * If no LICENSE file comes with this software, it is provided AS-IS.
0019   *
0020   ******************************************************************************
0021   @verbatim
0022   ==============================================================================
0023                         ##### How to use this driver #####
0024   ==============================================================================
0025   [..]
0026    The MMC Extension HAL driver can be used as follows:
0027    (+) Configure Buffer0 and Buffer1 start address and Buffer size using HAL_MMCEx_ConfigDMAMultiBuffer() function.
0028 
0029    (+) Start Read and Write for multibuffer mode using HAL_MMCEx_ReadBlocksDMAMultiBuffer() and
0030        HAL_MMCEx_WriteBlocksDMAMultiBuffer() functions.
0031 
0032   @endverbatim
0033   ******************************************************************************
0034   */
0035 
0036 /* Includes ------------------------------------------------------------------*/
0037 #include "stm32h7xx_hal.h"
0038 
0039 /** @addtogroup STM32H7xx_HAL_Driver
0040   * @{
0041   */
0042 
0043 /** @defgroup MMCEx MMCEx
0044   * @ingroup RTEMSBSPsARMSTM32H7
0045   * @brief MMC Extended HAL module driver
0046   * @{
0047   */
0048 
0049 #ifdef HAL_MMC_MODULE_ENABLED
0050 
0051 /* Private typedef -----------------------------------------------------------*/
0052 /* Private define ------------------------------------------------------------*/
0053 /* Private macro -------------------------------------------------------------*/
0054 /* Private variables ---------------------------------------------------------*/
0055 /* Private function prototypes -----------------------------------------------*/
0056 /* Private functions ---------------------------------------------------------*/
0057 /* Exported functions --------------------------------------------------------*/
0058 /** @addtogroup MMCEx_Exported_Functions
0059   * @{
0060   */
0061 
0062 
0063 
0064 /** @addtogroup MMCEx_Exported_Functions_Group1
0065   *  @brief   Multibuffer functions
0066   *
0067 @verbatim
0068   ==============================================================================
0069           ##### Multibuffer functions #####
0070   ==============================================================================
0071   [..]
0072     This section provides functions allowing to configure the multibuffer mode and start read and write
0073     multibuffer mode for MMC HAL driver.
0074 
0075 @endverbatim
0076   * @{
0077   */
0078 
0079 /**
0080   * @brief  Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA.
0081   * @param  hmmc: MMC handle
0082   * @param  pDataBuffer0: Pointer to the buffer0 that will contain/receive the transferred data
0083   * @param  pDataBuffer1: Pointer to the buffer1 that will contain/receive the transferred data
0084   * @param  BufferSize: Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size.
0085   * @retval HAL status
0086   */
0087 HAL_StatusTypeDef HAL_MMCEx_ConfigDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t *pDataBuffer0,
0088                                                  uint32_t *pDataBuffer1, uint32_t BufferSize)
0089 {
0090   if (hmmc->State == HAL_MMC_STATE_READY)
0091   {
0092     hmmc->Instance->IDMABASE0 = (uint32_t) pDataBuffer0 ;
0093     hmmc->Instance->IDMABASE1 = (uint32_t) pDataBuffer1 ;
0094     hmmc->Instance->IDMABSIZE = (uint32_t)(MMC_BLOCKSIZE * BufferSize);
0095 
0096     return HAL_OK;
0097   }
0098   else
0099   {
0100     return HAL_BUSY;
0101   }
0102 }
0103 
0104 /**
0105   * @brief  Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1.
0106   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before
0107   *         call this function.
0108   * @param  hmmc: MMC handle
0109   * @param  BlockAdd: Block Address from where data is to be read
0110   * @param  NumberOfBlocks: Total number of blocks to read
0111   * @retval HAL status
0112   */
0113 HAL_StatusTypeDef HAL_MMCEx_ReadBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd,
0114                                                      uint32_t NumberOfBlocks)
0115 {
0116   SDMMC_DataInitTypeDef config;
0117   uint32_t DmaBase0_reg;
0118   uint32_t DmaBase1_reg;
0119   uint32_t errorstate;
0120   uint32_t add = BlockAdd;
0121 
0122   if (hmmc->State == HAL_MMC_STATE_READY)
0123   {
0124     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
0125     {
0126       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
0127       return HAL_ERROR;
0128     }
0129 
0130     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
0131     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
0132     {
0133       if ((NumberOfBlocks % 8U) != 0U)
0134       {
0135         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
0136         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
0137         return HAL_ERROR;
0138       }
0139 
0140       if ((BlockAdd % 8U) != 0U)
0141       {
0142         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
0143         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
0144         return HAL_ERROR;
0145       }
0146     }
0147 
0148     DmaBase0_reg = hmmc->Instance->IDMABASE0;
0149     DmaBase1_reg = hmmc->Instance->IDMABASE1;
0150 
0151     if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
0152     {
0153       hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
0154       return HAL_ERROR;
0155     }
0156 
0157     /* Initialize data control register */
0158     hmmc->Instance->DCTRL = 0;
0159 
0160     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
0161     hmmc->State = HAL_MMC_STATE_BUSY;
0162 
0163     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
0164     {
0165       add *= 512U;
0166     }
0167 
0168     /* Configure the MMC DPSM (Data Path State Machine) */
0169     config.DataTimeOut   = SDMMC_DATATIMEOUT;
0170     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
0171     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
0172     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
0173     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
0174     config.DPSM          = SDMMC_DPSM_DISABLE;
0175     (void)SDMMC_ConfigData(hmmc->Instance, &config);
0176 
0177     hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
0178 
0179     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
0180 
0181     hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
0182 
0183     /* Read Blocks in DMA mode */
0184     hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
0185 
0186     /* Read Multi Block command */
0187     errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
0188     if (errorstate != HAL_MMC_ERROR_NONE)
0189     {
0190       hmmc->State = HAL_MMC_STATE_READY;
0191       hmmc->ErrorCode |= errorstate;
0192       return HAL_ERROR;
0193     }
0194 
0195     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND |
0196                                SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC));
0197 
0198     return HAL_OK;
0199   }
0200   else
0201   {
0202     return HAL_BUSY;
0203   }
0204 
0205 }
0206 
0207 /**
0208   * @brief  Write block(s) to a specified address in a card. The transferred Data are stored in Buffer0 and Buffer1.
0209   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before
0210   *         call this function.
0211   * @param  hmmc: MMC handle
0212   * @param  BlockAdd: Block Address from where data is to be read
0213   * @param  NumberOfBlocks: Total number of blocks to read
0214   * @retval HAL status
0215   */
0216 HAL_StatusTypeDef HAL_MMCEx_WriteBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd,
0217                                                       uint32_t NumberOfBlocks)
0218 {
0219   SDMMC_DataInitTypeDef config;
0220   uint32_t errorstate;
0221   uint32_t DmaBase0_reg;
0222   uint32_t DmaBase1_reg;
0223   uint32_t add = BlockAdd;
0224 
0225   if (hmmc->State == HAL_MMC_STATE_READY)
0226   {
0227     if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
0228     {
0229       hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
0230       return HAL_ERROR;
0231     }
0232 
0233     /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */
0234     if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U)
0235     {
0236       if ((NumberOfBlocks % 8U) != 0U)
0237       {
0238         /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */
0239         hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR;
0240         return HAL_ERROR;
0241       }
0242 
0243       if ((BlockAdd % 8U) != 0U)
0244       {
0245         /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */
0246         hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED;
0247         return HAL_ERROR;
0248       }
0249     }
0250 
0251     DmaBase0_reg = hmmc->Instance->IDMABASE0;
0252     DmaBase1_reg = hmmc->Instance->IDMABASE1;
0253 
0254     if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
0255     {
0256       hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
0257       return HAL_ERROR;
0258     }
0259 
0260     /* Initialize data control register */
0261     hmmc->Instance->DCTRL = 0;
0262 
0263     hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
0264 
0265     hmmc->State = HAL_MMC_STATE_BUSY;
0266 
0267     if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
0268     {
0269       add *= 512U;
0270     }
0271 
0272     /* Configure the MMC DPSM (Data Path State Machine) */
0273     config.DataTimeOut   = SDMMC_DATATIMEOUT;
0274     config.DataLength    = MMC_BLOCKSIZE * NumberOfBlocks;
0275     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
0276     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
0277     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
0278     config.DPSM          = SDMMC_DPSM_DISABLE;
0279     (void)SDMMC_ConfigData(hmmc->Instance, &config);
0280 
0281     __SDMMC_CMDTRANS_ENABLE(hmmc->Instance);
0282 
0283     hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
0284 
0285     /* Write Blocks in DMA mode */
0286     hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
0287 
0288     /* Write Multi Block command */
0289     errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
0290     if (errorstate != HAL_MMC_ERROR_NONE)
0291     {
0292       hmmc->State = HAL_MMC_STATE_READY;
0293       hmmc->ErrorCode |= errorstate;
0294       return HAL_ERROR;
0295     }
0296 
0297     __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND |
0298                                SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC));
0299 
0300     return HAL_OK;
0301   }
0302   else
0303   {
0304     return HAL_BUSY;
0305   }
0306 }
0307 
0308 
0309 /**
0310   * @brief  Change the DMA Buffer0 or Buffer1 address on the fly.
0311   * @param  hmmc:           pointer to a MMC_HandleTypeDef structure.
0312   * @param  Buffer:        the buffer to be changed, This parameter can be one of
0313   *                        the following values: MMC_DMA_BUFFER0 or MMC_DMA_BUFFER1
0314   * @param  pDataBuffer:   The new address
0315   * @note   The BUFFER0 address can be changed only when the current transfer use
0316   *         BUFFER1 and the BUFFER1 address can be changed only when the current
0317   *         transfer use BUFFER0.
0318   * @retval HAL status
0319   */
0320 HAL_StatusTypeDef HAL_MMCEx_ChangeDMABuffer(MMC_HandleTypeDef *hmmc, HAL_MMCEx_DMABuffer_MemoryTypeDef Buffer,
0321                                             uint32_t *pDataBuffer)
0322 {
0323   if (Buffer == MMC_DMA_BUFFER0)
0324   {
0325     /* change the buffer0 address */
0326     hmmc->Instance->IDMABASE0 = (uint32_t)pDataBuffer;
0327   }
0328   else
0329   {
0330     /* change the memory1 address */
0331     hmmc->Instance->IDMABASE1 = (uint32_t)pDataBuffer;
0332   }
0333 
0334   return HAL_OK;
0335 }
0336 
0337 
0338 /**
0339   * @}
0340   */
0341 
0342 /**
0343   * @}
0344   */
0345 
0346 #endif /* HAL_MMC_MODULE_ENABLED */
0347 
0348 /**
0349   * @}
0350   */
0351 
0352 /**
0353   * @}
0354   */