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