你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7的DMAMUX基础知识(重要)

[复制链接]
STMCU小助手 发布时间:2021-12-24 19:00
39.1 初学者重要提示
  DMAMUX其实就是DMA控制器前一级的多路选择器,有了这个选择器就不用再像F1,F4系列那样每个通道(数据流)要固定选择指定的外设,有了多路选择器就可以任意选择,外设使用DMA方式时无需再选择指定的DMA通道(数据流),任意通道(数据流)都可以。

39.2 DMAMUX基础知识
当前STM32H7有两路DMAMUX,分别是DMAMUX1和DMAMUX2,其中DMAMUX1负责DMA1和DMA2,而DMAMUX2负责BDMA。

39.2.1 DMAMUX和DMA的连接关系
认识一个外设,最好的方式就是看它的框图,方便我们快速的了解DMAMUX的基本功能,然后再看手册了解细节。首先来看下DMAMUX与DMA之间的连接方式,从整体上把握下,可以更好的理解DMAMUX的作用。

DMAMUX1有16个输出通道,前8个通道分别连接DMA1 Stream0到Stream7,而后8个通道分别连接DMA2 Stream0到Stream7。上面DMAMUX1的前8路接到DMA1的8路数据流通道Stream0到Stream7中。

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


DMAMUX2有8个输出通道,连接BDMA的8个输入通道:

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


39.2.2 DMAMUX的硬件框图
这个框图对于理解DMAMUX至关重要。

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


通过这个框图,我们可以得到如下信息:

  DMA requests from peripherals接口
对于DMAMUX1来说,这个接口支持107个DMA外设请求,供DMA1和DMA2的数据流使用:

  1. #define DMA_REQUEST_ADC1             9U  /*!< DMAMUX1 ADC1 request */
  2. #define DMA_REQUEST_ADC2             10U /*!< DMAMUX1 ADC2 request */

  3. #define DMA_REQUEST_TIM1_CH1         11U  /*!< DMAMUX1 TIM1 CH1 request  */
  4. #define DMA_REQUEST_TIM1_CH2         12U  /*!< DMAMUX1 TIM1 CH2 request  */
  5. #define DMA_REQUEST_TIM1_CH3         13U  /*!< DMAMUX1 TIM1 CH3 request  */
  6. #define DMA_REQUEST_TIM1_CH4         14U  /*!< DMAMUX1 TIM1 CH4 request  */
  7. #define DMA_REQUEST_TIM1_UP          15U  /*!< DMAMUX1 TIM1 UP request   */
  8. #define DMA_REQUEST_TIM1_TRIG        16U  /*!< DMAMUX1 TIM1 TRIG request */
  9. #define DMA_REQUEST_TIM1_COM         17U  /*!< DMAMUX1 TIM1 COM request  */

  10. 中间部分省略未写

  11. #define DMA_REQUEST_TIM16_CH1       109U  /*!< DMAMUX1 TIM16 CH1 request  */
  12. #define DMA_REQUEST_TIM16_UP        110U  /*!< DMAMUX1 TIM16 UP request   */

  13. #define DMA_REQUEST_TIM17_CH1       111U  /*!< DMAMUX1 TIM17 CH1 request  */
  14. #define DMA_REQUEST_TIM17_UP        112U  /*!< DMAMUX1 TIM17 UP request   */

  15. #define DMA_REQUEST_SAI3_A          113U  /*!< DMAMUX1 SAI3 A request  */
  16. #define DMA_REQUEST_SAI3_B          114U  /*!< DMAMUX1 SAI3 B request  */

  17. #define DMA_REQUEST_ADC3            115U  /*!< DMAMUX1 ADC3  request  */
复制代码

对于DMAMUX2来说,这个接口支持9个DMA外设请求,供BDMA通道使用:

  1. #define BDMA_REQUEST_LPUART1_RX       9U  /*!< DMAMUX2 LP_UART1_RX request */
  2. #define BDMA_REQUEST_LPUART1_TX      10U  /*!< DMAMUX2 LP_UART1_TX request */
  3. #define BDMA_REQUEST_SPI6_RX         11U  /*!< DMAMUX2 SPI6 RX request     */
  4. #define BDMA_REQUEST_SPI6_TX         12U  /*!< DMAMUX2 SPI6 TX request     */
  5. #define BDMA_REQUEST_I2C4_RX         13U  /*!< DMAMUX2 I2C4 RX request     */
  6. #define BDMA_REQUEST_I2C4_TX         14U  /*!< DMAMUX2 I2C4 TX request     */
  7. #define BDMA_REQUEST_SAI4_A          15U  /*!< DMAMUX2 SAI4 A request      */
  8. #define BDMA_REQUEST_SAI4_B          16U  /*!< DMAMUX2 SAI4 B request      */
  9. #define BDMA_REQUEST_ADC3            17U  /*!< DMAMUX2 ADC3 request        */
