STM32H735xx HAL User Manual
|
00001 /** 00002 ****************************************************************************** 00003 * @file stm32h7xx_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 00030 HAL_MMCEx_WriteBlocksDMAMultiBuffer() functions. 00031 00032 @endverbatim 00033 ****************************************************************************** 00034 */ 00035 00036 /* Includes ------------------------------------------------------------------*/ 00037 #include "stm32h7xx_hal.h" 00038 00039 /** @addtogroup STM32H7xx_HAL_Driver 00040 * @{ 00041 */ 00042 00043 /** @defgroup MMCEx MMCEx 00044 * @brief MMC Extended HAL module driver 00045 * @{ 00046 */ 00047 00048 #ifdef HAL_MMC_MODULE_ENABLED 00049 00050 /* Private typedef -----------------------------------------------------------*/ 00051 /* Private define ------------------------------------------------------------*/ 00052 /* Private macro -------------------------------------------------------------*/ 00053 /* Private variables ---------------------------------------------------------*/ 00054 /* Private function prototypes -----------------------------------------------*/ 00055 /* Private functions ---------------------------------------------------------*/ 00056 /* Exported functions --------------------------------------------------------*/ 00057 /** @addtogroup MMCEx_Exported_Functions 00058 * @{ 00059 */ 00060 00061 00062 00063 /** @addtogroup MMCEx_Exported_Functions_Group1 00064 * @brief Multibuffer functions 00065 * 00066 @verbatim 00067 ============================================================================== 00068 ##### Multibuffer functions ##### 00069 ============================================================================== 00070 [..] 00071 This section provides functions allowing to configure the multibuffer mode and start read and write 00072 multibuffer mode for MMC HAL driver. 00073 00074 @endverbatim 00075 * @{ 00076 */ 00077 00078 /** 00079 * @brief Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA. 00080 * @param hmmc: MMC handle 00081 * @param pDataBuffer0: Pointer to the buffer0 that will contain/receive the transferred data 00082 * @param pDataBuffer1: Pointer to the buffer1 that will contain/receive the transferred data 00083 * @param BufferSize: Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size. 00084 * @retval HAL status 00085 */ 00086 HAL_StatusTypeDef HAL_MMCEx_ConfigDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t *pDataBuffer0, 00087 uint32_t *pDataBuffer1, uint32_t BufferSize) 00088 { 00089 if (hmmc->State == HAL_MMC_STATE_READY) 00090 { 00091 hmmc->Instance->IDMABASE0 = (uint32_t) pDataBuffer0 ; 00092 hmmc->Instance->IDMABASE1 = (uint32_t) pDataBuffer1 ; 00093 hmmc->Instance->IDMABSIZE = (uint32_t)(MMC_BLOCKSIZE * BufferSize); 00094 00095 return HAL_OK; 00096 } 00097 else 00098 { 00099 return HAL_BUSY; 00100 } 00101 } 00102 00103 /** 00104 * @brief Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1. 00105 * Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before 00106 * call this function. 00107 * @param hmmc: MMC handle 00108 * @param BlockAdd: Block Address from where data is to be read 00109 * @param NumberOfBlocks: Total number of blocks to read 00110 * @retval HAL status 00111 */ 00112 HAL_StatusTypeDef HAL_MMCEx_ReadBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd, 00113 uint32_t NumberOfBlocks) 00114 { 00115 SDMMC_DataInitTypeDef config; 00116 uint32_t DmaBase0_reg; 00117 uint32_t DmaBase1_reg; 00118 uint32_t errorstate; 00119 uint32_t add = BlockAdd; 00120 00121 if (hmmc->State == HAL_MMC_STATE_READY) 00122 { 00123 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 00124 { 00125 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 00126 return HAL_ERROR; 00127 } 00128 00129 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 00130 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 00131 { 00132 if ((NumberOfBlocks % 8U) != 0U) 00133 { 00134 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 00135 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 00136 return HAL_ERROR; 00137 } 00138 00139 if ((BlockAdd % 8U) != 0U) 00140 { 00141 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 00142 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 00143 return HAL_ERROR; 00144 } 00145 } 00146 00147 DmaBase0_reg = hmmc->Instance->IDMABASE0; 00148 DmaBase1_reg = hmmc->Instance->IDMABASE1; 00149 00150 if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U)) 00151 { 00152 hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 00153 return HAL_ERROR; 00154 } 00155 00156 /* Initialize data control register */ 00157 hmmc->Instance->DCTRL = 0; 00158 00159 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 00160 hmmc->State = HAL_MMC_STATE_BUSY; 00161 00162 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 00163 { 00164 add *= 512U; 00165 } 00166 00167 /* Configure the MMC DPSM (Data Path State Machine) */ 00168 config.DataTimeOut = SDMMC_DATATIMEOUT; 00169 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; 00170 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 00171 config.TransferDir = SDMMC_TRANSFER_DIR_TO_SDMMC; 00172 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 00173 config.DPSM = SDMMC_DPSM_DISABLE; 00174 (void)SDMMC_ConfigData(hmmc->Instance, &config); 00175 00176 hmmc->Instance->DCTRL |= SDMMC_DCTRL_FIFORST; 00177 00178 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 00179 00180 hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0; 00181 00182 /* Read Blocks in DMA mode */ 00183 hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA); 00184 00185 /* Read Multi Block command */ 00186 errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add); 00187 if (errorstate != HAL_MMC_ERROR_NONE) 00188 { 00189 hmmc->State = HAL_MMC_STATE_READY; 00190 hmmc->ErrorCode |= errorstate; 00191 return HAL_ERROR; 00192 } 00193 00194 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND | 00195 SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC)); 00196 00197 return HAL_OK; 00198 } 00199 else 00200 { 00201 return HAL_BUSY; 00202 } 00203 00204 } 00205 00206 /** 00207 * @brief Write block(s) to a specified address in a card. The transferred Data are stored in Buffer0 and Buffer1. 00208 * Buffer0, Buffer1 and BufferSize need to be configured by function HAL_MMCEx_ConfigDMAMultiBuffer before 00209 * call this function. 00210 * @param hmmc: MMC handle 00211 * @param BlockAdd: Block Address from where data is to be read 00212 * @param NumberOfBlocks: Total number of blocks to read 00213 * @retval HAL status 00214 */ 00215 HAL_StatusTypeDef HAL_MMCEx_WriteBlocksDMAMultiBuffer(MMC_HandleTypeDef *hmmc, uint32_t BlockAdd, 00216 uint32_t NumberOfBlocks) 00217 { 00218 SDMMC_DataInitTypeDef config; 00219 uint32_t errorstate; 00220 uint32_t DmaBase0_reg; 00221 uint32_t DmaBase1_reg; 00222 uint32_t add = BlockAdd; 00223 00224 if (hmmc->State == HAL_MMC_STATE_READY) 00225 { 00226 if ((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr)) 00227 { 00228 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 00229 return HAL_ERROR; 00230 } 00231 00232 /* Check the case of 4kB blocks (field DATA SECTOR SIZE of extended CSD register) */ 00233 if (((hmmc->Ext_CSD[(MMC_EXT_CSD_DATA_SEC_SIZE_INDEX / 4)] >> MMC_EXT_CSD_DATA_SEC_SIZE_POS) & 0x000000FFU) != 0x0U) 00234 { 00235 if ((NumberOfBlocks % 8U) != 0U) 00236 { 00237 /* The number of blocks should be a multiple of 8 sectors of 512 bytes = 4 KBytes */ 00238 hmmc->ErrorCode |= HAL_MMC_ERROR_BLOCK_LEN_ERR; 00239 return HAL_ERROR; 00240 } 00241 00242 if ((BlockAdd % 8U) != 0U) 00243 { 00244 /* The address should be aligned to 8 (corresponding to 4 KBytes blocks) */ 00245 hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_MISALIGNED; 00246 return HAL_ERROR; 00247 } 00248 } 00249 00250 DmaBase0_reg = hmmc->Instance->IDMABASE0; 00251 DmaBase1_reg = hmmc->Instance->IDMABASE1; 00252 00253 if ((hmmc->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U)) 00254 { 00255 hmmc->ErrorCode = HAL_MMC_ERROR_ADDR_OUT_OF_RANGE; 00256 return HAL_ERROR; 00257 } 00258 00259 /* Initialize data control register */ 00260 hmmc->Instance->DCTRL = 0; 00261 00262 hmmc->ErrorCode = HAL_MMC_ERROR_NONE; 00263 00264 hmmc->State = HAL_MMC_STATE_BUSY; 00265 00266 if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD) 00267 { 00268 add *= 512U; 00269 } 00270 00271 /* Configure the MMC DPSM (Data Path State Machine) */ 00272 config.DataTimeOut = SDMMC_DATATIMEOUT; 00273 config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks; 00274 config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B; 00275 config.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD; 00276 config.TransferMode = SDMMC_TRANSFER_MODE_BLOCK; 00277 config.DPSM = SDMMC_DPSM_DISABLE; 00278 (void)SDMMC_ConfigData(hmmc->Instance, &config); 00279 00280 __SDMMC_CMDTRANS_ENABLE(hmmc->Instance); 00281 00282 hmmc->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0; 00283 00284 /* Write Blocks in DMA mode */ 00285 hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA); 00286 00287 /* Write Multi Block command */ 00288 errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add); 00289 if (errorstate != HAL_MMC_ERROR_NONE) 00290 { 00291 hmmc->State = HAL_MMC_STATE_READY; 00292 hmmc->ErrorCode |= errorstate; 00293 return HAL_ERROR; 00294 } 00295 00296 __HAL_MMC_ENABLE_IT(hmmc, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND | 00297 SDMMC_FLAG_IDMATE | SDMMC_FLAG_IDMABTC)); 00298 00299 return HAL_OK; 00300 } 00301 else 00302 { 00303 return HAL_BUSY; 00304 } 00305 } 00306 00307 00308 /** 00309 * @brief Change the DMA Buffer0 or Buffer1 address on the fly. 00310 * @param hmmc: pointer to a MMC_HandleTypeDef structure. 00311 * @param Buffer: the buffer to be changed, This parameter can be one of 00312 * the following values: MMC_DMA_BUFFER0 or MMC_DMA_BUFFER1 00313 * @param pDataBuffer: The new address 00314 * @note The BUFFER0 address can be changed only when the current transfer use 00315 * BUFFER1 and the BUFFER1 address can be changed only when the current 00316 * transfer use BUFFER0. 00317 * @retval HAL status 00318 */ 00319 HAL_StatusTypeDef HAL_MMCEx_ChangeDMABuffer(MMC_HandleTypeDef *hmmc, HAL_MMCEx_DMABuffer_MemoryTypeDef Buffer, 00320 uint32_t *pDataBuffer) 00321 { 00322 if (Buffer == MMC_DMA_BUFFER0) 00323 { 00324 /* change the buffer0 address */ 00325 hmmc->Instance->IDMABASE0 = (uint32_t)pDataBuffer; 00326 } 00327 else 00328 { 00329 /* change the memory1 address */ 00330 hmmc->Instance->IDMABASE1 = (uint32_t)pDataBuffer; 00331 } 00332 00333 return HAL_OK; 00334 } 00335 00336 00337 /** 00338 * @} 00339 */ 00340 00341 /** 00342 * @} 00343 */ 00344 00345 #endif /* HAL_MMC_MODULE_ENABLED */ 00346 00347 /** 00348 * @} 00349 */ 00350 00351 /** 00352 * @} 00353 */