1 /**
2   ******************************************************************************
3   * @file    stm32f7xx_hal_dma_ex.c
4   * @author  MCD Application Team
5   * @brief   DMA Extension HAL module driver
6   *         This file provides firmware functions to manage the following
7   *         functionalities of the DMA Extension peripheral:
8   *           + Extended features functions
9   *
10   @verbatim
11   ==============================================================================
12                         ##### How to use this driver #####
13   ==============================================================================
14   [..]
15   The DMA Extension HAL driver can be used as follows:
16    (+) Start a multi buffer transfer using the HAL_DMA_MultiBufferStart() function
17        for polling mode or HAL_DMA_MultiBufferStart_IT() for interrupt mode.
18 
19      -@-  In Memory-to-Memory transfer mode, Multi (Double) Buffer mode is not allowed.
20      -@-  When Multi (Double) Buffer mode is enabled, the transfer is circular by default.
21      -@-  In Multi (Double) buffer mode, it is possible to update the base address for
22           the AHB memory port on the fly (DMA_SxM0AR or DMA_SxM1AR) when the stream is enabled.
23 
24   @endverbatim
25   ******************************************************************************
26   * @attention
27   *
28   * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
29   * All rights reserved.</center></h2>
30   *
31   * This software component is licensed by ST under BSD 3-Clause license,
32   * the "License"; You may not use this file except in compliance with the
33   * License. You may obtain a copy of the License at:
34   *                        opensource.org/licenses/BSD-3-Clause
35   *
36   ******************************************************************************
37   */
38 
39 /* Includes ------------------------------------------------------------------*/
40 #include "stm32f7xx_hal.h"
41 
42 /** @addtogroup STM32F7xx_HAL_Driver
43   * @{
44   */
45 
46 /** @defgroup DMAEx DMAEx
47   * @brief DMA Extended HAL module driver
48   * @{
49   */
50 
51 #ifdef HAL_DMA_MODULE_ENABLED
52 
53 /* Private types -------------------------------------------------------------*/
54 /* Private variables ---------------------------------------------------------*/
55 /* Private Constants ---------------------------------------------------------*/
56 /* Private macros ------------------------------------------------------------*/
57 /* Private functions ---------------------------------------------------------*/
58 /** @addtogroup DMAEx_Private_Functions
59   * @{
60   */
61 
62 static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
63 
64 /**
65   * @}
66   */
67 
68 /* Exported functions ---------------------------------------------------------*/
69 
70 /** @addtogroup DMAEx_Exported_Functions
71   * @{
72   */
73 
74 
75 /** @addtogroup DMAEx_Exported_Functions_Group1
76   *
77 @verbatim
78  ===============================================================================
79                 #####  Extended features functions  #####
80  ===============================================================================
81     [..]  This section provides functions allowing to:
82       (+) Configure the source, destination address and data length and
83           Start MultiBuffer DMA transfer
84       (+) Configure the source, destination address and data length and
85           Start MultiBuffer DMA transfer with interrupt
86       (+) Change on the fly the memory0 or memory1 address.
87 
88 @endverbatim
89   * @{
90   */
91 
92 
93 /**
94   * @brief  Starts the multi_buffer DMA Transfer.
95   * @param  hdma       pointer to a DMA_HandleTypeDef structure that contains
96   *                     the configuration information for the specified DMA Stream.
97   * @param  SrcAddress The source memory Buffer address
98   * @param  DstAddress The destination memory Buffer address
99   * @param  SecondMemAddress The second memory Buffer address in case of multi buffer Transfer
100   * @param  DataLength The length of data to be transferred from source to destination
101   * @retval HAL status
102   */
HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SecondMemAddress,uint32_t DataLength)103 HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength)
104 {
105   HAL_StatusTypeDef status = HAL_OK;
106 
107   /* Check the parameters */
108   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
109 
110   /* Memory-to-memory transfer not supported in double buffering mode */
111   if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
112   {
113     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
114     status = HAL_ERROR;
115   }
116   else
117   {
118     /* Process Locked */
119     __HAL_LOCK(hdma);
120 
121     if(HAL_DMA_STATE_READY == hdma->State)
122     {
123       /* Change DMA peripheral state */
124       hdma->State = HAL_DMA_STATE_BUSY;
125 
126       /* Enable the double buffer mode */
127       hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM;
128 
129       /* Configure DMA Stream destination address */
130       hdma->Instance->M1AR = SecondMemAddress;
131 
132       /* Configure the source, destination address and the data length */
133       DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength);
134 
135       /* Enable the peripheral */
136       __HAL_DMA_ENABLE(hdma);
137     }
138     else
139     {
140       /* Return error status */
141       status = HAL_BUSY;
142     }
143   }
144   return status;
145 }
146 
147 /**
148   * @brief  Starts the multi_buffer DMA Transfer with interrupt enabled.
149   * @param  hdma       pointer to a DMA_HandleTypeDef structure that contains
150   *                     the configuration information for the specified DMA Stream.
151   * @param  SrcAddress The source memory Buffer address
152   * @param  DstAddress The destination memory Buffer address
153   * @param  SecondMemAddress The second memory Buffer address in case of multi buffer Transfer
154   * @param  DataLength The length of data to be transferred from source to destination
155   * @retval HAL status
156   */
HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SecondMemAddress,uint32_t DataLength)157 HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength)
158 {
159   HAL_StatusTypeDef status = HAL_OK;
160 
161   /* Check the parameters */
162   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
163 
164   /* Memory-to-memory transfer not supported in double buffering mode */
165   if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
166   {
167     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
168     return HAL_ERROR;
169   }
170 
171   /* Process locked */
172   __HAL_LOCK(hdma);
173 
174   if(HAL_DMA_STATE_READY == hdma->State)
175   {
176     /* Change DMA peripheral state */
177     hdma->State = HAL_DMA_STATE_BUSY;
178 
179     /* Initialize the error code */
180     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
181 
182     /* Enable the Double buffer mode */
183     hdma->Instance->CR |= (uint32_t)DMA_SxCR_DBM;
184 
185     /* Configure DMA Stream destination address */
186     hdma->Instance->M1AR = SecondMemAddress;
187 
188     /* Configure the source, destination address and the data length */
189     DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength);
190 
191     /* Clear all flags */
192     __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
193     __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
194     __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
195     __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
196     __HAL_DMA_CLEAR_FLAG (hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
197 
198     /* Enable Common interrupts*/
199     hdma->Instance->CR  |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME;
200     hdma->Instance->FCR |= DMA_IT_FE;
201 
202     if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
203     {
204       hdma->Instance->CR  |= DMA_IT_HT;
205     }
206 
207     /* Enable the peripheral */
208     __HAL_DMA_ENABLE(hdma);
209   }
210   else
211   {
212     /* Process unlocked */
213     __HAL_UNLOCK(hdma);
214 
215     /* Return error status */
216     status = HAL_BUSY;
217   }
218   return status;
219 }
220 
221 /**
222   * @brief  Change the memory0 or memory1 address on the fly.
223   * @param  hdma       pointer to a DMA_HandleTypeDef structure that contains
224   *                     the configuration information for the specified DMA Stream.
225   * @param  Address    The new address
226   * @param  memory     the memory to be changed, This parameter can be one of
227   *                     the following values:
228   *                      MEMORY0 /
229   *                      MEMORY1
230   * @note   The MEMORY0 address can be changed only when the current transfer use
231   *         MEMORY1 and the MEMORY1 address can be changed only when the current
232   *         transfer use MEMORY0.
233   * @retval HAL status
234   */
HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef * hdma,uint32_t Address,HAL_DMA_MemoryTypeDef memory)235 HAL_StatusTypeDef HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef *hdma, uint32_t Address, HAL_DMA_MemoryTypeDef memory)
236 {
237   if(memory == MEMORY0)
238   {
239     /* change the memory0 address */
240     hdma->Instance->M0AR = Address;
241   }
242   else
243   {
244     /* change the memory1 address */
245     hdma->Instance->M1AR = Address;
246   }
247 
248   return HAL_OK;
249 }
250 
251 /**
252   * @}
253   */
254 
255 /**
256   * @}
257   */
258 
259 /** @addtogroup DMAEx_Private_Functions
260   * @{
261   */
262 
263 /**
264   * @brief  Set the DMA Transfer parameter.
265   * @param  hdma       pointer to a DMA_HandleTypeDef structure that contains
266   *                     the configuration information for the specified DMA Stream.
267   * @param  SrcAddress The source memory Buffer address
268   * @param  DstAddress The destination memory Buffer address
269   * @param  DataLength The length of data to be transferred from source to destination
270   * @retval HAL status
271   */
DMA_MultiBufferSetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)272 static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
273 {
274   /* Configure DMA Stream data length */
275   hdma->Instance->NDTR = DataLength;
276 
277   /* Peripheral to Memory */
278   if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
279   {
280     /* Configure DMA Stream destination address */
281     hdma->Instance->PAR = DstAddress;
282 
283     /* Configure DMA Stream source address */
284     hdma->Instance->M0AR = SrcAddress;
285   }
286   /* Memory to Peripheral */
287   else
288   {
289     /* Configure DMA Stream source address */
290     hdma->Instance->PAR = SrcAddress;
291 
292     /* Configure DMA Stream destination address */
293     hdma->Instance->M0AR = DstAddress;
294   }
295 }
296 
297 /**
298   * @}
299   */
300 
301 #endif /* HAL_DMA_MODULE_ENABLED */
302 /**
303   * @}
304   */
305 
306 /**
307   * @}
308   */
309 
310 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
311