复制代码

这里特别注意一点,DMA1,DMA2和BDMA都支持存储区到存储区的传输。

  Trigger inputs接口

除了正常的DMA请求可以输入到DMAMUX里面,通过设置触发条件也可以生成DMA触发请求。这样就比较灵活了,不支持DMA的外设也可以通过Trigger inputs接口触发DMA传输,比如我们可以将RAM中的数据通过定时器触发直接输出到GPIO,这样就可以产生各种脉冲效果。

DMAMUX1支持8种触发输入,供DMA1和DMA2使用:

  1. #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH0_EVT   0U  
  2. #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH1_EVT   1U   
  3. #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH2_EVT   2U   
  4. #define HAL_DMAMUX1_REQ_GEN_LPTIM1_OUT        3U  
  5. #define HAL_DMAMUX1_REQ_GEN_LPTIM2_OUT        4U   
  6. #define HAL_DMAMUX1_REQ_GEN_LPTIM3_OUT        5U   
  7. #define HAL_DMAMUX1_REQ_GEN_EXTI0             6U  
  8. #define HAL_DMAMUX1_REQ_GEN_TIM12_TRGO        7U  
复制代码

DMAMUX2支持的30种触发输入,供BDMA使用:

  1. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH0_EVT   0U   
  2. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH1_EVT   1U   
  3. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH2_EVT   2U  
  4. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH3_EVT   3U   
  5. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH4_EVT   4U   
  6. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH5_EVT   5U  
  7. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH6_EVT   6U   
  8. #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_WKUP   7U  
  9. #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_WKUP   8U   
  10. #define HAL_DMAMUX2_REQ_GEN_LPTIM2_WKUP       9U   
  11. #define HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT       10U   
  12. #define HAL_DMAMUX2_REQ_GEN_LPTIM3_WKUP      11U  
  13. #define HAL_DMAMUX2_REQ_GEN_LPTIM3_OUT       12U   
  14. #define HAL_DMAMUX2_REQ_GEN_LPTIM4_WKUP      13U   
  15. #define HAL_DMAMUX2_REQ_GEN_LPTIM5_WKUP      14U   
  16. #define HAL_DMAMUX2_REQ_GEN_I2C4_WKUP        15U   
  17. #define HAL_DMAMUX2_REQ_GEN_SPI6_WKUP        16U   
  18. #define HAL_DMAMUX2_REQ_GEN_COMP1_OUT        17U   
  19. #define HAL_DMAMUX2_REQ_GEN_COMP2_OUT        18U   
  20. #define HAL_DMAMUX2_REQ_GEN_RTC_WKUP         19U   
  21. #define HAL_DMAMUX2_REQ_GEN_EXTI0            20U
  22. #define HAL_DMAMUX2_REQ_GEN_EXTI2            21U   
  23. #define HAL_DMAMUX2_REQ_GEN_I2C4_IT_EVT      22U   
  24. #define HAL_DMAMUX2_REQ_GEN_SPI6_IT          23U   
  25. #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_IT    24U   
  26. #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_IT    25U   
  27. #define HAL_DMAMUX2_REQ_GEN_ADC3_IT          26U   
  28. #define HAL_DMAMUX2_REQ_GEN_ADC3_AWD1_OUT    27U   
  29. #define HAL_DMAMUX2_REQ_GEN_BDMA_CH0_IT      28U   
  30. #define HAL_DMAMUX2_REQ_GEN_BDMA_CH1_IT      29U   
复制代码


  Interrupt接口


用于触发中断。                                                                                                                             

  Synchronization inputs接口

同步输入接口可以用来控制DMAMUX的输入端的DMA外设请求到输出端的同步控制,其实就是控制何时输出。

DMAMUX1支持的8种同步输入,供DMA1和DMA2使用:

  1. #define HAL_DMAMUX1_SYNC_DMAMUX1_CH0_EVT   0U   
  2. #define HAL_DMAMUX1_SYNC_DMAMUX1_CH1_EVT   1U   
  3. #define HAL_DMAMUX1_SYNC_DMAMUX1_CH2_EVT   2U   
  4. #define HAL_DMAMUX1_SYNC_LPTIM1_OUT        3U   
  5. #define HAL_DMAMUX1_SYNC_LPTIM2_OUT        4U  
  6. #define HAL_DMAMUX1_SYNC_LPTIM3_OUT        5U  
  7. #define HAL_DMAMUX1_SYNC_EXTI0             6U   
  8. #define HAL_DMAMUX1_SYNC_TIM12_TRGO        7U   

