Back to home page

LXR

 
 

    


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

0001 /**
0002   ******************************************************************************
0003   * @file    stm32h7xx_hal_sd_ex.c
0004   * @author  MCD Application Team
0005   * @brief   SD card Extended HAL module driver.
0006   *          This file provides firmware functions to manage the following
0007   *          functionalities of the Secure Digital (SD) 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 SD Extension HAL driver can be used as follows:
0027    (+) Configure Buffer0 and Buffer1 start address and Buffer size using HAL_SDEx_ConfigDMAMultiBuffer() function.
0028    (+) Start Read and Write for multibuffer mode using HAL_SDEx_ReadBlocksDMAMultiBuffer()
0029        and HAL_SDEx_WriteBlocksDMAMultiBuffer() functions.
0030 
0031   @endverbatim
0032   ******************************************************************************
0033   */
0034 
0035 /* Includes ------------------------------------------------------------------*/
0036 #include "stm32h7xx_hal.h"
0037 
0038 /** @addtogroup STM32H7xx_HAL_Driver
0039   * @{
0040   */
0041 
0042 /** @defgroup SDEx SDEx
0043   * @ingroup RTEMSBSPsARMSTM32H7
0044   * @brief SD Extended HAL module driver
0045   * @{
0046   */
0047 
0048 #ifdef HAL_SD_MODULE_ENABLED
0049 
0050 /* Private typedef -----------------------------------------------------------*/
0051 /* Private define ------------------------------------------------------------*/
0052 /* Private macro -------------------------------------------------------------*/
0053 /* Private variables ---------------------------------------------------------*/
0054 /* Private function prototypes -----------------------------------------------*/
0055 /* Private functions ---------------------------------------------------------*/
0056 /* Exported functions --------------------------------------------------------*/
0057 /** @addtogroup SDEx_Exported_Functions
0058   * @{
0059   */
0060 
0061 /** @addtogroup SDEx_Exported_Functions_Group1
0062   *  @brief   Multibuffer functions
0063   *
0064 @verbatim
0065   ==============================================================================
0066           ##### Multibuffer functions #####
0067   ==============================================================================
0068   [..]
0069     This section provides functions allowing to configure the multibuffer mode and start read and write
0070     multibuffer mode for SD HAL driver.
0071 
0072 @endverbatim
0073   * @{
0074   */
0075 
0076 /**
0077   * @brief  Configure DMA Dual Buffer mode. The Data transfer is managed by an Internal DMA.
0078   * @param  hsd: SD handle
0079   * @param  pDataBuffer0: Pointer to the buffer0 that will contain/receive the transferred data
0080   * @param  pDataBuffer1: Pointer to the buffer1 that will contain/receive the transferred data
0081   * @param  BufferSize: Size of Buffer0 in Blocks. Buffer0 and Buffer1 must have the same size.
0082   * @retval HAL status
0083   */
0084 HAL_StatusTypeDef HAL_SDEx_ConfigDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t *pDataBuffer0, uint32_t *pDataBuffer1,
0085                                                 uint32_t BufferSize)
0086 {
0087   if (hsd->State == HAL_SD_STATE_READY)
0088   {
0089     hsd->Instance->IDMABASE0 = (uint32_t) pDataBuffer0;
0090     hsd->Instance->IDMABASE1 = (uint32_t) pDataBuffer1;
0091     hsd->Instance->IDMABSIZE = (uint32_t)(BLOCKSIZE * BufferSize);
0092 
0093     return HAL_OK;
0094   }
0095   else
0096   {
0097     return HAL_BUSY;
0098   }
0099 }
0100 
0101 /**
0102   * @brief  Reads block(s) from a specified address in a card. The received Data will be stored in Buffer0 and Buffer1.
0103   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_SDEx_ConfigDMAMultiBuffer before
0104   *         call this function.
0105   * @param  hsd: SD handle
0106   * @param  BlockAdd: Block Address from where data is to be read
0107   * @param  NumberOfBlocks: Total number of blocks to read
0108   * @retval HAL status
0109   */
0110 HAL_StatusTypeDef HAL_SDEx_ReadBlocksDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks)
0111 {
0112   SDMMC_DataInitTypeDef config;
0113   uint32_t errorstate;
0114   uint32_t DmaBase0_reg;
0115   uint32_t DmaBase1_reg;
0116   uint32_t add = BlockAdd;
0117 
0118   if (hsd->State == HAL_SD_STATE_READY)
0119   {
0120     if ((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
0121     {
0122       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
0123       return HAL_ERROR;
0124     }
0125 
0126     DmaBase0_reg = hsd->Instance->IDMABASE0;
0127     DmaBase1_reg = hsd->Instance->IDMABASE1;
0128 
0129     if ((hsd->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
0130     {
0131       hsd->ErrorCode = HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
0132       return HAL_ERROR;
0133     }
0134 
0135     /* Initialize data control register */
0136     hsd->Instance->DCTRL = 0;
0137     /* Clear old Flags*/
0138     __HAL_SD_CLEAR_FLAG(hsd, SDMMC_STATIC_DATA_FLAGS);
0139 
0140     hsd->ErrorCode = HAL_SD_ERROR_NONE;
0141     hsd->State = HAL_SD_STATE_BUSY;
0142 
0143     if (hsd->SdCard.CardType != CARD_SDHC_SDXC)
0144     {
0145       add *= 512U;
0146     }
0147 
0148     /* Configure the SD DPSM (Data Path State Machine) */
0149     config.DataTimeOut   = SDMMC_DATATIMEOUT;
0150     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
0151     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
0152     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_SDMMC;
0153     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
0154     config.DPSM          = SDMMC_DPSM_DISABLE;
0155     (void)SDMMC_ConfigData(hsd->Instance, &config);
0156 
0157     hsd->Instance->DCTRL |= SDMMC_DCTRL_FIFORST;
0158 
0159     __SDMMC_CMDTRANS_ENABLE(hsd->Instance);
0160 
0161     hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
0162 
0163     /* Read Blocks in DMA mode */
0164     hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
0165 
0166     /* Read Multi Block command */
0167     errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
0168     if (errorstate != HAL_SD_ERROR_NONE)
0169     {
0170       hsd->State = HAL_SD_STATE_READY;
0171       hsd->ErrorCode |= errorstate;
0172       return HAL_ERROR;
0173     }
0174 
0175     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_RXOVERR | SDMMC_IT_DATAEND |
0176                              SDMMC_IT_IDMABTC));
0177 
0178     return HAL_OK;
0179   }
0180   else
0181   {
0182     return HAL_BUSY;
0183   }
0184 
0185 }
0186 
0187 /**
0188   * @brief  Write block(s) to a specified address in a card. The transferred Data are stored in Buffer0 and Buffer1.
0189   *         Buffer0, Buffer1 and BufferSize need to be configured by function HAL_SDEx_ConfigDMAMultiBuffer before
0190   *   call this function.
0191   * @param  hsd: SD handle
0192   * @param  BlockAdd: Block Address from where data is to be read
0193   * @param  NumberOfBlocks: Total number of blocks to read
0194   * @retval HAL status
0195   */
0196 HAL_StatusTypeDef HAL_SDEx_WriteBlocksDMAMultiBuffer(SD_HandleTypeDef *hsd, uint32_t BlockAdd, uint32_t NumberOfBlocks)
0197 {
0198   SDMMC_DataInitTypeDef config;
0199   uint32_t errorstate;
0200   uint32_t DmaBase0_reg;
0201   uint32_t DmaBase1_reg;
0202   uint32_t add = BlockAdd;
0203 
0204   if (hsd->State == HAL_SD_STATE_READY)
0205   {
0206     if ((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
0207     {
0208       hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
0209       return HAL_ERROR;
0210     }
0211 
0212     DmaBase0_reg = hsd->Instance->IDMABASE0;
0213     DmaBase1_reg = hsd->Instance->IDMABASE1;
0214     if ((hsd->Instance->IDMABSIZE == 0U) || (DmaBase0_reg == 0U) || (DmaBase1_reg == 0U))
0215     {
0216       hsd->ErrorCode = HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
0217       return HAL_ERROR;
0218     }
0219 
0220     /* Initialize data control register */
0221     hsd->Instance->DCTRL = 0;
0222 
0223     hsd->ErrorCode = HAL_SD_ERROR_NONE;
0224 
0225     hsd->State = HAL_SD_STATE_BUSY;
0226 
0227     if (hsd->SdCard.CardType != CARD_SDHC_SDXC)
0228     {
0229       add *= 512U;
0230     }
0231 
0232     /* Configure the SD DPSM (Data Path State Machine) */
0233     config.DataTimeOut   = SDMMC_DATATIMEOUT;
0234     config.DataLength    = BLOCKSIZE * NumberOfBlocks;
0235     config.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
0236     config.TransferDir   = SDMMC_TRANSFER_DIR_TO_CARD;
0237     config.TransferMode  = SDMMC_TRANSFER_MODE_BLOCK;
0238     config.DPSM          = SDMMC_DPSM_DISABLE;
0239     (void)SDMMC_ConfigData(hsd->Instance, &config);
0240 
0241     __SDMMC_CMDTRANS_ENABLE(hsd->Instance);
0242 
0243     hsd->Instance->IDMACTRL = SDMMC_ENABLE_IDMA_DOUBLE_BUFF0;
0244 
0245     /* Write Blocks in DMA mode */
0246     hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
0247 
0248     /* Write Multi Block command */
0249     errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
0250     if (errorstate != HAL_SD_ERROR_NONE)
0251     {
0252       hsd->State = HAL_SD_STATE_READY;
0253       hsd->ErrorCode |= errorstate;
0254       return HAL_ERROR;
0255     }
0256 
0257     __HAL_SD_ENABLE_IT(hsd, (SDMMC_IT_DCRCFAIL | SDMMC_IT_DTIMEOUT | SDMMC_IT_TXUNDERR | SDMMC_IT_DATAEND |
0258                              SDMMC_IT_IDMABTC));
0259 
0260     return HAL_OK;
0261   }
0262   else
0263   {
0264     return HAL_BUSY;
0265   }
0266 }
0267 
0268 
0269 /**
0270   * @brief  Change the DMA Buffer0 or Buffer1 address on the fly.
0271   * @param  hsd:           pointer to a SD_HandleTypeDef structure.
0272   * @param  Buffer:        the buffer to be changed, This parameter can be one of
0273   *                        the following values: SD_DMA_BUFFER0 or SD_DMA_BUFFER1
0274   * @param  pDataBuffer:   The new address
0275   * @note   The BUFFER0 address can be changed only when the current transfer use
0276   *         BUFFER1 and the BUFFER1 address can be changed only when the current
0277   *         transfer use BUFFER0.
0278   * @retval HAL status
0279   */
0280 HAL_StatusTypeDef HAL_SDEx_ChangeDMABuffer(SD_HandleTypeDef *hsd, HAL_SDEx_DMABuffer_MemoryTypeDef Buffer,
0281                                            uint32_t *pDataBuffer)
0282 {
0283   if (Buffer == SD_DMA_BUFFER0)
0284   {
0285     /* change the buffer0 address */
0286     hsd->Instance->IDMABASE0 = (uint32_t)pDataBuffer;
0287   }
0288   else
0289   {
0290     /* change the memory1 address */
0291     hsd->Instance->IDMABASE1 = (uint32_t)pDataBuffer;
0292   }
0293 
0294   return HAL_OK;
0295 }
0296 
0297 
0298 /**
0299   * @}
0300   */
0301 
0302 /**
0303   * @}
0304   */
0305 
0306 #endif /* HAL_SD_MODULE_ENABLED */
0307 
0308 /**
0309   * @}
0310   */
0311 
0312 /**
0313   * @}
0314   */