38
|
1 /**
|
|
2 ******************************************************************************
|
|
3 * @file stm32f4xx_hal_dma.c
|
|
4 * @author MCD Application Team
|
|
5 * @version V1.2.0
|
|
6 * @date 26-December-2014
|
|
7 * @brief DMA HAL module driver.
|
|
8 *
|
|
9 * This file provides firmware functions to manage the following
|
|
10 * functionalities of the Direct Memory Access (DMA) peripheral:
|
|
11 * + Initialization and de-initialization functions
|
|
12 * + IO operation functions
|
|
13 * + Peripheral State and errors functions
|
|
14 @verbatim
|
|
15 ==============================================================================
|
|
16 ##### How to use this driver #####
|
|
17 ==============================================================================
|
|
18 [..]
|
|
19 (#) Enable and configure the peripheral to be connected to the DMA Stream
|
|
20 (except for internal SRAM/FLASH memories: no initialization is
|
|
21 necessary) please refer to Reference manual for connection between peripherals
|
|
22 and DMA requests .
|
|
23
|
|
24 (#) For a given Stream, program the required configuration through the following parameters:
|
|
25 Transfer Direction, Source and Destination data formats,
|
|
26 Circular, Normal or peripheral flow control mode, Stream Priority level,
|
|
27 Source and Destination Increment mode, FIFO mode and its Threshold (if needed),
|
|
28 Burst mode for Source and/or Destination (if needed) using HAL_DMA_Init() function.
|
|
29
|
|
30 *** Polling mode IO operation ***
|
|
31 =================================
|
|
32 [..]
|
|
33 (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
|
|
34 address and destination address and the Length of data to be transferred
|
|
35 (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
|
|
36 case a fixed Timeout can be configured by User depending from his application.
|
|
37
|
|
38 *** Interrupt mode IO operation ***
|
|
39 ===================================
|
|
40 [..]
|
|
41 (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
|
|
42 (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
|
|
43 (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
|
|
44 Source address and destination address and the Length of data to be transferred. In this
|
|
45 case the DMA interrupt is configured
|
|
46 (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
|
|
47 (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
|
|
48 add his own function by customization of function pointer XferCpltCallback and
|
|
49 XferErrorCallback (i.e a member of DMA handle structure).
|
|
50 [..]
|
|
51 (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
|
|
52 detection.
|
|
53
|
|
54 (#) Use HAL_DMA_Abort() function to abort the current transfer
|
|
55
|
|
56 -@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
|
|
57
|
|
58 -@- The FIFO is used mainly to reduce bus usage and to allow data packing/unpacking: it is
|
|
59 possible to set different Data Sizes for the Peripheral and the Memory (ie. you can set
|
|
60 Half-Word data size for the peripheral to access its data register and set Word data size
|
|
61 for the Memory to gain in access time. Each two half words will be packed and written in
|
|
62 a single access to a Word in the Memory).
|
|
63
|
|
64 -@- When FIFO is disabled, it is not allowed to configure different Data Sizes for Source
|
|
65 and Destination. In this case the Peripheral Data Size will be applied to both Source
|
|
66 and Destination.
|
|
67
|
|
68 *** DMA HAL driver macros list ***
|
|
69 =============================================
|
|
70 [..]
|
|
71 Below the list of most used macros in DMA HAL driver.
|
|
72
|
|
73 (+) __HAL_DMA_ENABLE: Enable the specified DMA Stream.
|
|
74 (+) __HAL_DMA_DISABLE: Disable the specified DMA Stream.
|
|
75 (+) __HAL_DMA_GET_FS: Return the current DMA Stream FIFO filled level.
|
|
76 (+) __HAL_DMA_GET_FLAG: Get the DMA Stream pending flags.
|
|
77 (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Stream pending flags.
|
|
78 (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Stream interrupts.
|
|
79 (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Stream interrupts.
|
|
80 (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Stream interrupt has occurred or not.
|
|
81
|
|
82 [..]
|
|
83 (@) You can refer to the DMA HAL driver header file for more useful macros
|
|
84
|
|
85 @endverbatim
|
|
86 ******************************************************************************
|
|
87 * @attention
|
|
88 *
|
|
89 * <h2><center>© COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
|
|
90 *
|
|
91 * Redistribution and use in source and binary forms, with or without modification,
|
|
92 * are permitted provided that the following conditions are met:
|
|
93 * 1. Redistributions of source code must retain the above copyright notice,
|
|
94 * this list of conditions and the following disclaimer.
|
|
95 * 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
96 * this list of conditions and the following disclaimer in the documentation
|
|
97 * and/or other materials provided with the distribution.
|
|
98 * 3. Neither the name of STMicroelectronics nor the names of its contributors
|
|
99 * may be used to endorse or promote products derived from this software
|
|
100 * without specific prior written permission.
|
|
101 *
|
|
102 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
103 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
104 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
105 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
106 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
107 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
108 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
109 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
110 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
111 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
112 *
|
|
113 ******************************************************************************
|
|
114 */
|
|
115
|
|
116 /* Includes ------------------------------------------------------------------*/
|
|
117 #include "stm32f4xx_hal.h"
|
|
118
|
|
119 /** @addtogroup STM32F4xx_HAL_Driver
|
|
120 * @{
|
|
121 */
|
|
122
|
|
123 /** @defgroup DMA DMA
|
|
124 * @brief DMA HAL module driver
|
|
125 * @{
|
|
126 */
|
|
127
|
|
128 #ifdef HAL_DMA_MODULE_ENABLED
|
|
129
|
|
130 /* Private types -------------------------------------------------------------*/
|
|
131 /* Private variables ---------------------------------------------------------*/
|
|
132 /* Private constants ---------------------------------------------------------*/
|
|
133 /** @addtogroup DMA_Private_Constants
|
|
134 * @{
|
|
135 */
|
|
136 #define HAL_TIMEOUT_DMA_ABORT ((uint32_t)1000) /* 1s */
|
|
137 /**
|
|
138 * @}
|
|
139 */
|
|
140 /* Private macros ------------------------------------------------------------*/
|
|
141 /* Private functions ---------------------------------------------------------*/
|
|
142 /** @addtogroup DMA_Private_Functions
|
|
143 * @{
|
|
144 */
|
|
145 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
|
|
146 /**
|
|
147 * @}
|
|
148 */
|
|
149
|
|
150 /* Exported functions ---------------------------------------------------------*/
|
|
151 /** @addtogroup DMA_Exported_Functions
|
|
152 * @{
|
|
153 */
|
|
154
|
|
155 /** @addtogroup DMA_Exported_Functions_Group1
|
|
156 *
|
|
157 @verbatim
|
|
158 ===============================================================================
|
|
159 ##### Initialization and de-initialization functions #####
|
|
160 ===============================================================================
|
|
161 [..]
|
|
162 This section provides functions allowing to initialize the DMA Stream source
|
|
163 and destination addresses, incrementation and data sizes, transfer direction,
|
|
164 circular/normal mode selection, memory-to-memory mode selection and Stream priority value.
|
|
165 [..]
|
|
166 The HAL_DMA_Init() function follows the DMA configuration procedures as described in
|
|
167 reference manual.
|
|
168
|
|
169 @endverbatim
|
|
170 * @{
|
|
171 */
|
|
172
|
|
173 /**
|
|
174 * @brief Initializes the DMA according to the specified
|
|
175 * parameters in the DMA_InitTypeDef and create the associated handle.
|
|
176 * @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
|
|
177 * the configuration information for the specified DMA Stream.
|
|
178 * @retval HAL status
|
|
179 */
|
|
180 HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
|
|
181 {
|
|
182 uint32_t tmp = 0;
|
|
183
|
|
184 /* Check the DMA peripheral state */
|
|
185 if(hdma == NULL)
|
|
186 {
|
|
187 return HAL_ERROR;
|
|
188 }
|
|
189
|
|
190 /* Check the parameters */
|
|
191 assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));
|
|
192 assert_param(IS_DMA_CHANNEL(hdma->Init.Channel));
|
|
193 assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
|
|
194 assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
|
|
195 assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
|
|
196 assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
|
|
197 assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
|
|
198 assert_param(IS_DMA_MODE(hdma->Init.Mode));
|
|
199 assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
|
|
200 assert_param(IS_DMA_FIFO_MODE_STATE(hdma->Init.FIFOMode));
|
|
201 /* Check the memory burst, peripheral burst and FIFO threshold parameters only
|
|
202 when FIFO mode is enabled */
|
|
203 if(hdma->Init.FIFOMode != DMA_FIFOMODE_DISABLE)
|
|
204 {
|
|
205 assert_param(IS_DMA_FIFO_THRESHOLD(hdma->Init.FIFOThreshold));
|
|
206 assert_param(IS_DMA_MEMORY_BURST(hdma->Init.MemBurst));
|
|
207 assert_param(IS_DMA_PERIPHERAL_BURST(hdma->Init.PeriphBurst));
|
|
208 }
|
|
209
|
|
210 /* Change DMA peripheral state */
|
|
211 hdma->State = HAL_DMA_STATE_BUSY;
|
|
212
|
|
213 /* Get the CR register value */
|
|
214 tmp = hdma->Instance->CR;
|
|
215
|
|
216 /* Clear CHSEL, MBURST, PBURST, PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR, CT and DBM bits */
|
|
217 tmp &= ((uint32_t)~(DMA_SxCR_CHSEL | DMA_SxCR_MBURST | DMA_SxCR_PBURST | \
|
|
218 DMA_SxCR_PL | DMA_SxCR_MSIZE | DMA_SxCR_PSIZE | \
|
|
219 DMA_SxCR_MINC | DMA_SxCR_PINC | DMA_SxCR_CIRC | \
|
|
220 DMA_SxCR_DIR | DMA_SxCR_CT | DMA_SxCR_DBM));
|
|
221
|
|
222 /* Prepare the DMA Stream configuration */
|
|
223 tmp |= hdma->Init.Channel | hdma->Init.Direction |
|
|
224 hdma->Init.PeriphInc | hdma->Init.MemInc |
|
|
225 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
|
|
226 hdma->Init.Mode | hdma->Init.Priority;
|
|
227
|
|
228 /* the Memory burst and peripheral burst are not used when the FIFO is disabled */
|
|
229 if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
|
|
230 {
|
|
231 /* Get memory burst and peripheral burst */
|
|
232 tmp |= hdma->Init.MemBurst | hdma->Init.PeriphBurst;
|
|
233 }
|
|
234
|
|
235 /* Write to DMA Stream CR register */
|
|
236 hdma->Instance->CR = tmp;
|
|
237
|
|
238 /* Get the FCR register value */
|
|
239 tmp = hdma->Instance->FCR;
|
|
240
|
|
241 /* Clear Direct mode and FIFO threshold bits */
|
|
242 tmp &= (uint32_t)~(DMA_SxFCR_DMDIS | DMA_SxFCR_FTH);
|
|
243
|
|
244 /* Prepare the DMA Stream FIFO configuration */
|
|
245 tmp |= hdma->Init.FIFOMode;
|
|
246
|
|
247 /* the FIFO threshold is not used when the FIFO mode is disabled */
|
|
248 if(hdma->Init.FIFOMode == DMA_FIFOMODE_ENABLE)
|
|
249 {
|
|
250 /* Get the FIFO threshold */
|
|
251 tmp |= hdma->Init.FIFOThreshold;
|
|
252 }
|
|
253
|
|
254 /* Write to DMA Stream FCR */
|
|
255 hdma->Instance->FCR = tmp;
|
|
256
|
|
257 /* Initialize the error code */
|
|
258 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
|
|
259
|
|
260 /* Initialize the DMA state */
|
|
261 hdma->State = HAL_DMA_STATE_READY;
|
|
262
|
|
263 return HAL_OK;
|
|
264 }
|
|
265
|
|
266 /**
|
|
267 * @brief DeInitializes the DMA peripheral
|
|
268 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
|
269 * the configuration information for the specified DMA Stream.
|
|
270 * @retval HAL status
|
|
271 */
|
|
272 HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
|
|
273 {
|
|
274 /* Check the DMA peripheral state */
|
|
275 if(hdma == NULL)
|
|
276 {
|
|
277 return HAL_ERROR;
|
|
278 }
|
|
279
|
|
280 /* Check the DMA peripheral state */
|
|
281 if(hdma->State == HAL_DMA_STATE_BUSY)
|
|
282 {
|
|
283 return HAL_ERROR;
|
|
284 }
|
|
285
|
|
286 /* Disable the selected DMA Streamx */
|
|
287 __HAL_DMA_DISABLE(hdma);
|
|
288
|
|
289 /* Reset DMA Streamx control register */
|
|
290 hdma->Instance->CR = 0;
|
|
291
|
|
292 /* Reset DMA Streamx number of data to transfer register */
|
|
293 hdma->Instance->NDTR = 0;
|
|
294
|
|
295 /* Reset DMA Streamx peripheral address register */
|
|
296 hdma->Instance->PAR = 0;
|
|
297
|
|
298 /* Reset DMA Streamx memory 0 address register */
|
|
299 hdma->Instance->M0AR = 0;
|
|
300
|
|
301 /* Reset DMA Streamx memory 1 address register */
|
|
302 hdma->Instance->M1AR = 0;
|
|
303
|
|
304 /* Reset DMA Streamx FIFO control register */
|
|
305 hdma->Instance->FCR = (uint32_t)0x00000021;
|
|
306
|
|
307 /* Clear all flags */
|
|
308 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
|
|
309 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
|
310 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
|
|
311 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
|
|
312 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
313
|
|
314 /* Initialize the error code */
|
|
315 hdma->ErrorCode = HAL_DMA_ERROR_NONE;
|
|
316
|
|
317 /* Initialize the DMA state */
|
|
318 hdma->State = HAL_DMA_STATE_RESET;
|
|
319
|
|
320 /* Release Lock */
|
|
321 __HAL_UNLOCK(hdma);
|
|
322
|
|
323 return HAL_OK;
|
|
324 }
|
|
325
|
|
326 /**
|
|
327 * @}
|
|
328 */
|
|
329
|
|
330 /** @addtogroup DMA_Exported_Functions_Group2
|
|
331 *
|
|
332 @verbatim
|
|
333 ===============================================================================
|
|
334 ##### IO operation functions #####
|
|
335 ===============================================================================
|
|
336 [..] This section provides functions allowing to:
|
|
337 (+) Configure the source, destination address and data length and Start DMA transfer
|
|
338 (+) Configure the source, destination address and data length and
|
|
339 Start DMA transfer with interrupt
|
|
340 (+) Abort DMA transfer
|
|
341 (+) Poll for transfer complete
|
|
342 (+) Handle DMA interrupt request
|
|
343
|
|
344 @endverbatim
|
|
345 * @{
|
|
346 */
|
|
347
|
|
348 /**
|
|
349 * @brief Starts the DMA Transfer.
|
|
350 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
351 * the configuration information for the specified DMA Stream.
|
|
352 * @param SrcAddress: The source memory Buffer address
|
|
353 * @param DstAddress: The destination memory Buffer address
|
|
354 * @param DataLength: The length of data to be transferred from source to destination
|
|
355 * @retval HAL status
|
|
356 */
|
|
357 HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
|
|
358 {
|
|
359 /* Process locked */
|
|
360 __HAL_LOCK(hdma);
|
|
361
|
|
362 /* Change DMA peripheral state */
|
|
363 hdma->State = HAL_DMA_STATE_BUSY;
|
|
364
|
|
365 /* Check the parameters */
|
|
366 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
|
|
367
|
|
368 /* Disable the peripheral */
|
|
369 __HAL_DMA_DISABLE(hdma);
|
|
370
|
|
371 /* Configure the source, destination address and the data length */
|
|
372 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
|
|
373
|
|
374 /* Enable the Peripheral */
|
|
375 __HAL_DMA_ENABLE(hdma);
|
|
376
|
|
377 return HAL_OK;
|
|
378 }
|
|
379
|
|
380 /**
|
|
381 * @brief Start the DMA Transfer with interrupt enabled.
|
|
382 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
|
383 * the configuration information for the specified DMA Stream.
|
|
384 * @param SrcAddress: The source memory Buffer address
|
|
385 * @param DstAddress: The destination memory Buffer address
|
|
386 * @param DataLength: The length of data to be transferred from source to destination
|
|
387 * @retval HAL status
|
|
388 */
|
|
389 HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
|
|
390 {
|
|
391 /* Process locked */
|
|
392 __HAL_LOCK(hdma);
|
|
393
|
|
394 /* Change DMA peripheral state */
|
|
395 hdma->State = HAL_DMA_STATE_BUSY;
|
|
396
|
|
397 /* Check the parameters */
|
|
398 assert_param(IS_DMA_BUFFER_SIZE(DataLength));
|
|
399
|
|
400 /* Disable the peripheral */
|
|
401 __HAL_DMA_DISABLE(hdma);
|
|
402
|
|
403 /* Configure the source, destination address and the data length */
|
|
404 DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
|
|
405
|
|
406 /* Enable the transfer complete interrupt */
|
|
407 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TC);
|
|
408
|
|
409 /* Enable the Half transfer complete interrupt */
|
|
410 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_HT);
|
|
411
|
|
412 /* Enable the transfer Error interrupt */
|
|
413 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_TE);
|
|
414
|
|
415 /* Enable the FIFO Error interrupt */
|
|
416 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_FE);
|
|
417
|
|
418 /* Enable the direct mode Error interrupt */
|
|
419 __HAL_DMA_ENABLE_IT(hdma, DMA_IT_DME);
|
|
420
|
|
421 /* Enable the Peripheral */
|
|
422 __HAL_DMA_ENABLE(hdma);
|
|
423
|
|
424 return HAL_OK;
|
|
425 }
|
|
426
|
|
427 /**
|
|
428 * @brief Aborts the DMA Transfer.
|
|
429 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
430 * the configuration information for the specified DMA Stream.
|
|
431 *
|
|
432 * @note After disabling a DMA Stream, a check for wait until the DMA Stream is
|
|
433 * effectively disabled is added. If a Stream is disabled
|
|
434 * while a data transfer is ongoing, the current data will be transferred
|
|
435 * and the Stream will be effectively disabled only after the transfer of
|
|
436 * this single data is finished.
|
|
437 * @retval HAL status
|
|
438 */
|
|
439 HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
|
|
440 {
|
|
441 uint32_t tickstart = 0;
|
|
442
|
|
443 /* Disable the stream */
|
|
444 __HAL_DMA_DISABLE(hdma);
|
|
445
|
|
446 /* Get tick */
|
|
447 tickstart = HAL_GetTick();
|
|
448
|
|
449 /* Check if the DMA Stream is effectively disabled */
|
|
450 while((hdma->Instance->CR & DMA_SxCR_EN) != 0)
|
|
451 {
|
|
452 /* Check for the Timeout */
|
|
453 if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_DMA_ABORT)
|
|
454 {
|
|
455 /* Update error code */
|
|
456 hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
|
|
457
|
|
458 /* Process Unlocked */
|
|
459 __HAL_UNLOCK(hdma);
|
|
460
|
|
461 /* Change the DMA state */
|
|
462 hdma->State = HAL_DMA_STATE_TIMEOUT;
|
|
463
|
|
464 return HAL_TIMEOUT;
|
|
465 }
|
|
466 }
|
|
467 /* Process Unlocked */
|
|
468 __HAL_UNLOCK(hdma);
|
|
469
|
|
470 /* Change the DMA state*/
|
|
471 hdma->State = HAL_DMA_STATE_READY;
|
|
472
|
|
473 return HAL_OK;
|
|
474 }
|
|
475
|
|
476 /**
|
|
477 * @brief Polling for transfer complete.
|
|
478 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
|
479 * the configuration information for the specified DMA Stream.
|
|
480 * @param CompleteLevel: Specifies the DMA level complete.
|
|
481 * @param Timeout: Timeout duration.
|
|
482 * @retval HAL status
|
|
483 */
|
|
484 HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
|
|
485 {
|
|
486 uint32_t temp, tmp, tmp1, tmp2;
|
|
487 uint32_t tickstart = 0;
|
|
488
|
|
489 /* Get the level transfer complete flag */
|
|
490 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
|
|
491 {
|
|
492 /* Transfer Complete flag */
|
|
493 temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma);
|
|
494 }
|
|
495 else
|
|
496 {
|
|
497 /* Half Transfer Complete flag */
|
|
498 temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma);
|
|
499 }
|
|
500
|
|
501 /* Get tick */
|
|
502 tickstart = HAL_GetTick();
|
|
503
|
|
504 while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET)
|
|
505 {
|
|
506 tmp = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
|
|
507 tmp1 = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
|
|
508 tmp2 = __HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
|
|
509 if((tmp != RESET) || (tmp1 != RESET) || (tmp2 != RESET))
|
|
510 {
|
|
511 if(tmp != RESET)
|
|
512 {
|
|
513 /* Update error code */
|
|
514 hdma->ErrorCode |= HAL_DMA_ERROR_TE;
|
|
515
|
|
516 /* Clear the transfer error flag */
|
|
517 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
|
|
518 }
|
|
519 if(tmp1 != RESET)
|
|
520 {
|
|
521 /* Update error code */
|
|
522 hdma->ErrorCode |= HAL_DMA_ERROR_FE;
|
|
523
|
|
524 /* Clear the FIFO error flag */
|
|
525 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
|
|
526 }
|
|
527 if(tmp2 != RESET)
|
|
528 {
|
|
529 /* Update error code */
|
|
530 hdma->ErrorCode |= HAL_DMA_ERROR_DME;
|
|
531
|
|
532 /* Clear the Direct Mode error flag */
|
|
533 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
|
|
534 }
|
|
535 /* Change the DMA state */
|
|
536 hdma->State= HAL_DMA_STATE_ERROR;
|
|
537
|
|
538 /* Process Unlocked */
|
|
539 __HAL_UNLOCK(hdma);
|
|
540
|
|
541 return HAL_ERROR;
|
|
542 }
|
|
543 /* Check for the Timeout */
|
|
544 if(Timeout != HAL_MAX_DELAY)
|
|
545 {
|
|
546 if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
|
|
547 {
|
|
548 /* Update error code */
|
|
549 hdma->ErrorCode |= HAL_DMA_ERROR_TIMEOUT;
|
|
550
|
|
551 /* Change the DMA state */
|
|
552 hdma->State = HAL_DMA_STATE_TIMEOUT;
|
|
553
|
|
554 /* Process Unlocked */
|
|
555 __HAL_UNLOCK(hdma);
|
|
556
|
|
557 return HAL_TIMEOUT;
|
|
558 }
|
|
559 }
|
|
560 }
|
|
561
|
|
562 if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
|
|
563 {
|
|
564 /* Multi_Buffering mode enabled */
|
|
565 if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
|
|
566 {
|
|
567 /* Clear the half transfer complete flag */
|
|
568 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
569 /* Clear the transfer complete flag */
|
|
570 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
|
571
|
|
572 /* Current memory buffer used is Memory 0 */
|
|
573 if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
|
|
574 {
|
|
575 /* Change DMA peripheral state */
|
|
576 hdma->State = HAL_DMA_STATE_READY_MEM0;
|
|
577 }
|
|
578 /* Current memory buffer used is Memory 1 */
|
|
579 else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
|
|
580 {
|
|
581 /* Change DMA peripheral state */
|
|
582 hdma->State = HAL_DMA_STATE_READY_MEM1;
|
|
583 }
|
|
584 }
|
|
585 else
|
|
586 {
|
|
587 /* Clear the half transfer complete flag */
|
|
588 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
589 /* Clear the transfer complete flag */
|
|
590 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
|
591
|
|
592 /* The selected Streamx EN bit is cleared (DMA is disabled and all transfers
|
|
593 are complete) */
|
|
594 hdma->State = HAL_DMA_STATE_READY_MEM0;
|
|
595 }
|
|
596 /* Process Unlocked */
|
|
597 __HAL_UNLOCK(hdma);
|
|
598 }
|
|
599 else
|
|
600 {
|
|
601 /* Multi_Buffering mode enabled */
|
|
602 if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
|
|
603 {
|
|
604 /* Clear the half transfer complete flag */
|
|
605 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
606
|
|
607 /* Current memory buffer used is Memory 0 */
|
|
608 if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
|
|
609 {
|
|
610 /* Change DMA peripheral state */
|
|
611 hdma->State = HAL_DMA_STATE_READY_HALF_MEM0;
|
|
612 }
|
|
613 /* Current memory buffer used is Memory 1 */
|
|
614 else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
|
|
615 {
|
|
616 /* Change DMA peripheral state */
|
|
617 hdma->State = HAL_DMA_STATE_READY_HALF_MEM1;
|
|
618 }
|
|
619 }
|
|
620 else
|
|
621 {
|
|
622 /* Clear the half transfer complete flag */
|
|
623 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
624
|
|
625 /* Change DMA peripheral state */
|
|
626 hdma->State = HAL_DMA_STATE_READY_HALF_MEM0;
|
|
627 }
|
|
628 }
|
|
629 return HAL_OK;
|
|
630 }
|
|
631
|
|
632 /**
|
|
633 * @brief Handles DMA interrupt request.
|
|
634 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
|
635 * the configuration information for the specified DMA Stream.
|
|
636 * @retval None
|
|
637 */
|
|
638 void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
|
|
639 {
|
|
640 /* Transfer Error Interrupt management ***************************************/
|
|
641 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET)
|
|
642 {
|
|
643 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TE) != RESET)
|
|
644 {
|
|
645 /* Disable the transfer error interrupt */
|
|
646 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE);
|
|
647
|
|
648 /* Clear the transfer error flag */
|
|
649 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma));
|
|
650
|
|
651 /* Update error code */
|
|
652 hdma->ErrorCode |= HAL_DMA_ERROR_TE;
|
|
653
|
|
654 /* Change the DMA state */
|
|
655 hdma->State = HAL_DMA_STATE_ERROR;
|
|
656
|
|
657 /* Process Unlocked */
|
|
658 __HAL_UNLOCK(hdma);
|
|
659
|
|
660 if(hdma->XferErrorCallback != NULL)
|
|
661 {
|
|
662 /* Transfer error callback */
|
|
663 hdma->XferErrorCallback(hdma);
|
|
664 }
|
|
665 }
|
|
666 }
|
|
667 /* FIFO Error Interrupt management ******************************************/
|
|
668 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma)) != RESET)
|
|
669 {
|
|
670 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_FE) != RESET)
|
|
671 {
|
|
672 /* Disable the FIFO Error interrupt */
|
|
673 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_FE);
|
|
674
|
|
675 /* Clear the FIFO error flag */
|
|
676 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_FE_FLAG_INDEX(hdma));
|
|
677
|
|
678 /* Update error code */
|
|
679 hdma->ErrorCode |= HAL_DMA_ERROR_FE;
|
|
680
|
|
681 /* Change the DMA state */
|
|
682 hdma->State = HAL_DMA_STATE_ERROR;
|
|
683
|
|
684 /* Process Unlocked */
|
|
685 __HAL_UNLOCK(hdma);
|
|
686
|
|
687 if(hdma->XferErrorCallback != NULL)
|
|
688 {
|
|
689 /* Transfer error callback */
|
|
690 hdma->XferErrorCallback(hdma);
|
|
691 }
|
|
692 }
|
|
693 }
|
|
694 /* Direct Mode Error Interrupt management ***********************************/
|
|
695 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma)) != RESET)
|
|
696 {
|
|
697 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_DME) != RESET)
|
|
698 {
|
|
699 /* Disable the direct mode Error interrupt */
|
|
700 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_DME);
|
|
701
|
|
702 /* Clear the direct mode error flag */
|
|
703 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_DME_FLAG_INDEX(hdma));
|
|
704
|
|
705 /* Update error code */
|
|
706 hdma->ErrorCode |= HAL_DMA_ERROR_DME;
|
|
707
|
|
708 /* Change the DMA state */
|
|
709 hdma->State = HAL_DMA_STATE_ERROR;
|
|
710
|
|
711 /* Process Unlocked */
|
|
712 __HAL_UNLOCK(hdma);
|
|
713
|
|
714 if(hdma->XferErrorCallback != NULL)
|
|
715 {
|
|
716 /* Transfer error callback */
|
|
717 hdma->XferErrorCallback(hdma);
|
|
718 }
|
|
719 }
|
|
720 }
|
|
721 /* Half Transfer Complete Interrupt management ******************************/
|
|
722 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma)) != RESET)
|
|
723 {
|
|
724 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_HT) != RESET)
|
|
725 {
|
|
726 /* Multi_Buffering mode enabled */
|
|
727 if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
|
|
728 {
|
|
729 /* Clear the half transfer complete flag */
|
|
730 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
731
|
|
732 /* Current memory buffer used is Memory 0 */
|
|
733 if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
|
|
734 {
|
|
735 /* Change DMA peripheral state */
|
|
736 hdma->State = HAL_DMA_STATE_READY_HALF_MEM0;
|
|
737 }
|
|
738 /* Current memory buffer used is Memory 1 */
|
|
739 else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
|
|
740 {
|
|
741 /* Change DMA peripheral state */
|
|
742 hdma->State = HAL_DMA_STATE_READY_HALF_MEM1;
|
|
743 }
|
|
744 }
|
|
745 else
|
|
746 {
|
|
747 /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
|
|
748 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
|
|
749 {
|
|
750 /* Disable the half transfer interrupt */
|
|
751 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
|
|
752 }
|
|
753 /* Clear the half transfer complete flag */
|
|
754 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
|
755
|
|
756 /* Change DMA peripheral state */
|
|
757 hdma->State = HAL_DMA_STATE_READY_HALF_MEM0;
|
|
758 }
|
|
759
|
|
760 if(hdma->XferHalfCpltCallback != NULL)
|
|
761 {
|
|
762 /* Half transfer callback */
|
|
763 hdma->XferHalfCpltCallback(hdma);
|
|
764 }
|
|
765 }
|
|
766 }
|
|
767 /* Transfer Complete Interrupt management ***********************************/
|
|
768 if(__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma)) != RESET)
|
|
769 {
|
|
770 if(__HAL_DMA_GET_IT_SOURCE(hdma, DMA_IT_TC) != RESET)
|
|
771 {
|
|
772 if(((hdma->Instance->CR) & (uint32_t)(DMA_SxCR_DBM)) != 0)
|
|
773 {
|
|
774 /* Clear the transfer complete flag */
|
|
775 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
|
776
|
|
777 /* Current memory buffer used is Memory 1 */
|
|
778 if((hdma->Instance->CR & DMA_SxCR_CT) == 0)
|
|
779 {
|
|
780 if(hdma->XferM1CpltCallback != NULL)
|
|
781 {
|
|
782 /* Transfer complete Callback for memory1 */
|
|
783 hdma->XferM1CpltCallback(hdma);
|
|
784 }
|
|
785 }
|
|
786 /* Current memory buffer used is Memory 0 */
|
|
787 else if((hdma->Instance->CR & DMA_SxCR_CT) != 0)
|
|
788 {
|
|
789 if(hdma->XferCpltCallback != NULL)
|
|
790 {
|
|
791 /* Transfer complete Callback for memory0 */
|
|
792 hdma->XferCpltCallback(hdma);
|
|
793 }
|
|
794 }
|
|
795 }
|
|
796 /* Disable the transfer complete interrupt if the DMA mode is not CIRCULAR */
|
|
797 else
|
|
798 {
|
|
799 if((hdma->Instance->CR & DMA_SxCR_CIRC) == 0)
|
|
800 {
|
|
801 /* Disable the transfer complete interrupt */
|
|
802 __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TC);
|
|
803 }
|
|
804 /* Clear the transfer complete flag */
|
|
805 __HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
|
806
|
|
807 /* Update error code */
|
|
808 hdma->ErrorCode |= HAL_DMA_ERROR_NONE;
|
|
809
|
|
810 /* Change the DMA state */
|
|
811 hdma->State = HAL_DMA_STATE_READY_MEM0;
|
|
812
|
|
813 /* Process Unlocked */
|
|
814 __HAL_UNLOCK(hdma);
|
|
815
|
|
816 if(hdma->XferCpltCallback != NULL)
|
|
817 {
|
|
818 /* Transfer complete callback */
|
|
819 hdma->XferCpltCallback(hdma);
|
|
820 }
|
|
821 }
|
|
822 }
|
|
823 }
|
|
824 }
|
|
825
|
|
826 /**
|
|
827 * @}
|
|
828 */
|
|
829
|
|
830 /** @addtogroup DMA_Exported_Functions_Group3
|
|
831 *
|
|
832 @verbatim
|
|
833 ===============================================================================
|
|
834 ##### State and Errors functions #####
|
|
835 ===============================================================================
|
|
836 [..]
|
|
837 This subsection provides functions allowing to
|
|
838 (+) Check the DMA state
|
|
839 (+) Get error code
|
|
840
|
|
841 @endverbatim
|
|
842 * @{
|
|
843 */
|
|
844
|
|
845 /**
|
|
846 * @brief Returns the DMA state.
|
|
847 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
|
848 * the configuration information for the specified DMA Stream.
|
|
849 * @retval HAL state
|
|
850 */
|
|
851 HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
|
|
852 {
|
|
853 return hdma->State;
|
|
854 }
|
|
855
|
|
856 /**
|
|
857 * @brief Return the DMA error code
|
|
858 * @param hdma : pointer to a DMA_HandleTypeDef structure that contains
|
|
859 * the configuration information for the specified DMA Stream.
|
|
860 * @retval DMA Error Code
|
|
861 */
|
|
862 uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
|
|
863 {
|
|
864 return hdma->ErrorCode;
|
|
865 }
|
|
866
|
|
867 /**
|
|
868 * @}
|
|
869 */
|
|
870
|
|
871 /**
|
|
872 * @}
|
|
873 */
|
|
874
|
|
875 /** @addtogroup DMA_Private_Functions
|
|
876 * @{
|
|
877 */
|
|
878
|
|
879 /**
|
|
880 * @brief Sets the DMA Transfer parameter.
|
|
881 * @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
|
882 * the configuration information for the specified DMA Stream.
|
|
883 * @param SrcAddress: The source memory Buffer address
|
|
884 * @param DstAddress: The destination memory Buffer address
|
|
885 * @param DataLength: The length of data to be transferred from source to destination
|
|
886 * @retval HAL status
|
|
887 */
|
|
888 static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
|
|
889 {
|
|
890 /* Clear DBM bit */
|
|
891 hdma->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM);
|
|
892
|
|
893 /* Configure DMA Stream data length */
|
|
894 hdma->Instance->NDTR = DataLength;
|
|
895
|
|
896 /* Peripheral to Memory */
|
|
897 if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
|
|
898 {
|
|
899 /* Configure DMA Stream destination address */
|
|
900 hdma->Instance->PAR = DstAddress;
|
|
901
|
|
902 /* Configure DMA Stream source address */
|
|
903 hdma->Instance->M0AR = SrcAddress;
|
|
904 }
|
|
905 /* Memory to Peripheral */
|
|
906 else
|
|
907 {
|
|
908 /* Configure DMA Stream source address */
|
|
909 hdma->Instance->PAR = SrcAddress;
|
|
910
|
|
911 /* Configure DMA Stream destination address */
|
|
912 hdma->Instance->M0AR = DstAddress;
|
|
913 }
|
|
914 }
|
|
915 /**
|
|
916 * @}
|
|
917 */
|
|
918
|
|
919 #endif /* HAL_DMA_MODULE_ENABLED */
|
|
920 /**
|
|
921 * @}
|
|
922 */
|
|
923
|
|
924 /**
|
|
925 * @}
|
|
926 */
|
|
927
|
|
928 /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|