复制代码

DMAMUX2支持的16种同步输入,供BDMA使用:

  1. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH0_EVT   0U   
  2. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH1_EVT   1U   
  3. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH2_EVT   2U  
  4. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH3_EVT   3U   
  5. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH4_EVT   4U   
  6. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH5_EVT   5U   
  7. #define HAL_DMAMUX2_SYNC_LPUART1_RX_WKUP   6U   
  8. #define HAL_DMAMUX2_SYNC_LPUART1_TX_WKUP   7U   
  9. #define HAL_DMAMUX2_SYNC_LPTIM2_OUT        8U   
  10. #define HAL_DMAMUX2_SYNC_LPTIM3_OUT        9U  
  11. #define HAL_DMAMUX2_SYNC_I2C4_WKUP        10U   
  12. #define HAL_DMAMUX2_SYNC_SPI6_WKUP        11U   
  13. #define HAL_DMAMUX2_SYNC_COMP1_OUT        12U   
  14. #define HAL_DMAMUX2_SYNC_RTC_WKUP         13U   
  15. #define HAL_DMAMUX2_SYNC_EXTI0            14U   
  16. #define HAL_DMAMUX2_SYNC_EXTI2            15U  
复制代码

  DMA Channels event接口

DMAMUX的事件输出。

  DMA requests to DMA controllers接口

DMAMUX的输出,发往DMA1,DMA2或者BDMA。

39.2.3 请求发生器(Request Generator)
请求触发器最大的优势就是可以让不支持DMA传输的外设也可以通过Trigger inputs接口触发DMA传输,比如我们可以将RAM中的数据通过定时器触发直接输出到GPIO,这样就可以产生各种脉冲效果,这样就比较灵活了。

这里我们再进一步的认识下请求发生器,通过下面框图可以看出请求发生器有n个通道,并且每个通道都支持t个触发。这里有一个关键知识点,所有这些通道可以选择同一个触发源。

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


了解了这些之后,我们要对它的工作过程有一个简单的认识,看下面的时序图:

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


  dmamux_req_gen信号请求发生器生成的DMA请求。
  dmamux_req_out信号是DMAMUX的输出,供DMA1,DMA2或者BDMA使用。
  Request generator counter这个计数器比较重要,它的意思是一次dmamux_trg触发信号,可以连续执行的DMA请求,最大32次。这里是以DMA可以执行的最快速度进行响应的。每执行一次,计数器减1,减到0后自动加载用户设置的最大次数,等待下次触发,依次进行。如果计数器还没有减到0就再次触发,请求发生器的中断状态寄存器DMAMUX_RGSR的标志将被置位,如果使能了中断,将会被触发。
  dmamux_trg信号是触发源。

39.2.4 同步触发和请求复用器(Request multiplexer)
同步输入接口可以用来控制DMAMUX的输入端的DMA外设请求到输出端的同步控制,其实就是控制何时输出。

这里我们再进一步的认识下请求复用器,从下面的框图中可以看出请求发生器有m个通道,并且每个通道都支持n+p+2个DMA请求,但是每个通道不可以选择相同的DMA请求。

特别注意红色方框的地方,请求发生器的n个DMA请求和p个DMA外设请求全都汇集于此,可供这里的多路选择器选择。

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


了解了这些之后,我们要对它的工作过程有一个简单的认识,看下面的时序图:

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


下面连续同步三次的效果,每次产生4次DMA请求:

aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMS8xMzc5MTA3LTIw.png


  dmamux_reqx信号是请求复用器的输入端。
  dmamux_syncx是同步触发信号。
  dmamux_req_outx信号是DMAMUX的输出,供DMA1,DMA2或者BDMA使用。
  DMA request counter这个计数器比较重要,他的意思是一次dmamux_syncx触发信号,可以连续执行的DMA请求,最大32次。这里是以DMA请求可以执行的最快速度进行响应的。每执行一次,计数器减1,减到0后自动加载用户设置的最大次数,等待下次触发,依次进行。如果计数器还没有减到0就再次触发,请求发生器的中断状态寄存器DMAMUX_CSR的标志将被置位,如果使能了中断,将会被触发。
  dmamux_evt信号是输出事件。
39.2.5 正常的DMA请求方式
除了前面说的请求发生器产生的DMA请求和同步触发产生的DMA请求,关闭了这两种方式后也可以通过DMAMUX正常发出DMA请求的,这种情况和之前使用F1和F4系列是一样的。

39.3 DMAMUX的HAL库用法
DMAMUX的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置GPIO、时钟,并根据需要配置NVIC、中断和DMA。下面我们逐一展开为大家做个说明。

