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