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