39.3.1 请求发生器结构体HAL_DMA_MuxRequestGeneratorConfigTypeDef
HAL_DMA_MuxRequestGeneratorConfigTypeDef的定义如下:

  1. typedef struct
  2. {
  3. uint32_t SignalID;  /*!< Specifies the ID of the signal used for DMAMUX request generator
  4.                          This parameter can be a value of @ref DMAEx_MUX_SignalGeneratorID_selection */

  5.   uint32_t Polarity; /*!< Specifies the polarity of the signal on which the request is generated.
  6.                       This parameter can be a value of @ref DMAEx_MUX_RequestGeneneratorPolarity_selection */

  7.   uint32_t RequestNumber;  /*!< Specifies the number of DMA request that will be generated after a signal event.
  8.                            This parameters can be in the range 1 to 32 */

  9. }HAL_DMA_MuxRequestGeneratorConfigTypeDef;
复制代码

下面将这三个结构体成员一 一为大家做个说明。

  SingnalID
请求发生器的触发源ID选择,DMAMUX1可以选择的触发源ID如下:

  1. #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH0_EVT   0U  
  2. #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH1_EVT   1U   
  3. #define HAL_DMAMUX1_REQ_GEN_DMAMUX1_CH2_EVT   2U   
  4. #define HAL_DMAMUX1_REQ_GEN_LPTIM1_OUT        3U   
  5. #define HAL_DMAMUX1_REQ_GEN_LPTIM2_OUT        4U   
  6. #define HAL_DMAMUX1_REQ_GEN_LPTIM3_OUT        5U   
  7. #define HAL_DMAMUX1_REQ_GEN_EXTI0             6U   
  8. #define HAL_DMAMUX1_REQ_GEN_TIM12_TRGO        7U  
复制代码

DMAMUX2可以选择的触发源ID如下:

  1. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH0_EVT   0U  
  2. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH1_EVT   1U   
  3. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH2_EVT   2U   
  4. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH3_EVT   3U  
  5. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH4_EVT   4U   
  6. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH5_EVT   5U   
  7. #define HAL_DMAMUX2_REQ_GEN_DMAMUX2_CH6_EVT   6U   
  8. #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_WKUP   7U   
  9. #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_WKUP   8U   
  10. #define HAL_DMAMUX2_REQ_GEN_LPTIM2_WKUP       9U   
  11. #define HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT       10U  
  12. #define HAL_DMAMUX2_REQ_GEN_LPTIM3_WKUP      11U   
  13. #define HAL_DMAMUX2_REQ_GEN_LPTIM3_OUT       12U   
  14. #define HAL_DMAMUX2_REQ_GEN_LPTIM4_WKUP      13U   
  15. #define HAL_DMAMUX2_REQ_GEN_LPTIM5_WKUP      14U  
  16. #define HAL_DMAMUX2_REQ_GEN_I2C4_WKUP        15U   
  17. #define HAL_DMAMUX2_REQ_GEN_SPI6_WKUP        16U   
  18. #define HAL_DMAMUX2_REQ_GEN_COMP1_OUT        17U  
  19. #define HAL_DMAMUX2_REQ_GEN_COMP2_OUT        18U   
  20. #define HAL_DMAMUX2_REQ_GEN_RTC_WKUP         19U   
  21. #define HAL_DMAMUX2_REQ_GEN_EXTI0            20U   
  22. #define HAL_DMAMUX2_REQ_GEN_EXTI2            21U  
  23. #define HAL_DMAMUX2_REQ_GEN_I2C4_IT_EVT      22U   
  24. #define HAL_DMAMUX2_REQ_GEN_SPI6_IT          23U   
  25. #define HAL_DMAMUX2_REQ_GEN_LPUART1_TX_IT    24U   
  26. #define HAL_DMAMUX2_REQ_GEN_LPUART1_RX_IT    25U   
  27. #define HAL_DMAMUX2_REQ_GEN_ADC3_IT          26U   
  28. #define HAL_DMAMUX2_REQ_GEN_ADC3_AWD1_OUT    27U   
  29. #define HAL_DMAMUX2_REQ_GEN_BDMA_CH0_IT      28U  
  30. #define HAL_DMAMUX2_REQ_GEN_BDMA_CH1_IT      29U   
复制代码

  Polarity

触发信号的极性设置,可以是上升沿触发、下降沿触发或者双沿触发。

  1. #define HAL_DMAMUX_REQ_GEN_NO_EVENT        0x00000000U         
  2. #define HAL_DMAMUX_REQ_GEN_RISING          DMAMUX_RGxCR_GPOL_0  
  3. #define HAL_DMAMUX_REQ_GEN_FALLING         DMAMUX_RGxCR_GPOL_1  
  4. #define HAL_DMAMUX_REQ_GEN_RISING_FALLING  DMAMUX_RGxCR_GPOL
