1 /**
2   ******************************************************************************
3   * @file    stm32h7xx_hal_dma_ex.c
4   * @author  MCD Application Team
5   * @brief   DMA Extension HAL module driver
6   *          This file provides firmware functions to manage the following
7   *          functionalities of the DMA Extension peripheral:
8   *           + Extended features functions
9   *
10   @verbatim
11   ==============================================================================
12                         ##### How to use this driver #####
13   ==============================================================================
14   [..]
15   The DMA Extension HAL driver can be used as follows:
16    (+) Start a multi buffer transfer using the HAL_DMA_MultiBufferStart() function
17        for polling mode or HAL_DMA_MultiBufferStart_IT() for interrupt mode.
18 
19    (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
20    (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
21        Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
22        to respectively enable/disable the request generator.
23 
24    (+) To handle the DMAMUX Interrupts, the function  HAL_DMAEx_MUX_IRQHandler should be called from
25        the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler or DMAMUX2_OVR_IRQHandler .
26        As only one interrupt line is available for all DMAMUX channels and request generators , HAL_DMA_MUX_IRQHandler should be
27        called with, as parameter, the appropriate DMA handle as many as used DMAs in the user project
28       (exception done if a given DMA is not using the DMAMUX SYNC block neither a request generator)
29 
30      -@-  In Memory-to-Memory transfer mode, Multi (Double) Buffer mode is not allowed.
31      -@-  When Multi (Double) Buffer mode is enabled, the transfer is circular by default.
32      -@-  In Multi (Double) buffer mode, it is possible to update the base address for
33           the AHB memory port on the fly (DMA_SxM0AR or DMA_SxM1AR) when the stream is enabled.
34      -@-  Multi (Double) buffer mode is possible with DMA and BDMA instances.
35 
36   @endverbatim
37   ******************************************************************************
38   * @attention
39   *
40   * Copyright (c) 2017 STMicroelectronics.
41   * All rights reserved.
42   *
43   * This software is licensed under terms that can be found in the LICENSE file
44   * in the root directory of this software component.
45   * If no LICENSE file comes with this software, it is provided AS-IS.
46   *
47   ******************************************************************************
48   */
49 
50 /* Includes ------------------------------------------------------------------*/
51 #include "stm32h7xx_hal.h"
52 
53 /** @addtogroup STM32H7xx_HAL_Driver
54   * @{
55   */
56 
57 /** @defgroup DMAEx DMAEx
58   * @brief DMA Extended HAL module driver
59   * @{
60   */
61 
62 #ifdef HAL_DMA_MODULE_ENABLED
63 
64 /* Private types -------------------------------------------------------------*/
65 /* Private variables ---------------------------------------------------------*/
66 /* Private Constants ---------------------------------------------------------*/
67 /* Private macros ------------------------------------------------------------*/
68 /* Private functions ---------------------------------------------------------*/
69 /** @addtogroup DMAEx_Private_Functions
70   * @{
71   */
72 
73 static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
74 
75 /**
76   * @}
77   */
78 
79 /* Exported functions ---------------------------------------------------------*/
80 
81 /** @addtogroup DMAEx_Exported_Functions
82   * @{
83   */
84 
85 
86 /** @addtogroup DMAEx_Exported_Functions_Group1
87   *
88 @verbatim
89  ===============================================================================
90                 #####  Extended features functions  #####
91  ===============================================================================
92     [..]  This section provides functions allowing to:
93       (+) Configure the source, destination address and data length and
94           Start MultiBuffer DMA transfer
95       (+) Configure the source, destination address and data length and
96           Start MultiBuffer DMA transfer with interrupt
97       (+) Change on the fly the memory0 or memory1 address.
98       (+) Configure the DMA_MUX Synchronization Block using HAL_DMAEx_ConfigMuxSync function.
99       (+) Configure the DMA_MUX Request Generator Block using HAL_DMAEx_ConfigMuxRequestGenerator function.
100       (+) Functions HAL_DMAEx_EnableMuxRequestGenerator and HAL_DMAEx_DisableMuxRequestGenerator can then be used
101           to respectively enable/disable the request generator.
102       (+) Handle DMAMUX interrupts using HAL_DMAEx_MUX_IRQHandler : should be called from
103           the DMAMUX IRQ handler i.e DMAMUX1_OVR_IRQHandler or DMAMUX2_OVR_IRQHandler
104 
105 @endverbatim
106   * @{
107   */
108 
109 
110 /**
111   * @brief  Starts the multi_buffer DMA Transfer.
112   * @param  hdma      : pointer to a DMA_HandleTypeDef structure that contains
113   *                     the configuration information for the specified DMA Stream.
114   * @param  SrcAddress: The source memory Buffer address
115   * @param  DstAddress: The destination memory Buffer address
116   * @param  SecondMemAddress: The second memory Buffer address in case of multi buffer Transfer
117   * @param  DataLength: The length of data to be transferred from source to destination
118   * @retval HAL status
119   */
HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SecondMemAddress,uint32_t DataLength)120 HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength)
121 {
122   HAL_StatusTypeDef status = HAL_OK;
123   __IO uint32_t *ifcRegister_Base; /* DMA Stream Interrupt Clear register */
124 
125   /* Check the parameters */
126   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
127   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
128 
129   /* Memory-to-memory transfer not supported in double buffering mode */
130   if (hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
131   {
132     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
133     status = HAL_ERROR;
134   }
135   else
136   {
137     /* Process Locked */
138     __HAL_LOCK(hdma);
139 
140     if(HAL_DMA_STATE_READY == hdma->State)
141     {
142       /* Change DMA peripheral state */
143       hdma->State = HAL_DMA_STATE_BUSY;
144 
145       /* Initialize the error code */
146       hdma->ErrorCode = HAL_DMA_ERROR_NONE;
147 
148       if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
149       {
150         /* Enable the Double buffer mode */
151         ((DMA_Stream_TypeDef   *)hdma->Instance)->CR |= DMA_SxCR_DBM;
152 
153         /* Configure DMA Stream destination address */
154         ((DMA_Stream_TypeDef   *)hdma->Instance)->M1AR = SecondMemAddress;
155 
156         /* Calculate the interrupt clear flag register (IFCR) base address  */
157         ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 8U));
158 
159         /* Clear all flags */
160         *ifcRegister_Base = 0x3FUL << (hdma->StreamIndex & 0x1FU);
161       }
162       else /* BDMA instance(s) */
163       {
164         /* Enable the Double buffer mode */
165         ((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR |= (BDMA_CCR_DBM | BDMA_CCR_CIRC);
166 
167         /* Configure DMA Stream destination address */
168         ((BDMA_Channel_TypeDef   *)hdma->Instance)->CM1AR = SecondMemAddress;
169 
170         /* Calculate the interrupt clear flag register (IFCR) base address  */
171         ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 4U));
172 
173         /* Clear all flags */
174         *ifcRegister_Base = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
175       }
176 
177       if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
178       {
179         /* Configure the source, destination address and the data length */
180         DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength);
181 
182         /* Clear the DMAMUX synchro overrun flag */
183         hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
184 
185         if(hdma->DMAmuxRequestGen != 0U)
186         {
187           /* Clear the DMAMUX request generator overrun flag */
188           hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
189         }
190       }
191 
192       /* Enable the peripheral */
193       __HAL_DMA_ENABLE(hdma);
194     }
195     else
196     {
197       /* Set the error code to busy */
198       hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
199 
200       /* Return error status */
201       status = HAL_ERROR;
202     }
203   }
204   return status;
205 }
206 
207 /**
208   * @brief  Starts the multi_buffer DMA Transfer with interrupt enabled.
209   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
210   *                     the configuration information for the specified DMA Stream.
211   * @param  SrcAddress: The source memory Buffer address
212   * @param  DstAddress: The destination memory Buffer address
213   * @param  SecondMemAddress: The second memory Buffer address in case of multi buffer Transfer
214   * @param  DataLength: The length of data to be transferred from source to destination
215   * @retval HAL status
216   */
HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t SecondMemAddress,uint32_t DataLength)217 HAL_StatusTypeDef HAL_DMAEx_MultiBufferStart_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t SecondMemAddress, uint32_t DataLength)
218 {
219   HAL_StatusTypeDef status = HAL_OK;
220   __IO uint32_t *ifcRegister_Base; /* DMA Stream Interrupt Clear register */
221 
222   /* Check the parameters */
223   assert_param(IS_DMA_BUFFER_SIZE(DataLength));
224   assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
225 
226   /* Memory-to-memory transfer not supported in double buffering mode */
227   if(hdma->Init.Direction == DMA_MEMORY_TO_MEMORY)
228   {
229     hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
230     return HAL_ERROR;
231   }
232 
233   /* Process locked */
234   __HAL_LOCK(hdma);
235 
236   if(HAL_DMA_STATE_READY == hdma->State)
237   {
238     /* Change DMA peripheral state */
239     hdma->State = HAL_DMA_STATE_BUSY;
240 
241     /* Initialize the error code */
242     hdma->ErrorCode = HAL_DMA_ERROR_NONE;
243 
244     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
245     {
246       /* Enable the Double buffer mode */
247       ((DMA_Stream_TypeDef   *)hdma->Instance)->CR |= DMA_SxCR_DBM;
248 
249       /* Configure DMA Stream destination address */
250       ((DMA_Stream_TypeDef   *)hdma->Instance)->M1AR = SecondMemAddress;
251 
252       /* Calculate the interrupt clear flag register (IFCR) base address  */
253       ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 8U));
254 
255       /* Clear all flags */
256       *ifcRegister_Base = 0x3FUL << (hdma->StreamIndex & 0x1FU);
257     }
258     else /* BDMA instance(s) */
259     {
260       /* Enable the Double buffer mode */
261       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR |= (BDMA_CCR_DBM | BDMA_CCR_CIRC);
262 
263       /* Configure DMA Stream destination address */
264       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CM1AR = SecondMemAddress;
265 
266       /* Calculate the interrupt clear flag register (IFCR) base address  */
267       ifcRegister_Base = (uint32_t *)((uint32_t)(hdma->StreamBaseAddress + 4U));
268 
269       /* Clear all flags */
270       *ifcRegister_Base = (BDMA_ISR_GIF0) << (hdma->StreamIndex & 0x1FU);
271     }
272 
273     /* Configure the source, destination address and the data length */
274     DMA_MultiBufferSetConfig(hdma, SrcAddress, DstAddress, DataLength);
275 
276     if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
277     {
278       /* Clear the DMAMUX synchro overrun flag */
279       hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
280 
281       if(hdma->DMAmuxRequestGen != 0U)
282       {
283         /* Clear the DMAMUX request generator overrun flag */
284         hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
285       }
286     }
287 
288     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
289     {
290       /* Enable Common interrupts*/
291       MODIFY_REG(((DMA_Stream_TypeDef   *)hdma->Instance)->CR, (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME | DMA_IT_HT), (DMA_IT_TC | DMA_IT_TE | DMA_IT_DME));
292       ((DMA_Stream_TypeDef   *)hdma->Instance)->FCR |= DMA_IT_FE;
293 
294       if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
295       {
296         /*Enable Half Transfer IT if corresponding Callback is set*/
297         ((DMA_Stream_TypeDef   *)hdma->Instance)->CR  |= DMA_IT_HT;
298       }
299     }
300     else /* BDMA instance(s) */
301     {
302       /* Enable Common interrupts*/
303       MODIFY_REG(((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR, (BDMA_CCR_TCIE | BDMA_CCR_HTIE | BDMA_CCR_TEIE), (BDMA_CCR_TCIE | BDMA_CCR_TEIE));
304 
305       if((hdma->XferHalfCpltCallback != NULL) || (hdma->XferM1HalfCpltCallback != NULL))
306       {
307         /*Enable Half Transfer IT if corresponding Callback is set*/
308         ((BDMA_Channel_TypeDef   *)hdma->Instance)->CCR  |= BDMA_CCR_HTIE;
309       }
310     }
311 
312     if(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance) != 0U) /* No DMAMUX available for BDMA1 */
313     {
314       /* Check if DMAMUX Synchronization is enabled*/
315       if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
316       {
317         /* Enable DMAMUX sync overrun IT*/
318         hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
319       }
320 
321       if(hdma->DMAmuxRequestGen != 0U)
322       {
323         /* if using DMAMUX request generator, enable the DMAMUX request generator overrun IT*/
324         /* enable the request gen overrun IT*/
325         hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
326       }
327     }
328 
329     /* Enable the peripheral */
330     __HAL_DMA_ENABLE(hdma);
331   }
332   else
333   {
334     /* Set the error code to busy */
335     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
336 
337     /* Return error status */
338     status = HAL_ERROR;
339   }
340   return status;
341 }
342 
343 /**
344   * @brief  Change the memory0 or memory1 address on the fly.
345   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
346   *                     the configuration information for the specified DMA Stream.
347   * @param  Address:    The new address
348   * @param  memory:     the memory to be changed, This parameter can be one of
349   *                     the following values:
350   *                      MEMORY0 /
351   *                      MEMORY1
352   * @note   The MEMORY0 address can be changed only when the current transfer use
353   *         MEMORY1 and the MEMORY1 address can be changed only when the current
354   *         transfer use MEMORY0.
355   * @retval HAL status
356   */
HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef * hdma,uint32_t Address,HAL_DMA_MemoryTypeDef memory)357 HAL_StatusTypeDef HAL_DMAEx_ChangeMemory(DMA_HandleTypeDef *hdma, uint32_t Address, HAL_DMA_MemoryTypeDef memory)
358 {
359   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
360   {
361     if(memory == MEMORY0)
362     {
363       /* change the memory0 address */
364       ((DMA_Stream_TypeDef   *)hdma->Instance)->M0AR = Address;
365     }
366     else
367     {
368       /* change the memory1 address */
369       ((DMA_Stream_TypeDef   *)hdma->Instance)->M1AR = Address;
370     }
371   }
372   else /* BDMA instance(s) */
373   {
374     if(memory == MEMORY0)
375     {
376       /* change the memory0 address */
377       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CM0AR = Address;
378     }
379     else
380     {
381       /* change the memory1 address */
382       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CM1AR = Address;
383     }
384   }
385 
386   return HAL_OK;
387 }
388 
389 /**
390   * @brief  Configure the DMAMUX synchronization parameters for a given DMA stream (instance).
391   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
392   *                     the configuration information for the specified DMA Stream.
393   * @param  pSyncConfig : pointer to HAL_DMA_MuxSyncConfigTypeDef : contains the DMAMUX synchronization parameters
394   * @retval HAL status
395   */
HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef * hdma,HAL_DMA_MuxSyncConfigTypeDef * pSyncConfig)396 HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig)
397 {
398   uint32_t syncSignalID = 0;
399   uint32_t syncPolarity = 0;
400 
401   /* Check the parameters */
402   assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
403   assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable));
404   assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable));
405   assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber));
406 
407   if(pSyncConfig->SyncEnable == ENABLE)
408   {
409     assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig->SyncPolarity));
410 
411     if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
412     {
413       assert_param(IS_DMA_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
414     }
415     else
416     {
417       assert_param(IS_BDMA_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
418     }
419     syncSignalID = pSyncConfig->SyncSignalID;
420     syncPolarity = pSyncConfig->SyncPolarity;
421   }
422 
423   /*Check if the DMA state is ready */
424   if(hdma->State == HAL_DMA_STATE_READY)
425   {
426     /* Process Locked */
427     __HAL_LOCK(hdma);
428 
429     /* Disable the synchronization and event generation before applying a new config */
430     CLEAR_BIT(hdma->DMAmuxChannel->CCR,(DMAMUX_CxCR_SE | DMAMUX_CxCR_EGE));
431 
432     /* Set the new synchronization parameters (and keep the request ID filled during the Init)*/
433     MODIFY_REG( hdma->DMAmuxChannel->CCR, \
434                (~DMAMUX_CxCR_DMAREQ_ID) , \
435                (syncSignalID << DMAMUX_CxCR_SYNC_ID_Pos)       | \
436                ((pSyncConfig->RequestNumber - 1U) << DMAMUX_CxCR_NBREQ_Pos) | \
437                syncPolarity | ((uint32_t)pSyncConfig->SyncEnable << DMAMUX_CxCR_SE_Pos)    | \
438                ((uint32_t)pSyncConfig->EventEnable << DMAMUX_CxCR_EGE_Pos));
439 
440       /* Process Locked */
441     __HAL_UNLOCK(hdma);
442 
443     return HAL_OK;
444   }
445   else
446   {
447     /* Set the error code to busy */
448     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
449 
450     /* Return error status */
451     return HAL_ERROR;
452   }
453 }
454 
455 /**
456   * @brief  Configure the DMAMUX request generator block used by the given DMA stream (instance).
457   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
458   *                     the configuration information for the specified DMA Stream.
459   * @param  pRequestGeneratorConfig : pointer to HAL_DMA_MuxRequestGeneratorConfigTypeDef :
460   *         contains the request generator parameters.
461   *
462   * @retval HAL status
463   */
HAL_DMAEx_ConfigMuxRequestGenerator(DMA_HandleTypeDef * hdma,HAL_DMA_MuxRequestGeneratorConfigTypeDef * pRequestGeneratorConfig)464 HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig)
465 {
466   HAL_StatusTypeDef status;
467   HAL_DMA_StateTypeDef temp_state = hdma->State;
468 
469   /* Check the parameters */
470   assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
471 
472   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
473   {
474     assert_param(IS_DMA_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
475   }
476   else
477   {
478     assert_param(IS_BDMA_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
479   }
480 
481 
482   assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity));
483   assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber));
484 
485   /* check if the DMA state is ready
486      and DMA is using a DMAMUX request generator block
487   */
488   if(hdma->DMAmuxRequestGen == 0U)
489   {
490     /* Set the error code to busy */
491     hdma->ErrorCode = HAL_DMA_ERROR_PARAM;
492 
493     /* error status */
494     status = HAL_ERROR;
495   }
496   else if(((hdma->DMAmuxRequestGen->RGCR & DMAMUX_RGxCR_GE) == 0U) && (temp_state == HAL_DMA_STATE_READY))
497   {
498     /* RequestGenerator must be disable prior to the configuration i.e GE bit is 0 */
499 
500     /* Process Locked */
501     __HAL_LOCK(hdma);
502 
503     /* Set the request generator new parameters */
504     hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID | \
505                                   ((pRequestGeneratorConfig->RequestNumber - 1U) << DMAMUX_RGxCR_GNBREQ_Pos)| \
506                                   pRequestGeneratorConfig->Polarity;
507     /* Process Locked */
508     __HAL_UNLOCK(hdma);
509 
510     return HAL_OK;
511   }
512   else
513   {
514     /* Set the error code to busy */
515     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;
516 
517     /* error status */
518     status = HAL_ERROR;
519   }
520 
521   return status;
522 }
523 
524 /**
525   * @brief  Enable the DMAMUX request generator block used by the given DMA stream (instance).
526   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
527   *                     the configuration information for the specified DMA Stream.
528   * @retval HAL status
529   */
HAL_DMAEx_EnableMuxRequestGenerator(DMA_HandleTypeDef * hdma)530 HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
531 {
532   /* Check the parameters */
533   assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
534 
535   /* check if the DMA state is ready
536      and DMA is using a DMAMUX request generator block */
537   if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
538   {
539     /* Enable the request generator*/
540     hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE;
541 
542    return HAL_OK;
543  }
544  else
545  {
546    return HAL_ERROR;
547  }
548 }
549 
550 /**
551   * @brief  Disable the DMAMUX request generator block used by the given DMA stream (instance).
552   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
553   *                     the configuration information for the specified DMA Stream.
554   * @retval HAL status
555   */
HAL_DMAEx_DisableMuxRequestGenerator(DMA_HandleTypeDef * hdma)556 HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
557 {
558   /* Check the parameters */
559   assert_param(IS_DMA_DMAMUX_ALL_INSTANCE(hdma->Instance));
560 
561   /* check if the DMA state is ready
562      and DMA is using a DMAMUX request generator block */
563   if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
564   {
565     /* Disable the request generator*/
566     hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE;
567 
568    return HAL_OK;
569  }
570  else
571  {
572    return HAL_ERROR;
573  }
574 }
575 
576 /**
577   * @brief  Handles DMAMUX interrupt request.
578   * @param  hdma: pointer to a DMA_HandleTypeDef structure that contains
579   *               the configuration information for the specified DMA Stream.
580   * @retval None
581   */
HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef * hdma)582 void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma)
583 {
584   /* Check for DMAMUX Synchronization overrun */
585   if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
586   {
587     /* Disable the synchro overrun interrupt */
588     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;
589 
590     /* Clear the DMAMUX synchro overrun flag */
591     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;
592 
593     /* Update error code */
594     hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;
595 
596     if(hdma->XferErrorCallback != NULL)
597     {
598       /* Transfer error callback */
599       hdma->XferErrorCallback(hdma);
600     }
601   }
602 
603   if(hdma->DMAmuxRequestGen != 0)
604   {
605    /* if using a DMAMUX request generator block Check for DMAMUX request generator overrun */
606     if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
607     {
608       /* Disable the request gen overrun interrupt */
609       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;
610 
611       /* Clear the DMAMUX request generator overrun flag */
612       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;
613 
614       /* Update error code */
615       hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;
616 
617       if(hdma->XferErrorCallback != NULL)
618       {
619         /* Transfer error callback */
620         hdma->XferErrorCallback(hdma);
621       }
622     }
623   }
624 }
625 
626 
627 /**
628   * @}
629   */
630 
631 /**
632   * @}
633   */
634 
635 /** @addtogroup DMAEx_Private_Functions
636   * @{
637   */
638 
639 /**
640   * @brief  Set the DMA Transfer parameter.
641   * @param  hdma:       pointer to a DMA_HandleTypeDef structure that contains
642   *                     the configuration information for the specified DMA Stream.
643   * @param  SrcAddress: The source memory Buffer address
644   * @param  DstAddress: The destination memory Buffer address
645   * @param  DataLength: The length of data to be transferred from source to destination
646   * @retval HAL status
647   */
DMA_MultiBufferSetConfig(DMA_HandleTypeDef * hdma,uint32_t SrcAddress,uint32_t DstAddress,uint32_t DataLength)648 static void DMA_MultiBufferSetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
649 {
650   if(IS_DMA_STREAM_INSTANCE(hdma->Instance) != 0U) /* DMA1 or DMA2 instance */
651   {
652     /* Configure DMA Stream data length */
653     ((DMA_Stream_TypeDef   *)hdma->Instance)->NDTR = DataLength;
654 
655     /* Peripheral to Memory */
656     if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
657     {
658       /* Configure DMA Stream destination address */
659       ((DMA_Stream_TypeDef   *)hdma->Instance)->PAR = DstAddress;
660 
661       /* Configure DMA Stream source address */
662       ((DMA_Stream_TypeDef   *)hdma->Instance)->M0AR = SrcAddress;
663     }
664     /* Memory to Peripheral */
665     else
666     {
667       /* Configure DMA Stream source address */
668       ((DMA_Stream_TypeDef   *)hdma->Instance)->PAR = SrcAddress;
669 
670       /* Configure DMA Stream destination address */
671       ((DMA_Stream_TypeDef   *)hdma->Instance)->M0AR = DstAddress;
672     }
673   }
674   else /* BDMA instance(s) */
675   {
676     /* Configure DMA Stream data length */
677     ((BDMA_Channel_TypeDef   *)hdma->Instance)->CNDTR = DataLength;
678 
679     /* Peripheral to Memory */
680     if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
681     {
682       /* Configure DMA Stream destination address */
683       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CPAR = DstAddress;
684 
685       /* Configure DMA Stream source address */
686       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CM0AR = SrcAddress;
687     }
688     /* Memory to Peripheral */
689     else
690     {
691       /* Configure DMA Stream source address */
692       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CPAR = SrcAddress;
693 
694       /* Configure DMA Stream destination address */
695       ((BDMA_Channel_TypeDef   *)hdma->Instance)->CM0AR = DstAddress;
696     }
697   }
698 }
699 
700 /**
701   * @}
702   */
703 
704 #endif /* HAL_DMA_MODULE_ENABLED */
705 /**
706   * @}
707   */
708 
709 /**
710   * @}
711   */
712 
713