Mercurial > public > ostc4
comparison Common/Drivers/STM32F4xx_HAL_DRIVER_v120/Src/stm32f4xx_hal_dma.c @ 38:5f11787b4f42
include in ostc4 repository
author | heinrichsweikamp |
---|---|
date | Sat, 28 Apr 2018 11:52:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
37:ccc45c0e1ea2 | 38:5f11787b4f42 |
---|---|
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****/ |