复制代码

  RequestNumber
每次触发信号后,可以执行的DMA请求次数,这个在本章的2.3小节已经进行了详细说明。

39.3.2 同步触发结构体HAL_DMA_MuxSyncConfigTypeDef
HAL_DMA_MuxSyncConfigTypeDef的定义如下::

  1. typedef struct
  2. {
  3.   uint32_t SyncSignalID;  
  4.   uint32_t SyncPolarity;
  5.   FunctionalState SyncEnable;  
  6.   FunctionalState EventEnable;  
  7.   uint32_t RequestNumber;
  8. }HAL_DMA_MuxSyncConfigTypeDef;
复制代码

下面将这五个结构体成员一 一为大家做个说明。

  SyncSingnalID
同步触发源的ID选择,DMAMUX1可以选择的触发源ID如下:

  1. #define HAL_DMAMUX1_SYNC_DMAMUX1_CH0_EVT   0U   
  2. #define HAL_DMAMUX1_SYNC_DMAMUX1_CH1_EVT   1U  
  3. #define HAL_DMAMUX1_SYNC_DMAMUX1_CH2_EVT   2U   
  4. #define HAL_DMAMUX1_SYNC_LPTIM1_OUT        3U   
  5. #define HAL_DMAMUX1_SYNC_LP TIM2_OUT       4U   
  6. #define HAL_DMAMUX1_SYNC_LPTIM3_OUT        5U   
  7. #define HAL_DMAMUX1_SYNC_EXTI0             6U   
  8. #define HAL_DMAMUX1_SYNC_TIM12_TRGO        7U
复制代码

DMAMUX2可以选择的触发源ID如下:

  1. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH0_EVT   0U   
  2. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH1_EVT   1U   
  3. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH2_EVT   2U   
  4. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH3_EVT   3U   
  5. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH4_EVT   4U   
  6. #define HAL_DMAMUX2_SYNC_DMAMUX2_CH5_EVT   5U   
  7. #define HAL_DMAMUX2_SYNC_LPUART1_RX_WKUP   6U   
  8. #define HAL_DMAMUX2_SYNC_LPUART1_TX_WKUP   7U   
  9. #define HAL_DMAMUX2_SYNC_LPTIM2_OUT        8U   
  10. #define HAL_DMAMUX2_SYNC_LPTIM3_OUT        9U   
  11. #define HAL_DMAMUX2_SYNC_I2C4_WKUP        10U   
  12. #define HAL_DMAMUX2_SYNC_SPI6_WKUP        11U   
  13. #define HAL_DMAMUX2_SYNC_COMP1_OUT        12U   
  14. #define HAL_DMAMUX2_SYNC_RTC_WKUP         13U   
  15. #define HAL_DMAMUX2_SYNC_EXTI0            14U   
  16. #define HAL_DMAMUX2_SYNC_EXTI2            15U  
复制代码

  SyncPolarity
同步触发信号的极性设置,可以是上升沿触发、下降沿触发或者双沿触发。

  1. #define HAL_DMAMUX_SYNC_NO_EVENT        0x00000000U            
  2. #define HAL_DMAMUX_SYNC_RISING          DMAMUX_CxCR_SPOL_0      
  3. #define HAL_DMAMUX_SYNC_FALLING         DMAMUX_CxCR_SPOL_1      
  4. #define HAL_DMAMUX_SYNC_RISING_FALLING  DMAMUX_CxCR_SPOL   
复制代码

  SyncEnable
用于使能同步触发,参数可以是ENABLE 或者 DISABLE。

  EventEnable
同步触发事件输出使能,当参数RequestNumber的数值减到0的时候才会输出。

  RequestNumber
每次同步触发信号后,可以执行的DMA请求次数,这个在本章的2.4小节已经进行了详细说明。

39.3.3 DMAMUX的状态标志清除问题
DMAMUX有两个中断,一个是请求复用器通道发生同步事件溢出,另一个是请求发生器通道发生触发事件溢出。

当用户调用了函数HAL_DMA_Start_IT,程序代码中会根据用户是否使能了请求复用器或者请求发生器通道来使能这两个中断。

  1. HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
  2. {
  3.     /* 省略未写 */

  4.     if((hdma->DMAmuxChannel->CCR & DMAMUX_CxCR_SE) != 0U)
  5.     {
  6.       /* 使能同步溢出中断 */
  7.       hdma->DMAmuxChannel->CCR |= DMAMUX_CxCR_SOIE;
  8.     }

  9.     if(hdma->DMAmuxRequestGen != 0U)
  10.     {
  11.       /* 使能请求发生器的溢出中断 */
  12.       hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_OIE;
  13.     }

  14.     /* 省略未写 */

  15. }
