1 | /** |
---|
2 | ****************************************************************************** |
---|
3 | * @file stm32g0xx_hal_dma.c |
---|
4 | * @author MCD Application Team |
---|
5 | * @brief DMA HAL module driver. |
---|
6 | * This file provides firmware functions to manage the following |
---|
7 | * functionalities of the Direct Memory Access (DMA) peripheral: |
---|
8 | * + Initialization and de-initialization functions |
---|
9 | * + IO operation functions |
---|
10 | * + Peripheral State and errors functions |
---|
11 | * |
---|
12 | ****************************************************************************** |
---|
13 | * @attention |
---|
14 | * |
---|
15 | * Copyright (c) 2018 STMicroelectronics. |
---|
16 | * All rights reserved. |
---|
17 | * |
---|
18 | * This software is licensed under terms that can be found in the LICENSE file |
---|
19 | * in the root directory of this software component. |
---|
20 | * If no LICENSE file comes with this software, it is provided AS-IS. |
---|
21 | * |
---|
22 | ****************************************************************************** |
---|
23 | @verbatim |
---|
24 | ============================================================================== |
---|
25 | ##### How to use this driver ##### |
---|
26 | ============================================================================== |
---|
27 | [..] |
---|
28 | (#) Enable and configure the peripheral to be connected to the DMA Channel |
---|
29 | (except for internal SRAM / FLASH memories: no initialization is |
---|
30 | necessary). Please refer to the Reference manual for connection between peripherals |
---|
31 | and DMA requests. |
---|
32 | |
---|
33 | (#) For a given Channel, program the required configuration through the following parameters: |
---|
34 | Channel request, Transfer Direction, Source and Destination data formats, |
---|
35 | Circular or Normal mode, Channel Priority level, Source and Destination Increment mode |
---|
36 | using HAL_DMA_Init() function. |
---|
37 | |
---|
38 | Prior to HAL_DMA_Init the peripheral clock shall be enabled for both DMA & DMAMUX |
---|
39 | thanks to: |
---|
40 | (##) DMA1 or DMA2: __HAL_RCC_DMA1_CLK_ENABLE() or __HAL_RCC_DMA2_CLK_ENABLE(); |
---|
41 | |
---|
42 | (#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error |
---|
43 | detection. |
---|
44 | |
---|
45 | (#) Use HAL_DMA_Abort() function to abort the current transfer |
---|
46 | |
---|
47 | -@- In Memory-to-Memory transfer mode, Circular mode is not allowed. |
---|
48 | |
---|
49 | *** Polling mode IO operation *** |
---|
50 | ================================= |
---|
51 | [..] |
---|
52 | (+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source |
---|
53 | address and destination address and the Length of data to be transferred |
---|
54 | (+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this |
---|
55 | case a fixed Timeout can be configured by User depending from his application. |
---|
56 | |
---|
57 | *** Interrupt mode IO operation *** |
---|
58 | =================================== |
---|
59 | [..] |
---|
60 | (+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority() |
---|
61 | (+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ() |
---|
62 | (+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of |
---|
63 | Source address and destination address and the Length of data to be transferred. |
---|
64 | In this case the DMA interrupt is configured |
---|
65 | (+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine |
---|
66 | (+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can |
---|
67 | add his own function to register callbacks with HAL_DMA_RegisterCallback(). |
---|
68 | |
---|
69 | *** DMA HAL driver macros list *** |
---|
70 | ============================================= |
---|
71 | [..] |
---|
72 | Below the list of macros in DMA HAL driver. |
---|
73 | |
---|
74 | (+) __HAL_DMA_ENABLE: Enable the specified DMA Channel. |
---|
75 | (+) __HAL_DMA_DISABLE: Disable the specified DMA Channel. |
---|
76 | (+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags. |
---|
77 | (+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags. |
---|
78 | (+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts. |
---|
79 | (+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts. |
---|
80 | (+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt is enabled or not. |
---|
81 | |
---|
82 | [..] |
---|
83 | (@) You can refer to the DMA HAL driver header file for more useful macros |
---|
84 | |
---|
85 | @endverbatim |
---|
86 | ****************************************************************************** |
---|
87 | */ |
---|
88 | |
---|
89 | /* Includes ------------------------------------------------------------------*/ |
---|
90 | #include "stm32g0xx_hal.h" |
---|
91 | |
---|
92 | /** @addtogroup STM32G0xx_HAL_Driver |
---|
93 | * @{ |
---|
94 | */ |
---|
95 | |
---|
96 | /** @defgroup DMA DMA |
---|
97 | * @brief DMA HAL module driver |
---|
98 | * @{ |
---|
99 | */ |
---|
100 | |
---|
101 | #ifdef HAL_DMA_MODULE_ENABLED |
---|
102 | |
---|
103 | /* Private typedef -----------------------------------------------------------*/ |
---|
104 | /* Private define ------------------------------------------------------------*/ |
---|
105 | /* Private macro -------------------------------------------------------------*/ |
---|
106 | /* Private variables ---------------------------------------------------------*/ |
---|
107 | /* Private function prototypes -----------------------------------------------*/ |
---|
108 | |
---|
109 | /** @defgroup DMA_Private_Functions DMA Private Functions |
---|
110 | * @{ |
---|
111 | */ |
---|
112 | static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength); |
---|
113 | static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma); |
---|
114 | static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma); |
---|
115 | |
---|
116 | /** |
---|
117 | * @} |
---|
118 | */ |
---|
119 | |
---|
120 | /* Exported functions ---------------------------------------------------------*/ |
---|
121 | |
---|
122 | /** @defgroup DMA_Exported_Functions DMA Exported Functions |
---|
123 | * @{ |
---|
124 | */ |
---|
125 | |
---|
126 | /** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions |
---|
127 | * @brief Initialization and de-initialization functions |
---|
128 | * |
---|
129 | @verbatim |
---|
130 | =============================================================================== |
---|
131 | ##### Initialization and de-initialization functions ##### |
---|
132 | =============================================================================== |
---|
133 | [..] |
---|
134 | This section provides functions allowing to initialize the DMA Channel source |
---|
135 | and destination addresses, incrementation and data sizes, transfer direction, |
---|
136 | circular/normal mode selection, memory-to-memory mode selection and Channel priority value. |
---|
137 | [..] |
---|
138 | The HAL_DMA_Init() function follows the DMA configuration procedures as described in |
---|
139 | reference manual. |
---|
140 | |
---|
141 | @endverbatim |
---|
142 | * @{ |
---|
143 | */ |
---|
144 | |
---|
145 | /** |
---|
146 | * @brief Initialize the DMA according to the specified |
---|
147 | * parameters in the DMA_InitTypeDef and initialize the associated handle. |
---|
148 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
149 | * the configuration information for the specified DMA Channel. |
---|
150 | * @retval HAL status |
---|
151 | */ |
---|
152 | HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma) |
---|
153 | { |
---|
154 | /* Check the DMA handle allocation */ |
---|
155 | if (hdma == NULL) |
---|
156 | { |
---|
157 | return HAL_ERROR; |
---|
158 | } |
---|
159 | |
---|
160 | /* Check the parameters */ |
---|
161 | assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); |
---|
162 | assert_param(IS_DMA_DIRECTION(hdma->Init.Direction)); |
---|
163 | assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc)); |
---|
164 | assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc)); |
---|
165 | assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment)); |
---|
166 | assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment)); |
---|
167 | assert_param(IS_DMA_MODE(hdma->Init.Mode)); |
---|
168 | assert_param(IS_DMA_PRIORITY(hdma->Init.Priority)); |
---|
169 | |
---|
170 | assert_param(IS_DMA_ALL_REQUEST(hdma->Init.Request)); |
---|
171 | |
---|
172 | /* Compute the channel index */ |
---|
173 | #if defined(DMA2) |
---|
174 | if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) |
---|
175 | { |
---|
176 | /* DMA1 */ |
---|
177 | hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U; |
---|
178 | hdma->DmaBaseAddress = DMA1; |
---|
179 | } |
---|
180 | else |
---|
181 | { |
---|
182 | /* DMA2 */ |
---|
183 | hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U; |
---|
184 | hdma->DmaBaseAddress = DMA2; |
---|
185 | } |
---|
186 | #else |
---|
187 | hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U; |
---|
188 | #endif /* DMA2 */ |
---|
189 | |
---|
190 | /* Change DMA peripheral state */ |
---|
191 | hdma->State = HAL_DMA_STATE_BUSY; |
---|
192 | |
---|
193 | /* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC, DIR and MEM2MEM bits */ |
---|
194 | CLEAR_BIT(hdma->Instance->CCR, (DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \ |
---|
195 | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \ |
---|
196 | DMA_CCR_DIR | DMA_CCR_MEM2MEM)); |
---|
197 | |
---|
198 | /* Set the DMA Channel configuration */ |
---|
199 | SET_BIT(hdma->Instance->CCR, (hdma->Init.Direction | \ |
---|
200 | hdma->Init.PeriphInc | hdma->Init.MemInc | \ |
---|
201 | hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment | \ |
---|
202 | hdma->Init.Mode | hdma->Init.Priority)); |
---|
203 | |
---|
204 | /* Initialize parameters for DMAMUX channel : |
---|
205 | DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask |
---|
206 | */ |
---|
207 | DMA_CalcDMAMUXChannelBaseAndMask(hdma); |
---|
208 | |
---|
209 | if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY) |
---|
210 | { |
---|
211 | /* if memory to memory force the request to 0*/ |
---|
212 | hdma->Init.Request = DMA_REQUEST_MEM2MEM; |
---|
213 | } |
---|
214 | |
---|
215 | /* Set peripheral request to DMAMUX channel */ |
---|
216 | hdma->DMAmuxChannel->CCR = (hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID); |
---|
217 | |
---|
218 | /* Clear the DMAMUX synchro overrun flag */ |
---|
219 | hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; |
---|
220 | |
---|
221 | if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3))) |
---|
222 | { |
---|
223 | /* Initialize parameters for DMAMUX request generator : |
---|
224 | DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask |
---|
225 | */ |
---|
226 | DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); |
---|
227 | |
---|
228 | /* Reset the DMAMUX request generator register*/ |
---|
229 | hdma->DMAmuxRequestGen->RGCR = 0U; |
---|
230 | |
---|
231 | /* Clear the DMAMUX request generator overrun flag */ |
---|
232 | hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; |
---|
233 | } |
---|
234 | else |
---|
235 | { |
---|
236 | hdma->DMAmuxRequestGen = 0U; |
---|
237 | hdma->DMAmuxRequestGenStatus = 0U; |
---|
238 | hdma->DMAmuxRequestGenStatusMask = 0U; |
---|
239 | } |
---|
240 | |
---|
241 | /* Initialize the error code */ |
---|
242 | hdma->ErrorCode = HAL_DMA_ERROR_NONE; |
---|
243 | |
---|
244 | /* Initialize the DMA state*/ |
---|
245 | hdma->State = HAL_DMA_STATE_READY; |
---|
246 | |
---|
247 | /* Release Lock */ |
---|
248 | __HAL_UNLOCK(hdma); |
---|
249 | |
---|
250 | return HAL_OK; |
---|
251 | } |
---|
252 | |
---|
253 | /** |
---|
254 | * @brief DeInitialize the DMA peripheral. |
---|
255 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
256 | * the configuration information for the specified DMA Channel. |
---|
257 | * @retval HAL status |
---|
258 | */ |
---|
259 | HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma) |
---|
260 | { |
---|
261 | /* Check the DMA handle allocation */ |
---|
262 | if (NULL == hdma) |
---|
263 | { |
---|
264 | return HAL_ERROR; |
---|
265 | } |
---|
266 | |
---|
267 | /* Check the parameters */ |
---|
268 | assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance)); |
---|
269 | |
---|
270 | /* Disable the selected DMA Channelx */ |
---|
271 | __HAL_DMA_DISABLE(hdma); |
---|
272 | |
---|
273 | /* Compute the channel index */ |
---|
274 | #if defined(DMA2) |
---|
275 | if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1)) |
---|
276 | { |
---|
277 | /* DMA1 */ |
---|
278 | hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U; |
---|
279 | hdma->DmaBaseAddress = DMA1; |
---|
280 | } |
---|
281 | else |
---|
282 | { |
---|
283 | /* DMA2 */ |
---|
284 | hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2U; |
---|
285 | hdma->DmaBaseAddress = DMA2; |
---|
286 | } |
---|
287 | #else |
---|
288 | hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2U; |
---|
289 | #endif /* DMA2 */ |
---|
290 | |
---|
291 | /* Reset DMA Channel control register */ |
---|
292 | hdma->Instance->CCR = 0U; |
---|
293 | |
---|
294 | /* Clear all flags */ |
---|
295 | #if defined(DMA2) |
---|
296 | hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); |
---|
297 | #else |
---|
298 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1CU))); |
---|
299 | #endif /* DMA2 */ |
---|
300 | |
---|
301 | /* Initialize parameters for DMAMUX channel : |
---|
302 | DMAmuxChannel, DMAmuxChannelStatus and DMAmuxChannelStatusMask */ |
---|
303 | |
---|
304 | DMA_CalcDMAMUXChannelBaseAndMask(hdma); |
---|
305 | |
---|
306 | /* Reset the DMAMUX channel that corresponds to the DMA channel */ |
---|
307 | hdma->DMAmuxChannel->CCR = 0U; |
---|
308 | |
---|
309 | /* Clear the DMAMUX synchro overrun flag */ |
---|
310 | hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; |
---|
311 | |
---|
312 | /* Reset Request generator parameters if any */ |
---|
313 | if (((hdma->Init.Request > 0UL) && (hdma->Init.Request <= DMA_REQUEST_GENERATOR3))) |
---|
314 | { |
---|
315 | /* Initialize parameters for DMAMUX request generator : |
---|
316 | DMAmuxRequestGen, DMAmuxRequestGenStatus and DMAmuxRequestGenStatusMask |
---|
317 | */ |
---|
318 | DMA_CalcDMAMUXRequestGenBaseAndMask(hdma); |
---|
319 | |
---|
320 | /* Reset the DMAMUX request generator register*/ |
---|
321 | hdma->DMAmuxRequestGen->RGCR = 0U; |
---|
322 | |
---|
323 | /* Clear the DMAMUX request generator overrun flag */ |
---|
324 | hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; |
---|
325 | } |
---|
326 | |
---|
327 | hdma->DMAmuxRequestGen = 0U; |
---|
328 | hdma->DMAmuxRequestGenStatus = 0U; |
---|
329 | hdma->DMAmuxRequestGenStatusMask = 0U; |
---|
330 | |
---|
331 | /* Clean callbacks */ |
---|
332 | hdma->XferCpltCallback = NULL; |
---|
333 | hdma->XferHalfCpltCallback = NULL; |
---|
334 | hdma->XferErrorCallback = NULL; |
---|
335 | hdma->XferAbortCallback = NULL; |
---|
336 | |
---|
337 | /* Initialize the error code */ |
---|
338 | hdma->ErrorCode = HAL_DMA_ERROR_NONE; |
---|
339 | |
---|
340 | /* Initialize the DMA state */ |
---|
341 | hdma->State = HAL_DMA_STATE_RESET; |
---|
342 | |
---|
343 | /* Release Lock */ |
---|
344 | __HAL_UNLOCK(hdma); |
---|
345 | |
---|
346 | return HAL_OK; |
---|
347 | } |
---|
348 | |
---|
349 | /** |
---|
350 | * @} |
---|
351 | */ |
---|
352 | |
---|
353 | /** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions |
---|
354 | * @brief Input and Output operation functions |
---|
355 | * |
---|
356 | @verbatim |
---|
357 | =============================================================================== |
---|
358 | ##### IO operation functions ##### |
---|
359 | =============================================================================== |
---|
360 | [..] This section provides functions allowing to: |
---|
361 | (+) Configure the source, destination address and data length and Start DMA transfer |
---|
362 | (+) Configure the source, destination address and data length and |
---|
363 | Start DMA transfer with interrupt |
---|
364 | (+) Abort DMA transfer |
---|
365 | (+) Poll for transfer complete |
---|
366 | (+) Handle DMA interrupt request |
---|
367 | (+) Register and Unregister DMA callbacks |
---|
368 | |
---|
369 | @endverbatim |
---|
370 | * @{ |
---|
371 | */ |
---|
372 | |
---|
373 | /** |
---|
374 | * @brief Start the DMA Transfer. |
---|
375 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
376 | * the configuration information for the specified DMA Channel. |
---|
377 | * @param SrcAddress The source memory Buffer address |
---|
378 | * @param DstAddress The destination memory Buffer address |
---|
379 | * @param DataLength The length of data to be transferred from source to destination |
---|
380 | * @retval HAL status |
---|
381 | */ |
---|
382 | HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) |
---|
383 | { |
---|
384 | HAL_StatusTypeDef status = HAL_OK; |
---|
385 | |
---|
386 | /* Check the parameters */ |
---|
387 | assert_param(IS_DMA_BUFFER_SIZE(DataLength)); |
---|
388 | |
---|
389 | /* Process locked */ |
---|
390 | __HAL_LOCK(hdma); |
---|
391 | |
---|
392 | if (hdma->State == HAL_DMA_STATE_READY) |
---|
393 | { |
---|
394 | /* Change DMA peripheral state */ |
---|
395 | hdma->State = HAL_DMA_STATE_BUSY; |
---|
396 | |
---|
397 | /* Initialize the error code */ |
---|
398 | hdma->ErrorCode = HAL_DMA_ERROR_NONE; |
---|
399 | |
---|
400 | /* Disable the peripheral */ |
---|
401 | __HAL_DMA_DISABLE(hdma); |
---|
402 | |
---|
403 | /* Configure the source, destination address and the data length & clear flags*/ |
---|
404 | DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); |
---|
405 | |
---|
406 | /* Enable the Peripheral */ |
---|
407 | __HAL_DMA_ENABLE(hdma); |
---|
408 | } |
---|
409 | else |
---|
410 | { |
---|
411 | /* Change the error code */ |
---|
412 | hdma->ErrorCode = HAL_DMA_ERROR_BUSY; |
---|
413 | |
---|
414 | /* Process Unlocked */ |
---|
415 | __HAL_UNLOCK(hdma); |
---|
416 | |
---|
417 | /* Return error status */ |
---|
418 | status = HAL_ERROR; |
---|
419 | } |
---|
420 | |
---|
421 | return status; |
---|
422 | } |
---|
423 | |
---|
424 | /** |
---|
425 | * @brief Start the DMA Transfer with interrupt enabled. |
---|
426 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
427 | * the configuration information for the specified DMA Channel. |
---|
428 | * @param SrcAddress The source memory Buffer address |
---|
429 | * @param DstAddress The destination memory Buffer address |
---|
430 | * @param DataLength The length of data to be transferred from source to destination |
---|
431 | * @retval HAL status |
---|
432 | */ |
---|
433 | HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, |
---|
434 | uint32_t DataLength) |
---|
435 | { |
---|
436 | HAL_StatusTypeDef status = HAL_OK; |
---|
437 | |
---|
438 | /* Check the parameters */ |
---|
439 | assert_param(IS_DMA_BUFFER_SIZE(DataLength)); |
---|
440 | |
---|
441 | /* Process locked */ |
---|
442 | __HAL_LOCK(hdma); |
---|
443 | |
---|
444 | if (hdma->State == HAL_DMA_STATE_READY) |
---|
445 | { |
---|
446 | /* Change DMA peripheral state */ |
---|
447 | hdma->State = HAL_DMA_STATE_BUSY; |
---|
448 | hdma->ErrorCode = HAL_DMA_ERROR_NONE; |
---|
449 | |
---|
450 | /* Disable the peripheral */ |
---|
451 | __HAL_DMA_DISABLE(hdma); |
---|
452 | |
---|
453 | /* Configure the source, destination address and the data length & clear flags*/ |
---|
454 | DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength); |
---|
455 | |
---|
456 | /* Enable the transfer complete interrupt */ |
---|
457 | /* Enable the transfer Error interrupt */ |
---|
458 | if (NULL != hdma->XferHalfCpltCallback) |
---|
459 | { |
---|
460 | /* Enable the Half transfer complete interrupt as well */ |
---|
461 | __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); |
---|
462 | } |
---|
463 | else |
---|
464 | { |
---|
465 | __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); |
---|
466 | __HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE)); |
---|
467 | } |
---|
468 | |
---|
469 | /* Check if DMAMUX Synchronization is enabled*/ |
---|
470 | if ((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U) |
---|
471 | { |
---|
472 | /* Enable DMAMUX sync overrun IT*/ |
---|
473 | hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE; |
---|
474 | } |
---|
475 | |
---|
476 | if (hdma->DMAmuxRequestGen != 0U) |
---|
477 | { |
---|
478 | /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/ |
---|
479 | /* enable the request gen overrun IT*/ |
---|
480 | hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; |
---|
481 | } |
---|
482 | |
---|
483 | /* Enable the Peripheral */ |
---|
484 | __HAL_DMA_ENABLE(hdma); |
---|
485 | } |
---|
486 | else |
---|
487 | { |
---|
488 | /* Change the error code */ |
---|
489 | hdma->ErrorCode = HAL_DMA_ERROR_BUSY; |
---|
490 | |
---|
491 | /* Process Unlocked */ |
---|
492 | __HAL_UNLOCK(hdma); |
---|
493 | |
---|
494 | /* Return error status */ |
---|
495 | status = HAL_ERROR; |
---|
496 | } |
---|
497 | |
---|
498 | return status; |
---|
499 | } |
---|
500 | |
---|
501 | /** |
---|
502 | * @brief Abort the DMA Transfer. |
---|
503 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
504 | * the configuration information for the specified DMA Channel. |
---|
505 | * @retval HAL status |
---|
506 | */ |
---|
507 | HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma) |
---|
508 | { |
---|
509 | /* Check the DMA peripheral handle */ |
---|
510 | if (NULL == hdma) |
---|
511 | { |
---|
512 | return HAL_ERROR; |
---|
513 | } |
---|
514 | |
---|
515 | /* Check the DMA peripheral state */ |
---|
516 | if (hdma->State != HAL_DMA_STATE_BUSY) |
---|
517 | { |
---|
518 | hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; |
---|
519 | |
---|
520 | /* Process Unlocked */ |
---|
521 | __HAL_UNLOCK(hdma); |
---|
522 | |
---|
523 | return HAL_ERROR; |
---|
524 | } |
---|
525 | else |
---|
526 | { |
---|
527 | /* Disable DMA IT */ |
---|
528 | __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); |
---|
529 | |
---|
530 | /* disable the DMAMUX sync overrun IT*/ |
---|
531 | hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; |
---|
532 | |
---|
533 | /* Disable the channel */ |
---|
534 | __HAL_DMA_DISABLE(hdma); |
---|
535 | |
---|
536 | /* Clear all flags */ |
---|
537 | #if defined(DMA2) |
---|
538 | hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); |
---|
539 | #else |
---|
540 | __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1CU))); |
---|
541 | #endif /* DMA2 */ |
---|
542 | |
---|
543 | /* Clear the DMAMUX synchro overrun flag */ |
---|
544 | hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; |
---|
545 | |
---|
546 | if (hdma->DMAmuxRequestGen != 0U) |
---|
547 | { |
---|
548 | /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ |
---|
549 | /* disable the request gen overrun IT*/ |
---|
550 | hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; |
---|
551 | |
---|
552 | /* Clear the DMAMUX request generator overrun flag */ |
---|
553 | hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; |
---|
554 | } |
---|
555 | |
---|
556 | /* Change the DMA state */ |
---|
557 | hdma->State = HAL_DMA_STATE_READY; |
---|
558 | |
---|
559 | /* Process Unlocked */ |
---|
560 | __HAL_UNLOCK(hdma); |
---|
561 | } |
---|
562 | |
---|
563 | return HAL_OK; |
---|
564 | } |
---|
565 | |
---|
566 | /** |
---|
567 | * @brief Aborts the DMA Transfer in Interrupt mode. |
---|
568 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
569 | * the configuration information for the specified DMA Channel. |
---|
570 | * @retval HAL status |
---|
571 | */ |
---|
572 | HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma) |
---|
573 | { |
---|
574 | HAL_StatusTypeDef status = HAL_OK; |
---|
575 | |
---|
576 | if (hdma->State != HAL_DMA_STATE_BUSY) |
---|
577 | { |
---|
578 | /* no transfer ongoing */ |
---|
579 | hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; |
---|
580 | |
---|
581 | status = HAL_ERROR; |
---|
582 | } |
---|
583 | else |
---|
584 | { |
---|
585 | /* Disable DMA IT */ |
---|
586 | __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); |
---|
587 | |
---|
588 | /* Disable the channel */ |
---|
589 | __HAL_DMA_DISABLE(hdma); |
---|
590 | |
---|
591 | /* disable the DMAMUX sync overrun IT*/ |
---|
592 | hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE; |
---|
593 | |
---|
594 | /* Clear all flags */ |
---|
595 | #if defined(DMA2) |
---|
596 | hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); |
---|
597 | #else |
---|
598 | __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1CU))); |
---|
599 | #endif /* DMA2 */ |
---|
600 | |
---|
601 | /* Clear the DMAMUX synchro overrun flag */ |
---|
602 | hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; |
---|
603 | |
---|
604 | if (hdma->DMAmuxRequestGen != 0U) |
---|
605 | { |
---|
606 | /* if using DMAMUX request generator, disable the DMAMUX request generator overrun IT*/ |
---|
607 | /* disable the request gen overrun IT*/ |
---|
608 | hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE; |
---|
609 | |
---|
610 | /* Clear the DMAMUX request generator overrun flag */ |
---|
611 | hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; |
---|
612 | } |
---|
613 | |
---|
614 | /* Change the DMA state */ |
---|
615 | hdma->State = HAL_DMA_STATE_READY; |
---|
616 | |
---|
617 | /* Process Unlocked */ |
---|
618 | __HAL_UNLOCK(hdma); |
---|
619 | |
---|
620 | /* Call User Abort callback */ |
---|
621 | if (hdma->XferAbortCallback != NULL) |
---|
622 | { |
---|
623 | hdma->XferAbortCallback(hdma); |
---|
624 | } |
---|
625 | } |
---|
626 | return status; |
---|
627 | } |
---|
628 | |
---|
629 | /** |
---|
630 | * @brief Polling for transfer complete. |
---|
631 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
632 | * the configuration information for the specified DMA Channel. |
---|
633 | * @param CompleteLevel Specifies the DMA level complete. |
---|
634 | * @param Timeout Timeout duration. |
---|
635 | * @retval HAL status |
---|
636 | */ |
---|
637 | HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, HAL_DMA_LevelCompleteTypeDef CompleteLevel, |
---|
638 | uint32_t Timeout) |
---|
639 | { |
---|
640 | uint32_t temp; |
---|
641 | uint32_t tickstart; |
---|
642 | |
---|
643 | if (hdma->State != HAL_DMA_STATE_BUSY) |
---|
644 | { |
---|
645 | /* no transfer ongoing */ |
---|
646 | hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER; |
---|
647 | __HAL_UNLOCK(hdma); |
---|
648 | return HAL_ERROR; |
---|
649 | } |
---|
650 | |
---|
651 | /* Polling mode not supported in circular mode */ |
---|
652 | if ((hdma->Instance->CCR & DMA_CCR_CIRC) != 0U) |
---|
653 | { |
---|
654 | hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED; |
---|
655 | return HAL_ERROR; |
---|
656 | } |
---|
657 | |
---|
658 | /* Get the level transfer complete flag */ |
---|
659 | if (HAL_DMA_FULL_TRANSFER == CompleteLevel) |
---|
660 | { |
---|
661 | /* Transfer Complete flag */ |
---|
662 | temp = DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU); |
---|
663 | } |
---|
664 | else |
---|
665 | { |
---|
666 | /* Half Transfer Complete flag */ |
---|
667 | temp = DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU); |
---|
668 | } |
---|
669 | |
---|
670 | /* Get tick */ |
---|
671 | tickstart = HAL_GetTick(); |
---|
672 | |
---|
673 | #if defined(DMA2) |
---|
674 | while ((hdma->DmaBaseAddress->ISR & temp) == 0U) |
---|
675 | { |
---|
676 | if ((hdma->DmaBaseAddress->ISR & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU))) != 0U) |
---|
677 | { |
---|
678 | /* When a DMA transfer error occurs */ |
---|
679 | /* A hardware clear of its EN bits is performed */ |
---|
680 | /* Clear all flags */ |
---|
681 | hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); |
---|
682 | |
---|
683 | /* Update error code */ |
---|
684 | hdma->ErrorCode = HAL_DMA_ERROR_TE; |
---|
685 | |
---|
686 | /* Change the DMA state */ |
---|
687 | hdma->State = HAL_DMA_STATE_READY; |
---|
688 | |
---|
689 | /* Process Unlocked */ |
---|
690 | __HAL_UNLOCK(hdma); |
---|
691 | |
---|
692 | return HAL_ERROR; |
---|
693 | } |
---|
694 | #else |
---|
695 | while (0U == __HAL_DMA_GET_FLAG(hdma, temp)) |
---|
696 | { |
---|
697 | if (0U != __HAL_DMA_GET_FLAG(hdma, (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU)))) |
---|
698 | { |
---|
699 | /* When a DMA transfer error occurs */ |
---|
700 | /* A hardware clear of its EN bits is performed */ |
---|
701 | /* Clear all flags */ |
---|
702 | __HAL_DMA_CLEAR_FLAG(hdma, ((DMA_FLAG_GI1) << (hdma->ChannelIndex & 0x1CU))); |
---|
703 | |
---|
704 | /* Update error code */ |
---|
705 | hdma->ErrorCode = HAL_DMA_ERROR_TE; |
---|
706 | |
---|
707 | /* Change the DMA state */ |
---|
708 | hdma->State = HAL_DMA_STATE_READY; |
---|
709 | |
---|
710 | /* Process Unlocked */ |
---|
711 | __HAL_UNLOCK(hdma); |
---|
712 | |
---|
713 | return HAL_ERROR; |
---|
714 | } |
---|
715 | #endif /* DMA2 */ |
---|
716 | /* Check for the Timeout */ |
---|
717 | if (Timeout != HAL_MAX_DELAY) |
---|
718 | { |
---|
719 | if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U)) |
---|
720 | { |
---|
721 | /* Update error code */ |
---|
722 | hdma->ErrorCode = HAL_DMA_ERROR_TIMEOUT; |
---|
723 | |
---|
724 | /* Change the DMA state */ |
---|
725 | hdma->State = HAL_DMA_STATE_READY; |
---|
726 | |
---|
727 | /* Process Unlocked */ |
---|
728 | __HAL_UNLOCK(hdma); |
---|
729 | |
---|
730 | return HAL_ERROR; |
---|
731 | } |
---|
732 | } |
---|
733 | } |
---|
734 | |
---|
735 | /*Check for DMAMUX Request generator (if used) overrun status */ |
---|
736 | if (hdma->DMAmuxRequestGen != 0U) |
---|
737 | { |
---|
738 | /* if using DMAMUX request generator Check for DMAMUX request generator overrun */ |
---|
739 | if ((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U) |
---|
740 | { |
---|
741 | /* Disable the request gen overrun interrupt */ |
---|
742 | hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE; |
---|
743 | |
---|
744 | /* Clear the DMAMUX request generator overrun flag */ |
---|
745 | hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; |
---|
746 | |
---|
747 | /* Update error code */ |
---|
748 | hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN; |
---|
749 | } |
---|
750 | } |
---|
751 | |
---|
752 | /* Check for DMAMUX Synchronization overrun */ |
---|
753 | if ((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U) |
---|
754 | { |
---|
755 | /* Clear the DMAMUX synchro overrun flag */ |
---|
756 | hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; |
---|
757 | |
---|
758 | /* Update error code */ |
---|
759 | hdma->ErrorCode |= HAL_DMA_ERROR_SYNC; |
---|
760 | } |
---|
761 | |
---|
762 | if (HAL_DMA_FULL_TRANSFER == CompleteLevel) |
---|
763 | { |
---|
764 | /* Clear the transfer complete flag */ |
---|
765 | #if defined(DMA2) |
---|
766 | hdma->DmaBaseAddress->IFCR = (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU)); |
---|
767 | #else |
---|
768 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))); |
---|
769 | #endif /* DMA2 */ |
---|
770 | |
---|
771 | /* Process unlocked */ |
---|
772 | __HAL_UNLOCK(hdma); |
---|
773 | |
---|
774 | /* The selected Channelx EN bit is cleared (DMA is disabled and |
---|
775 | all transfers are complete) */ |
---|
776 | hdma->State = HAL_DMA_STATE_READY; |
---|
777 | } |
---|
778 | else |
---|
779 | { |
---|
780 | /* Clear the half transfer complete flag */ |
---|
781 | #if defined(DMA2) |
---|
782 | hdma->DmaBaseAddress->IFCR = (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU)); |
---|
783 | #else |
---|
784 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU))); |
---|
785 | #endif /* DMA2 */ |
---|
786 | } |
---|
787 | |
---|
788 | return HAL_OK; |
---|
789 | } |
---|
790 | |
---|
791 | /** |
---|
792 | * @brief Handle DMA interrupt request. |
---|
793 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
794 | * the configuration information for the specified DMA Channel. |
---|
795 | * @retval None |
---|
796 | */ |
---|
797 | void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma) |
---|
798 | { |
---|
799 | #if defined(DMA2) |
---|
800 | uint32_t flag_it = hdma->DmaBaseAddress->ISR; |
---|
801 | #else |
---|
802 | uint32_t flag_it = DMA1->ISR; |
---|
803 | #endif /* DMA2 */ |
---|
804 | uint32_t source_it = hdma->Instance->CCR; |
---|
805 | |
---|
806 | /* Half Transfer Complete Interrupt management ******************************/ |
---|
807 | if (((flag_it & (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_HT) != 0U)) |
---|
808 | { |
---|
809 | /* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */ |
---|
810 | if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) |
---|
811 | { |
---|
812 | /* Disable the half transfer interrupt */ |
---|
813 | __HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT); |
---|
814 | } |
---|
815 | /* Clear the half transfer complete flag */ |
---|
816 | #if defined(DMA2) |
---|
817 | hdma->DmaBaseAddress->IFCR = DMA_ISR_HTIF1 << (hdma->ChannelIndex & 0x1CU); |
---|
818 | #else |
---|
819 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_HT1 << (hdma->ChannelIndex & 0x1CU))); |
---|
820 | #endif /* DMA2 */ |
---|
821 | |
---|
822 | /* DMA peripheral state is not updated in Half Transfer */ |
---|
823 | /* but in Transfer Complete case */ |
---|
824 | |
---|
825 | if (hdma->XferHalfCpltCallback != NULL) |
---|
826 | { |
---|
827 | /* Half transfer callback */ |
---|
828 | hdma->XferHalfCpltCallback(hdma); |
---|
829 | } |
---|
830 | } |
---|
831 | |
---|
832 | /* Transfer Complete Interrupt management ***********************************/ |
---|
833 | else if ((0U != (flag_it & (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU)))) && (0U != (source_it & DMA_IT_TC))) |
---|
834 | { |
---|
835 | if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) |
---|
836 | { |
---|
837 | /* Disable the transfer complete and error interrupt */ |
---|
838 | __HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC); |
---|
839 | |
---|
840 | /* Change the DMA state */ |
---|
841 | hdma->State = HAL_DMA_STATE_READY; |
---|
842 | } |
---|
843 | /* Clear the transfer complete flag */ |
---|
844 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_TC1 << (hdma->ChannelIndex & 0x1CU))); |
---|
845 | |
---|
846 | /* Process Unlocked */ |
---|
847 | __HAL_UNLOCK(hdma); |
---|
848 | |
---|
849 | if (hdma->XferCpltCallback != NULL) |
---|
850 | { |
---|
851 | /* Transfer complete callback */ |
---|
852 | hdma->XferCpltCallback(hdma); |
---|
853 | } |
---|
854 | } |
---|
855 | |
---|
856 | /* Transfer Error Interrupt management **************************************/ |
---|
857 | else if (((flag_it & (DMA_FLAG_TE1 << (hdma->ChannelIndex & 0x1CU))) != 0U) && ((source_it & DMA_IT_TE) != 0U)) |
---|
858 | { |
---|
859 | /* When a DMA transfer error occurs */ |
---|
860 | /* A hardware clear of its EN bits is performed */ |
---|
861 | /* Disable ALL DMA IT */ |
---|
862 | __HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE)); |
---|
863 | |
---|
864 | /* Clear all flags */ |
---|
865 | #if defined(DMA2) |
---|
866 | hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); |
---|
867 | #else |
---|
868 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1CU))); |
---|
869 | #endif /* DMA2 */ |
---|
870 | |
---|
871 | /* Update error code */ |
---|
872 | hdma->ErrorCode = HAL_DMA_ERROR_TE; |
---|
873 | |
---|
874 | /* Change the DMA state */ |
---|
875 | hdma->State = HAL_DMA_STATE_READY; |
---|
876 | |
---|
877 | /* Process Unlocked */ |
---|
878 | __HAL_UNLOCK(hdma); |
---|
879 | |
---|
880 | if (hdma->XferErrorCallback != NULL) |
---|
881 | { |
---|
882 | /* Transfer error callback */ |
---|
883 | hdma->XferErrorCallback(hdma); |
---|
884 | } |
---|
885 | } |
---|
886 | else |
---|
887 | { |
---|
888 | /* Nothing To Do */ |
---|
889 | } |
---|
890 | return; |
---|
891 | } |
---|
892 | |
---|
893 | /** |
---|
894 | * @brief Register callbacks |
---|
895 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
896 | * the configuration information for the specified DMA Channel. |
---|
897 | * @param CallbackID User Callback identifier |
---|
898 | * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. |
---|
899 | * @param pCallback Pointer to private callback function which has pointer to |
---|
900 | * a DMA_HandleTypeDef structure as parameter. |
---|
901 | * @retval HAL status |
---|
902 | */ |
---|
903 | HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)(DMA_HandleTypeDef *_hdma)) |
---|
904 | { |
---|
905 | HAL_StatusTypeDef status = HAL_OK; |
---|
906 | |
---|
907 | /* Process locked */ |
---|
908 | __HAL_LOCK(hdma); |
---|
909 | |
---|
910 | if (hdma->State == HAL_DMA_STATE_READY) |
---|
911 | { |
---|
912 | switch (CallbackID) |
---|
913 | { |
---|
914 | case HAL_DMA_XFER_CPLT_CB_ID: |
---|
915 | hdma->XferCpltCallback = pCallback; |
---|
916 | break; |
---|
917 | |
---|
918 | case HAL_DMA_XFER_HALFCPLT_CB_ID: |
---|
919 | hdma->XferHalfCpltCallback = pCallback; |
---|
920 | break; |
---|
921 | |
---|
922 | case HAL_DMA_XFER_ERROR_CB_ID: |
---|
923 | hdma->XferErrorCallback = pCallback; |
---|
924 | break; |
---|
925 | |
---|
926 | case HAL_DMA_XFER_ABORT_CB_ID: |
---|
927 | hdma->XferAbortCallback = pCallback; |
---|
928 | break; |
---|
929 | |
---|
930 | default: |
---|
931 | status = HAL_ERROR; |
---|
932 | break; |
---|
933 | } |
---|
934 | } |
---|
935 | else |
---|
936 | { |
---|
937 | status = HAL_ERROR; |
---|
938 | } |
---|
939 | |
---|
940 | /* Release Lock */ |
---|
941 | __HAL_UNLOCK(hdma); |
---|
942 | |
---|
943 | return status; |
---|
944 | } |
---|
945 | |
---|
946 | /** |
---|
947 | * @brief UnRegister callbacks |
---|
948 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
949 | * the configuration information for the specified DMA Channel. |
---|
950 | * @param CallbackID User Callback identifier |
---|
951 | * a HAL_DMA_CallbackIDTypeDef ENUM as parameter. |
---|
952 | * @retval HAL status |
---|
953 | */ |
---|
954 | HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID) |
---|
955 | { |
---|
956 | HAL_StatusTypeDef status = HAL_OK; |
---|
957 | |
---|
958 | /* Process locked */ |
---|
959 | __HAL_LOCK(hdma); |
---|
960 | |
---|
961 | if (hdma->State == HAL_DMA_STATE_READY) |
---|
962 | { |
---|
963 | switch (CallbackID) |
---|
964 | { |
---|
965 | case HAL_DMA_XFER_CPLT_CB_ID: |
---|
966 | hdma->XferCpltCallback = NULL; |
---|
967 | break; |
---|
968 | |
---|
969 | case HAL_DMA_XFER_HALFCPLT_CB_ID: |
---|
970 | hdma->XferHalfCpltCallback = NULL; |
---|
971 | break; |
---|
972 | |
---|
973 | case HAL_DMA_XFER_ERROR_CB_ID: |
---|
974 | hdma->XferErrorCallback = NULL; |
---|
975 | break; |
---|
976 | |
---|
977 | case HAL_DMA_XFER_ABORT_CB_ID: |
---|
978 | hdma->XferAbortCallback = NULL; |
---|
979 | break; |
---|
980 | |
---|
981 | case HAL_DMA_XFER_ALL_CB_ID: |
---|
982 | hdma->XferCpltCallback = NULL; |
---|
983 | hdma->XferHalfCpltCallback = NULL; |
---|
984 | hdma->XferErrorCallback = NULL; |
---|
985 | hdma->XferAbortCallback = NULL; |
---|
986 | break; |
---|
987 | |
---|
988 | default: |
---|
989 | status = HAL_ERROR; |
---|
990 | break; |
---|
991 | } |
---|
992 | } |
---|
993 | else |
---|
994 | { |
---|
995 | status = HAL_ERROR; |
---|
996 | } |
---|
997 | |
---|
998 | /* Release Lock */ |
---|
999 | __HAL_UNLOCK(hdma); |
---|
1000 | |
---|
1001 | return status; |
---|
1002 | } |
---|
1003 | |
---|
1004 | /** |
---|
1005 | * @} |
---|
1006 | */ |
---|
1007 | |
---|
1008 | |
---|
1009 | |
---|
1010 | /** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions |
---|
1011 | * @brief Peripheral State and Errors functions |
---|
1012 | * |
---|
1013 | @verbatim |
---|
1014 | =============================================================================== |
---|
1015 | ##### Peripheral State and Errors functions ##### |
---|
1016 | =============================================================================== |
---|
1017 | [..] |
---|
1018 | This subsection provides functions allowing to |
---|
1019 | (+) Check the DMA state |
---|
1020 | (+) Get error code |
---|
1021 | |
---|
1022 | @endverbatim |
---|
1023 | * @{ |
---|
1024 | */ |
---|
1025 | |
---|
1026 | /** |
---|
1027 | * @brief Return the DMA handle state. |
---|
1028 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
1029 | * the configuration information for the specified DMA Channel. |
---|
1030 | * @retval HAL state |
---|
1031 | */ |
---|
1032 | HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma) |
---|
1033 | { |
---|
1034 | /* Return DMA handle state */ |
---|
1035 | return hdma->State; |
---|
1036 | } |
---|
1037 | |
---|
1038 | /** |
---|
1039 | * @brief Return the DMA error code. |
---|
1040 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
1041 | * the configuration information for the specified DMA Channel. |
---|
1042 | * @retval DMA Error Code |
---|
1043 | */ |
---|
1044 | uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma) |
---|
1045 | { |
---|
1046 | /* Return the DMA error code */ |
---|
1047 | return hdma->ErrorCode; |
---|
1048 | } |
---|
1049 | |
---|
1050 | /** |
---|
1051 | * @} |
---|
1052 | */ |
---|
1053 | |
---|
1054 | /** |
---|
1055 | * @} |
---|
1056 | */ |
---|
1057 | |
---|
1058 | /** @addtogroup DMA_Private_Functions |
---|
1059 | * @{ |
---|
1060 | */ |
---|
1061 | |
---|
1062 | /** |
---|
1063 | * @brief Sets the DMA Transfer parameter. |
---|
1064 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
1065 | * the configuration information for the specified DMA Channel. |
---|
1066 | * @param SrcAddress The source memory Buffer address |
---|
1067 | * @param DstAddress The destination memory Buffer address |
---|
1068 | * @param DataLength The length of data to be transferred from source to destination |
---|
1069 | * @retval HAL status |
---|
1070 | */ |
---|
1071 | static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength) |
---|
1072 | { |
---|
1073 | /* Clear the DMAMUX synchro overrun flag */ |
---|
1074 | hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask; |
---|
1075 | |
---|
1076 | if (hdma->DMAmuxRequestGen != 0U) |
---|
1077 | { |
---|
1078 | /* Clear the DMAMUX request generator overrun flag */ |
---|
1079 | hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask; |
---|
1080 | } |
---|
1081 | |
---|
1082 | /* Clear all flags */ |
---|
1083 | #if defined(DMA2) |
---|
1084 | hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex & 0x1CU)); |
---|
1085 | #else |
---|
1086 | __HAL_DMA_CLEAR_FLAG(hdma, (DMA_FLAG_GI1 << (hdma->ChannelIndex & 0x1CU))); |
---|
1087 | #endif /* DMA2 */ |
---|
1088 | |
---|
1089 | /* Configure DMA Channel data length */ |
---|
1090 | hdma->Instance->CNDTR = DataLength; |
---|
1091 | |
---|
1092 | /* Memory to Peripheral */ |
---|
1093 | if ((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH) |
---|
1094 | { |
---|
1095 | /* Configure DMA Channel destination address */ |
---|
1096 | hdma->Instance->CPAR = DstAddress; |
---|
1097 | |
---|
1098 | /* Configure DMA Channel source address */ |
---|
1099 | hdma->Instance->CMAR = SrcAddress; |
---|
1100 | } |
---|
1101 | /* Peripheral to Memory */ |
---|
1102 | else |
---|
1103 | { |
---|
1104 | /* Configure DMA Channel source address */ |
---|
1105 | hdma->Instance->CPAR = SrcAddress; |
---|
1106 | |
---|
1107 | /* Configure DMA Channel destination address */ |
---|
1108 | hdma->Instance->CMAR = DstAddress; |
---|
1109 | } |
---|
1110 | } |
---|
1111 | |
---|
1112 | /** |
---|
1113 | * @brief Updates the DMA handle with the DMAMUX channel and status mask depending on channel number |
---|
1114 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
1115 | * the configuration information for the specified DMA Channel. |
---|
1116 | * @retval None |
---|
1117 | */ |
---|
1118 | static void DMA_CalcDMAMUXChannelBaseAndMask(DMA_HandleTypeDef *hdma) |
---|
1119 | { |
---|
1120 | uint32_t channel_number; |
---|
1121 | |
---|
1122 | #if defined(DMA2) |
---|
1123 | /* check if instance is not outside the DMA channel range */ |
---|
1124 | if ((uint32_t)hdma->Instance < (uint32_t)DMA2_Channel1) |
---|
1125 | { |
---|
1126 | /* DMA1 */ |
---|
1127 | /* Associate a DMA Channel to a DMAMUX channel */ |
---|
1128 | hdma->DMAmuxChannel = (DMAMUX1_Channel0 + (hdma->ChannelIndex >> 2U)); |
---|
1129 | |
---|
1130 | /* Prepare channel_number used for DMAmuxChannelStatusMask computation */ |
---|
1131 | channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U; |
---|
1132 | } |
---|
1133 | else |
---|
1134 | { |
---|
1135 | /* DMA2 */ |
---|
1136 | /* Associate a DMA Channel to a DMAMUX channel */ |
---|
1137 | hdma->DMAmuxChannel = (DMAMUX1_Channel7 + (hdma->ChannelIndex >> 2U)); |
---|
1138 | |
---|
1139 | /* Prepare channel_number used for DMAmuxChannelStatusMask computation */ |
---|
1140 | channel_number = (((((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U) + 7U); |
---|
1141 | } |
---|
1142 | #else |
---|
1143 | /* Associate a DMA Channel to a DMAMUX channel */ |
---|
1144 | hdma->DMAmuxChannel = (DMAMUX_Channel_TypeDef *)(uint32_t)((uint32_t)DMAMUX1_Channel0 + ((hdma->ChannelIndex >> 2U) * ((uint32_t)DMAMUX1_Channel1 - (uint32_t)DMAMUX1_Channel0))); |
---|
1145 | |
---|
1146 | /* Prepare channel_number used for DMAmuxChannelStatusMask computation */ |
---|
1147 | channel_number = (((uint32_t)hdma->Instance & 0xFFU) - 8U) / 20U; |
---|
1148 | #endif /* DMA2 */ |
---|
1149 | |
---|
1150 | /* Initialize the field DMAmuxChannelStatus to DMAMUX1_ChannelStatus base */ |
---|
1151 | hdma->DMAmuxChannelStatus = DMAMUX1_ChannelStatus; |
---|
1152 | |
---|
1153 | /* Initialize the field DMAmuxChannelStatusMask with the corresponding index of the DMAMUX channel selected for the current ChannelIndex */ |
---|
1154 | hdma->DMAmuxChannelStatusMask = 1UL << (channel_number & 0x1FU); |
---|
1155 | } |
---|
1156 | |
---|
1157 | /** |
---|
1158 | * @brief Updates the DMA handle with the DMAMUX request generator params |
---|
1159 | * @param hdma Pointer to a DMA_HandleTypeDef structure that contains |
---|
1160 | * the configuration information for the specified DMA Channel. |
---|
1161 | * @retval None |
---|
1162 | */ |
---|
1163 | |
---|
1164 | static void DMA_CalcDMAMUXRequestGenBaseAndMask(DMA_HandleTypeDef *hdma) |
---|
1165 | { |
---|
1166 | uint32_t request = hdma->Init.Request & DMAMUX_CxCR_DMAREQ_ID; |
---|
1167 | |
---|
1168 | /* DMA Channels are connected to DMAMUX1 request generator blocks*/ |
---|
1169 | hdma->DMAmuxRequestGen = (DMAMUX_RequestGen_TypeDef *)((uint32_t)(((uint32_t)DMAMUX1_RequestGenerator0) + ((request - 1U) * 4U))); |
---|
1170 | |
---|
1171 | hdma->DMAmuxRequestGenStatus = DMAMUX1_RequestGenStatus; |
---|
1172 | |
---|
1173 | /* here "Request" is either DMA_REQUEST_GENERATOR0 to DMA_REQUEST_GENERATOR3, i.e. <= 4*/ |
---|
1174 | hdma->DMAmuxRequestGenStatusMask = 1UL << ((request - 1U) & 0x3U); |
---|
1175 | } |
---|
1176 | |
---|
1177 | /** |
---|
1178 | * @} |
---|
1179 | */ |
---|
1180 | |
---|
1181 | /** |
---|
1182 | * @} |
---|
1183 | */ |
---|
1184 | |
---|
1185 | #endif /* HAL_DMA_MODULE_ENABLED */ |
---|
1186 | /** |
---|
1187 | * @} |
---|
1188 | */ |
---|
1189 | |
---|
1190 | /** |
---|
1191 | * @} |
---|
1192 | */ |
---|
1193 | |
---|