复制代码


这两个中断产生的中断标志是在函数HAL_DMAEx_MUX_IRQHandler里面做的清除,如果大家不使用HAL库提供的这个中断处理函数,就需要自己编写代码清除。

  1. void HAL_DMAEx_MUX_IRQHandler(DMA_HandleTypeDef *hdma)
  2. {
  3.   /* 检测DMAMUX同步溢出 */
  4.   if((hdma->DMAmuxChannelStatus->CSR & hdma->DMAmuxChannelStatusMask) != 0U)
  5.   {
  6.     /* 禁止同步溢出中断 */
  7.     hdma->DMAmuxChannel->CCR &= ~DMAMUX_CxCR_SOIE;

  8.     /* 清除DMAMUX同步溢出标志 */
  9.     hdma->DMAmuxChannelStatus->CFR = hdma->DMAmuxChannelStatusMask;

  10.     /* Update error code */
  11.     hdma->ErrorCode |= HAL_DMA_ERROR_SYNC;

  12.     if(hdma->XferErrorCallback != NULL)
  13.     {
  14.       /* 回调函数 */
  15.       hdma->XferErrorCallback(hdma);
  16.     }
  17.   }

  18.   if(hdma->DMAmuxRequestGen != 0)
  19.   {
  20.    /* 检测请求发生器溢出 */
  21.     if((hdma->DMAmuxRequestGenStatus->RGSR & hdma->DMAmuxRequestGenStatusMask) != 0U)
  22.     {
  23.       /* 禁止请求发生器溢出中断 */
  24.       hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_OIE;

  25.       /* 清除DMAMUX请求发生器溢出标志 */
  26.       hdma->DMAmuxRequestGenStatus->RGCFR = hdma->DMAmuxRequestGenStatusMask;

  27.       /* 更新错误代码标识 */
  28.       hdma->ErrorCode |= HAL_DMA_ERROR_REQGEN;

  29.       if(hdma->XferErrorCallback != NULL)
  30.       {
  31.         /* 回调函数 */
  32.         hdma->XferErrorCallback(hdma);
  33.       }
  34.     }
  35.   }
  36. }
复制代码


39.3.4 DMAMUX初始化流程总结
DMAMUX没有单独的初始化流程,要结合第40章和42章的函数一起使用。

39.4 源文件stm32h7xx_hal_dma_ex.c
DMAMUX用到如下四个说明,这里把这四个函数的使用为大家做个说明:

  HAL_DMAEx_ConfigMuxSync
  HAL_DMAEx_ConfigMuxRequestGenerator
  HAL_DMAEx_EnableMuxRequestGenerator
  HAL_DMAEx_DisableMuxRequestGenerator

39.4.1 函数HAL_DMAEx_ConfigMuxSync
函数原型:

  1. HAL_StatusTypeDef HAL_DMAEx_ConfigMuxSync(DMA_HandleTypeDef *hdma, HAL_DMA_MuxSyncConfigTypeDef *pSyncConfig)
  2. {
  3.   uint32_t syncSignalID = 0;
  4.   uint32_t syncPolarity = 0;

  5.   /* 检测参数 */
  6.   assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));
  7.   assert_param(IS_DMAMUX_SYNC_STATE(pSyncConfig->SyncEnable));
  8.   assert_param(IS_DMAMUX_SYNC_EVENT(pSyncConfig->EventEnable));
  9.   assert_param(IS_DMAMUX_SYNC_REQUEST_NUMBER(pSyncConfig->RequestNumber));

  10.   /* 检测是否使能了同步触发 */
  11.   if(pSyncConfig->SyncEnable == ENABLE)
  12.   {
  13.     assert_param(IS_DMAMUX_SYNC_POLARITY(pSyncConfig->SyncPolarity));

  14.     if(IS_D2_DMA_INSTANCE(hdma) != 0U)
  15.     {
  16.       assert_param(IS_D2_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
  17.     }
  18.     else
  19.     {
  20.       assert_param(IS_D3_DMAMUX_SYNC_SIGNAL_ID(pSyncConfig->SyncSignalID));
  21.     }
  22.     syncSignalID = pSyncConfig->SyncSignalID;
  23.     syncPolarity = pSyncConfig->SyncPolarity;
  24.   }

  25.   /* 检测DMA是否处于就绪态 */
  26.   if(hdma->State == HAL_DMA_STATE_READY)
  27.   {
  28.     /* 上锁 */
  29.     __HAL_LOCK(hdma);

  30.     /* 应用新的配置前禁止同步和产生同步事件 */
  31.     CLEAR_BIT(hdma->DMAmuxChannel->CCR,(DMAMUX_CxCR_SE | DMAMUX_CxCR_EGE));

  32.     /* 配置新的参数,同时DMAMUX_CxCR_DMAREQ_ID 位保持不变 */
  33.     MODIFY_REG( hdma->DMAmuxChannel->CCR, \
  34.                (~DMAMUX_CxCR_DMAREQ_ID) , \
  35.                (syncSignalID << POSITION_VAL(DMAMUX_CxCR_SYNC_ID))       | \
  36.                ((pSyncConfig->RequestNumber - 1U) << POSITION_VAL(DMAMUX_CxCR_NBREQ)) | \
  37.                syncPolarity | (pSyncConfig->SyncEnable << DMAMUX_POSITION_CxCR_SE)    | \
  38.                (pSyncConfig->EventEnable << DMAMUX_POSITION_CxCR_EGE));

  39.       /* 开锁 */
  40.     __HAL_UNLOCK(hdma);

  41.     return HAL_OK;
  42.   }
  43.   else
  44.   {
  45.     /* 设置错误标志 */
  46.     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;

  47.     /* 返回状态HAL_ERROR */
  48.     return HAL_ERROR;
  49.   }
  50. }
复制代码

函数描述:

此函数用于配置DMAMUX的同步触发,可以用来控制DMAMUX的输入端的DMA外设请求到输出端的同步控制,其实就是控制何时输出。

函数参数:

  第1个参数是DMA_HandleTypeDef类型结构体指针变量,用于配置DMA的初始化参数。
  第2个参数是HAL_DMA_MuxSyncConfigTypeDef类型结构体变量,参数成员的含义在本章的3.2小节有讲解说明。
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
注意事项:

第1个参数的结构体成员介绍在第40章进行了讲解。
调用此函数前要先调用函数HAL_DMA_Init配置好DMA。

39.4.2 函数HAL_DMAEx_ConfigMuxRequestGenerator
函数原型:

  1. HAL_StatusTypeDef HAL_DMAEx_ConfigMuxRequestGenerator (DMA_HandleTypeDef *hdma, HAL_DMA_MuxRequestGeneratorConfigTypeDef *pRequestGeneratorConfig)
  2. {
  3.   HAL_StatusTypeDef status = HAL_OK;

  4.   /* 检查参数 */
  5.   assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));

  6.   if(IS_D2_DMA_INSTANCE(hdma) != 0U)
  7.   {
  8.     assert_param(IS_D2_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
  9.   }
  10.   else
  11.   {
  12.     assert_param(IS_D3_DMAMUX_REQUEST_GEN_SIGNAL_ID(pRequestGeneratorConfig->SignalID));
  13.   }

  14.   assert_param(IS_DMAMUX_REQUEST_GEN_POLARITY(pRequestGeneratorConfig->Polarity));
  15.   assert_param(IS_DMAMUX_REQUEST_GEN_REQUEST_NUMBER(pRequestGeneratorConfig->RequestNumber));

  16.   /* 如果DMA配置中未使用DMAMUX的请求发生器,返回HAL_ERROR */
  17.   if(hdma->DMAmuxRequestGen == 0U)
  18.   {
  19.     /* 设置参数错误 */
  20.     hdma->ErrorCode = HAL_DMA_ERROR_PARAM;

  21.     /* 设置错误状态 */
  22.     status = HAL_ERROR;
  23.   }
  24.   /* 必须保证请求发生器是关闭的才可以配置 */
  25.   else if((hdma->State == HAL_DMA_STATE_READY) && ((hdma->DMAmuxRequestGen->RGCR & DMAMUX_RGxCR_GE) == 0))
  26.   {

  27.     /* 上锁 */
  28.     __HAL_LOCK(hdma);

  29.     /* 设置新参数 */
  30.     hdma->DMAmuxRequestGen->RGCR = pRequestGeneratorConfig->SignalID | \
  31.                                   ((pRequestGeneratorConfig->RequestNumber - 1U) << POSITION_VAL(DMAMUX_RGxCR_NBREQ))| \
  32.                                   pRequestGeneratorConfig->Polarity;
  33.     /* 解锁 */
  34.     __HAL_UNLOCK(hdma);

  35.     return HAL_OK;
  36.   }
  37.   else
  38.   {
  39.     /* 设置错误标志 */
  40.     hdma->ErrorCode = HAL_DMA_ERROR_BUSY;

  41.     /* 设置错误状态 */
  42.     status = HAL_ERROR;
  43.   }

  44.   return status;
  45. }

复制代码

函数描述:

此函数用于配置DMAMUX的发生器。请求触发器最大的优势就是可以让不支持DMA传输的外设也可以通过Trigger inputs接口触发DMA传输,比如我们可以将RAM中的数据通过定时器触发直接输出到GPIO,就可以产生各种脉冲效果,这样就比较灵活了。

函数参数:

  第1个参数是DMA_HandleTypeDef类型结构体指针变量,用于配置DMA的初始化参数。
  第2个参数是HAL_DMA_MuxRequestGeneratorConfigTypeDef f类型结构体变量,参数成员的含义在本章的3.1小节有讲解说明。
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
注意事项:

第1个参数的结构体成员介绍在第40章进行了讲解。
调用此函数前要先调用函数HAL_DMA_Init配置好DMA。
使用举例:

  1. HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams ={0}

  2. dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT;   /* 请求触发器选择LPTIM2_OUT */
  3. dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING; /* LPTIM2输出的上升沿和下降沿均可触发  */
  4. dmamux_ReqGenParams.RequestNumber = 1;                            /* 触发后,传输进行1次DMA传输 */
  5. HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle, &dmamux_ReqGenParams); /* 配置DMAMUX */
  6. HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle);                      /* 使能DMAMUX请求发生器 */   
复制代码

39.4.3 函数HAL_DMAEx_EnableMuxRequestGenerator
函数原型:

  1. HAL_StatusTypeDef HAL_DMAEx_EnableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
  2. {
  3.   /* 检测参数 */
  4.   assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));

  5.   /* 如果DMA配置中使用了DMAMUX的请求发生器,则将其使能并返回HAL_OK */
  6.   if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
  7.   {

  8.     /* 使能请求发生器 */
  9.     hdma->DMAmuxRequestGen->RGCR |= DMAMUX_RGxCR_GE;

  10.    return HAL_OK;
  11. }
  12. else
  13. {
  14.    return HAL_ERROR;
  15. }
  16. }

复制代码

函数描述:

调用函数HAL_DMAEx_ConfigMuxRequestGenerator配置了请求发生器后,就可以调用此函数使能请求发生器。跟禁止函数HAL_DMAEx_DisableMuxRequestGenerator是一对。

函数参数:

  第1个参数是DMA_HandleTypeDef类型结构体指针变量。
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
使用举例:

  1. HAL_DMA_MuxRequestGeneratorConfigTypeDef dmamux_ReqGenParams ={0}

  2. dmamux_ReqGenParams.SignalID  = HAL_DMAMUX2_REQ_GEN_LPTIM2_OUT;   /* 请求触发器选择LPTIM2_OUT */
  3. dmamux_ReqGenParams.Polarity  = HAL_DMAMUX_REQ_GEN_RISING_FALLING; /* LPTIM2输出的上升沿和下降沿均可触发  */
  4. dmamux_ReqGenParams.RequestNumber = 1;                            /* 触发后,传输进行1次DMA传输 */
  5. HAL_DMAEx_ConfigMuxRequestGenerator(&DMA_Handle, &dmamux_ReqGenParams); /* 配置DMAMUX */
  6. HAL_DMAEx_EnableMuxRequestGenerator (&DMA_Handle);                      /* 使能DMAMUX请求发生器 */

复制代码

39.4.4 函数HAL_DMAEx_DisableMuxRequestGenerator

函数原型:

  1. HAL_StatusTypeDef HAL_DMAEx_DisableMuxRequestGenerator (DMA_HandleTypeDef *hdma)
  2. {
  3.   /* 检查参数 */
  4.   assert_param(IS_DMA_STREAM_ALL_INSTANCE(hdma->Instance));

  5. /* 如果DMA配置中使用了DMAMUX的请求发生器,则将其禁止并返回HAL_OK */
  6.   if((hdma->State != HAL_DMA_STATE_RESET) && (hdma->DMAmuxRequestGen != 0U))
  7.   {

  8.     /* 禁止请求发生器 */
  9.     hdma->DMAmuxRequestGen->RGCR &= ~DMAMUX_RGxCR_GE;

  10.    return HAL_OK;
  11. }
  12. else
  13. {
  14.    return HAL_ERROR;
  15. }
  16. }
复制代码

函数描述:

此函数用于禁止请求发生器,跟使能函数HAL_DMAEx_EnableMuxRequestGenerator是一对,

函数参数:

  第1个参数是DMA_HandleTypeDef类型结构体指针变量。
使用举例:

此函数跟前面的HAL_DMAEx_EnableMuxRequestGenerator是一对,使用时直接调用即可。

39.5 总结

本章节就为大家讲解这么多,DMXMUX用到的地方比较多,这几个常用的函数要熟练掌握。



收藏 评论0 发布时间:2021-12-24 19:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版