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

【经验分享】STM32H7的MDMA基础知识和HAL库API

[复制链接]
STMCU小助手 发布时间:2021-11-1 08:00
61.1 初学者重要提示
* B3 g0 f2 X- H0 ]6 p5 d$ G3 h  MDMA位于D1域,使用的64位的AXI总线,可以操作TCM空间(前面章节讲解的DMA2D,通用DMA和BDMA不支持操作TCM空间)。! K; D' [, n2 n9 C0 V
  对于本章节,重点要了解MDMA的buffer缓冲传输,block块传输和list列表模式的区别,详情见本章2.2小节。
, C# @: g! U8 H$ [61.2 MDMA基础知识
5 l% W3 h! J! x$ R- X* r6 {对于STM32H7的MDMA了解到以下几点即可:
5 l9 K+ p& W# _$ Z) u# n& g3 l( T; U( o' ~
  由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。
4 r* e9 W+ B0 S; W1 \6 y  MDMA有两个主控总线接口,一个是AXI/AHB总线接口,主要用存储器或者外设访问,另一个是AHBS总线接口,仅用于TCM空间访问。4 Q% A( k% ~7 y3 C: T8 x/ U" f" T
  有个16个通道,32个硬件触发源。每个通道都可以选择1个触发源,当然,也可以通过软件触发。; v& n  T: _7 ~3 Q/ b+ S: j( V
  16个通道的传输请求,既可以外设,也可以来自DMA1或DMA2
) b0 C/ G- _5 {  MDMA具有一个256级的DMA空间,被分为两个128级空间使用。
/ |, r8 a) \! y: U% B- z7 |( V7 q  MDMA的优先级可通过软件配置,支持very high, high, medium, low四个等级,如果配置的优先级相同,则由channel的序号决定,channel0最高,channel15最低
+ o$ {. o/ V" f. V4 A) t. r  数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
- s9 j& i. J4 e8 P6 X4 c0 S  源地址和目标地址的大小和地址增量可以独立选择。4 |! b! V$ A2 B& f8 k5 s+ J
  数据的打包和拆解是采用的小端格式。* y3 _3 q9 t7 _4 {4 W7 U9 [
  支持突发模式,最大可传输128字节。
, u3 l) k/ j1 A1 ~  当源地址和目的地址的增量和数据大小相同,且位宽小于等于32bit时,才允许TCM使用突发模式。5 ~' C& x/ \6 W9 @4 p! X5 U
61.2.1 MDMA硬件框图  w$ e+ w; H! r& M* _& M: R
认识一个外设,最好的方式就是看它的框图,方便我们快速地了解MDMA的基本功能,然后再看手册了解细节。框图如下所示:7 H2 Z  L% [: X8 @6 X! f
' O8 v# _$ u- ^% m, U$ o2 _2 Q2 ]
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png

  u& ?* q% S4 W通过这个框图,我们可以得到如下信息:
6 z; ^6 o( i2 e% X; `- R5 q5 d' s( `
9 q3 \1 k7 M* {6 |' `  mdma_it
- \" e5 t6 S0 N" v% pmdma的中断触发信号。
; J. _+ t1 U* F/ f* |
. x: e; f1 J% o( z" |2 `. u- S  mdma_str0到mdma_str31触发源5 _+ N5 b2 o. f& t( k" N% g- V
mdma的输入请求。
/ R" M5 ?* }( w2 _4 [; \2 |' K0 j4 W- W0 h& G
  mdma_hclk, A  k: ~7 q% E2 n" T1 F
MDMA的HCLK时钟。
( j6 J: J& ]* p; Q+ [5 [2 H3 O
9 C7 a) y& w. \61.2.2 MDMA块传输,缓冲传输和列表传输区别3 M0 B! Z5 z8 q: U/ U0 m
初学MDMA,要搞清除MDMA支持的块传输,缓冲传输和列表传输的区别。
1 g3 Z, O( T' Q8 e; |
" d+ J# P$ t) l  缓冲传输(MDMA_BUFFER_TRANSFER)& p3 N  k0 x4 t3 z
这个模式主要用于QSPI,DCMI,硬件JPEG等外设上。每个请求都会触发BufferTransferLength(最大128字节)大小的数据传输,此大小由HAL_MDMA_Init调用的参数配置。) D. s6 B1 Y9 E

% R/ \! _) R. }& q1 V) R5 n7 W/ h$ p4 }6 p: z
  块传输(MDMA_BLOCK_TRANSFER)9 m6 S) J, U+ S* ]6 h
此方式与DMA1和DMA2的数据传输相似,每次请求,触发一次块传输,块大小由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。  R; T( }: ^1 w, @1 N, P

' m, I( X; p$ O: d6 }6 x( x5 p+ j  H" L( E; w6 ^( {
  多块传输(MDMA_REPEAT_BLOCK_TRANSFER)% ]3 L& \9 J3 Q& [
顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。
$ _* ^, D) j9 w, U  s) s0 ^
4 e4 {; W/ M9 K' O
& J& H& X9 [; @  列表传输(MDMA_FULL_TRANSFER)0 Z5 a: t6 N, H. F( v
这种模式可以方便的实现多种MDMA配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode),$ \. |5 b! w; m. I% ?7 V5 z$ f- B
# n1 r4 b* _8 P* b8 a
61.2.3 MDMA列表模式及其循环方式
- m2 t7 H; f& x列表模式包含多种MDMA的配置表,每个表包含一组完整MDMA配置。用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。4 T$ n" X  [) `- h4 O! E# Z7 X
# W: ~+ d+ S4 X. N: J
  使用列表模式的话,函数HAL_MDMA_Init创建的是节点0。$ x2 t8 b6 E+ A
  使用函数HAL_MDMA_LinkedList_EnableCircularMode使能循环模式,注意是从节点1开始循环的,将节点1和末尾的节点相连,不包含HAL_MDMA_Init创建的节点0。
+ y) Y6 P, z' b7 G* V: U  节点0是初始配置,仅在初始化MDMA传输时使用一次,比如调用函数HAL_MDMA_Start_IT。6 o+ [& x$ u( d: o; |- Y
  如果要禁止循环模式,可以调用函数HAL_MDMA_LinkedList_DisableCircularMode。
# @4 p8 r' m/ z7 e) W: p  m  通过函数HAL_MDMA_LinkedList_RemoveNode还可以删除指定节点。( g5 G* J: B( P. y9 U. g& Q. g
61.2.4 MDMA的触发源
2 N& `, J/ j$ w/ a( ?" G# s" T( HMDMA支持的触发源如下,主要包含DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:
% o  N1 o% G* Y, e" C$ X5 o3 z0 l" z: _) l8 {& t5 q
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)
    4 w0 v% n. }) K: L" y
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  / g( o  h% C! L" Q2 c
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U) 9 ]/ [* C7 i1 i" g, o" c
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U) ! t+ B. F' w8 B6 f
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)5 U# I# n3 w2 A/ z
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U) ) Z8 b8 f* J! A$ E; k- l
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U); e" L' o4 A" Z3 w8 A
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U) + d) F4 S* ]5 S% p9 ^( n0 |
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  
    - E  {  j; G& `
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)
    1 X. K2 l/ d1 K) w# s# h3 E
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  
    # [6 X6 k* \/ e; S% `9 N
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU)
    - O' x* S) I9 M& _
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    , n9 F+ w& V0 ]
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU)2 O  N# y. n2 A$ n( J. j7 E1 h% W- u" H
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  * X, D3 l4 L" z' Q/ d
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)8 m2 m* U9 a) R- j8 r; Q( G
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  / \9 F# a; q5 F  I3 ^
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U) + X, n' f# {, v' }. N" T
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U)
    + W; P7 a) Y6 J" z* D; O# _) h
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U) 3 r. I& A! }7 q
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  # z! M2 x" F& c/ l
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  ; o! S5 D. i6 Z2 L
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  8 v# t# c, C+ h9 f! e
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U) : S3 M( ]7 k3 j' h: O
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)
      z! _. U0 H4 m: Y, {
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U) ) y1 g7 n8 x1 o; D3 O- d
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)
    2 l$ f/ W4 l7 K; H

  28. 9 {- `0 ?3 i' {: s3 @
  29. #if defined(DSI)
    ' y7 i# N/ N8 I* t+ U9 [5 q
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU) & @! Q: k0 k! F( P+ n4 s$ A9 C4 g
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU)
    ) K$ X2 L6 k4 ]/ d; H
  32. #endif /* DSI */, x* y8 Y7 R$ k' j9 B

  33. - a4 j/ h$ P( Q1 m9 }
  34. #define MDMA_REQUEST_SDMMC1_ED_DATA      ((uint32_t)0x0000001DU) ! k/ M- i0 J2 W2 x1 @. k* N
  35. ; f$ R  C2 \9 X5 J
  36. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U)
复制代码

$ M8 v1 ?1 }; y  c. i0 _3 U& V% \# G) g3 A

5 W2 K3 x3 O) \8 V* n61.2.5 MDMA的软件触发方式
! m. b0 c! l. u5 ^4 \MDMA配置为MDMA_REQUEST_SW软件触发时,可以通过函数HAL_MDMA_GenerateSWRequest产生触发请求,使用此函数要注意以下两个问题:6 ~7 N; w+ u: p4 y# |
! S3 E  O( O  ~, ~) f' a
  如果传输结束或者传输还没有启动,调用此函数会返回error。0 i1 @# X: Y$ U: @
  如果传输还在进行中断,调用此函数会返回error,这次请求会被忽略。
# h7 R$ ^4 [4 j. ^. T" P& G8 R& A! b
. @2 Z2 ]9 {5 X
应用示例1:
% `& n8 m: H# ?+ ~' B& t7 @
& R7 @9 e! ^4 m! O  MDMA配置为MDMA_BUFFER_TRANSFER模式,软件触发。
( S4 d. ]; ]' E. j3 z% O  注册回调函数HAL_MDMA_XFER_BUFFERCPLT_CB_ID。" p- m- B/ K! \+ v! j; n
  调用函数HAL_MDMA_Start_IT会触发一次BufferTransferLength长度的数据传输。2 [, V0 v2 A" B! M4 Q2 @) _
  传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest启动传输。8 G# d4 P/ F, A2 L# \' ~

" B, }5 G  o& c) C5 q1 `4 t% ^: s8 J& _1 b
应用示例2:' _! m% A$ d$ d9 Q

6 ^5 s' v% X0 Y2 ~& ], J; i7 a  MDMA配置为MDMA_BLOCK_TRANSFER模式,软件触发。
: V* x& l! C! }; o" l  注册回调函数HAL_MDMA_XFER_BLOCKCPLT_CB_ID。: G3 e6 p/ n3 w. C4 i4 N, {) N
  调用函数HAL_MDMA_Start_IT会触发一次块传输。
+ s3 k' ^& i0 M2 c  传输结束会进入回调函数,用户可以再回调函数里面再次调用HAL_MDMA_GenerateSWRequest再次启动传输。
7 ~+ ^6 d  Q0 x( @$ I& _" t7 |$ [61.3 MDMA的HAL库用法
8 H, N: p/ U$ Q* I1 yMDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。
, w- Y, W) Z* s! p7 J; Y" M) n& J* [% U7 `, l4 ^/ T  }2 s
61.3.1 MDMA寄存器结构体MDMA_Channel_TypeDef和MDMA_TypeDef
. N4 {! M% V4 k0 G0 J' T. jMDMA相关的寄存器是通过HAL库中的结构体MDMA_Channel_TypeDef和MDMA_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:# R1 U0 }4 F/ N* k/ s( t3 @
3 Y1 F1 g. n% i- m/ _
  1. typedef struct9 u" f# P/ z! ~: R
  2. {
    - K2 B) g8 ]2 [$ r
  3.   __IO uint32_t  CISR;      /*!< MDMA channel x interrupt/status register,             Address offset: 0x40 */# Q1 V! u# J9 j: @: d7 S! d3 P
  4.   __IO uint32_t  CIFCR;     /*!< MDMA channel x interrupt flag clear register,         Address offset: 0x44 */: C' ?( t$ z. @* [3 j% ?
  5.   __IO uint32_t  CESR;      /*!< MDMA Channel x error status register,                 Address offset: 0x48 */
    * Q3 e' J" q% R. q
  6.   __IO uint32_t  CCR;       /*!< MDMA channel x control register,                      Address offset: 0x4C */ ' }. x$ |* M% ], b% s
  7.   __IO uint32_t  CTCR;      /*!< MDMA channel x Transfer Configuration register,       Address offset: 0x50 */( s2 c% k1 l$ j6 w# ?  A/ [$ }
  8.   __IO uint32_t  CBNDTR;    /*!< MDMA Channel x block number of data register,         Address offset: 0x54 */0 g3 v6 T  n6 j
  9.   __IO uint32_t  CSAR;      /*!< MDMA channel x source address register,               Address offset: 0x58 */
    # f4 L1 C8 O# ]% o9 z
  10.   __IO uint32_t  CDAR;      /*!< MDMA channel x destination address register,          Address offset: 0x5C */1 [5 M, e& Z) G1 v1 Q' C# Y0 F
  11.   __IO uint32_t  CBRUR;     /*!< MDMA channel x Block Repeat address Update register,  Address offset: 0x60 */
    5 Q! c3 L6 k- P5 s8 a3 K9 _9 |
  12.   __IO uint32_t  CLAR;      /*!< MDMA channel x Link Address register,                 Address offset: 0x64 */5 y& w( ?5 k8 s6 \& T5 d. E3 ^
  13.   __IO uint32_t  CTBR;      /*!< MDMA channel x Trigger and Bus selection Register,    Address offset: 0x68 */6 u8 t7 X+ q( e$ }8 }5 x( T
  14.   uint32_t     RESERVED0;   /*!< Reserved, 0x68                                                           */    r! f2 x0 C7 p4 r; e
  15. __IO uint32_t    CMAR;     /*!< MDMA channel x Mask address register,                Address offset: 0x70 */
    $ z9 w+ b8 _/ P% C( q
  16. __IO uint32_t   CMDR;      /*!< MDMA channel x Mask Data register,                   Address offset: 0x74 */
    $ P) N' t4 r0 Y. R! C
  17. }MDMA_Channel_TypeDef;4 K! {& H* L" H# S1 d7 [2 J

  18. + R$ y7 m* f& m0 W
  19. typedef struct
    + Q2 _: V; `2 l. o
  20. {4 L% @$ v7 H( ~0 {& B2 z# m* O" q
  21.   __IO uint32_t  GISR0;   /*!< MDMA Global Interrupt/Status Register 0,          Address offset: 0x00 */8 N4 N' Y8 U& ~5 d# S# V8 M  f9 G3 h
  22. }MDMA_TypeDef;* a# r9 I" o4 P. L$ M
复制代码
* [* g) _  S4 o2 J

1 v% s% o2 N6 N' j" I% ?__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
- n7 N. E( S9 U! F0 Q9 {
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    * M# Y( O0 _& T0 {$ _, _9 M
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码
8 R. W1 j8 h! t: J
下面我们再看MDMA的定义,在stm32h743xx.h文件。
- j3 X4 H- v+ W6 [' P- I$ Q3 D8 c' P" a( n* O1 T
  1. #define PERIPH_BASE           ((uint32_t)0x40000000)
    % e8 Q! Q1 y& m1 v- o5 E$ D
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000)
    ( c9 u' ^% i+ z
  3. #define MDMA_BASE             (D1_AHB1PERIPH_BASE + 0x0000)
    8 R! Q( h2 e" V0 l0 n4 S4 e
  4. 6 e: e: o0 A/ H4 W2 x9 ]. P
  5. #define MDMA_Channel0_BASE    (MDMA_BASE + 0x00000040)+ [! w7 y2 m3 z! G! k
  6. #define MDMA_Channel1_BASE    (MDMA_BASE + 0x00000080)5 D* Z5 y* H. j3 M; R
  7. #define MDMA_Channel2_BASE    (MDMA_BASE + 0x000000C0)
    ' t$ d6 b  [- f# `4 ?1 Q
  8. #define MDMA_Channel3_BASE    (MDMA_BASE + 0x00000100)
    . \' j# j  H7 {) }3 ^6 Z" S
  9. #define MDMA_Channel4_BASE    (MDMA_BASE + 0x00000140)0 g* O$ d# v7 Y' w, ^! n
  10. #define MDMA_Channel5_BASE    (MDMA_BASE + 0x00000180)( c' @$ v! m% h; J! ?! m' W, A
  11. #define MDMA_Channel6_BASE    (MDMA_BASE + 0x000001C0)
    ( Z6 e" _  x4 p7 \
  12. #define MDMA_Channel7_BASE    (MDMA_BASE + 0x00000200)  V7 R! x6 b: R' \
  13. #define MDMA_Channel8_BASE    (MDMA_BASE + 0x00000240)
    / a3 N% s% R" d; Y7 U
  14. #define MDMA_Channel9_BASE    (MDMA_BASE + 0x00000280)8 t9 |6 Y2 o# q
  15. #define MDMA_Channel10_BASE   (MDMA_BASE + 0x000002C0)
    9 {- k" J% l# b0 }% F/ K
  16. #define MDMA_Channel11_BASE   (MDMA_BASE + 0x00000300); o5 C/ R! T; ]( ~* F/ y6 P
  17. #define MDMA_Channel12_BASE   (MDMA_BASE + 0x00000340)
    % s1 B/ i" k4 y5 o* S, `5 t
  18. #define MDMA_Channel13_BASE   (MDMA_BASE + 0x00000380)
    4 v; E# i2 T4 k# F/ v2 R. H0 _
  19. #define MDMA_Channel14_BASE   (MDMA_BASE + 0x000003C0)- f* L- @! ~% A6 e4 ]
  20. #define MDMA_Channel15_BASE   (MDMA_BASE + 0x00000400)6 n  r! o, p& ]

  21. 7 H5 c/ s9 i7 A# {4 v& N$ e$ \
  22. #define MDMA                ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000- J; v3 }, D! @# `8 Q, x
  23. #define MDMA_Channel0       ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)
    + n: i$ `; J- i/ Y/ [
  24. #define MDMA_Channel1       ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)0 I% c7 K) X, y/ C8 q( i
  25. #define MDMA_Channel2       ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)
    4 ]$ }- y+ ^- l9 @9 H+ W
  26. #define MDMA_Channel3       ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
      i* @  V# O+ m$ o2 }0 ^! e
  27. #define MDMA_Channel4       ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)
    1 K8 d2 e2 y2 a, S7 P8 U
  28. #define MDMA_Channel5       ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)
    + f- A" P5 {$ x! n$ F$ C& ]
  29. #define MDMA_Channel6       ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)
    $ S* l, ^# d2 j/ u1 K/ {3 q
  30. #define MDMA_Channel7       ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
    ! d- o0 S8 B' D8 ^; o/ O& ~; w1 i
  31. #define MDMA_Channel8       ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)" Y# ?2 h" `( t5 Y1 l% m8 Y' J
  32. #define MDMA_Channel9       ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE)/ _+ g, x' Y3 T, Z* I8 y5 V, Q
  33. #define MDMA_Channel10      ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)& L9 N2 _5 l8 J! o" u' f4 r' {
  34. #define MDMA_Channel11      ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE)
    : E6 V. e5 Q& P9 w
  35. #define MDMA_Channel12      ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)8 z' q" V" ]3 ]  s
  36. #define MDMA_Channel13      ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
    $ O/ U1 J8 q5 d9 E9 j
  37. #define MDMA_Channel14      ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)" L9 S! V  H) n4 J7 X  T
  38. #define MDMA_Channel15      ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
复制代码

1 _+ H  W4 f# c6 I3 H2 y( z/ [/ n- D; e# [/ z, \2 \
8 s2 E/ ]: M- C6 ^8 e4 ?
我们访问MDMA的GISR0寄存器可以采用这种形式:MDMA->GISR0 = 0。
0 M: ^8 m: T$ }4 P8 \: p3 @' J: _" l2 g% r
61.3.2 MDMA的参数结构体MDMA_InitTypeDef
* f1 }0 n( H' v1 q0 U此结构体用于MDMA的参数配置,具体定义如下:
4 {7 i: D* I7 N* ]$ q$ |
$ q& g, T- ~. S# _- n, J
  1. typedef struct
    # B4 H" ?" z( A2 D! O6 Y4 [
  2. {. ?' {* F, W. `$ U6 E
  3.   uint32_t Request;                                                
    & T9 ?% Z0 M- d% c! p, N
  4.   uint32_t TransferTriggerMode;                                    $ y' h  h  F( y
  5.   uint32_t Priority;                                                     
    # i) `. M. q3 g  l# G( u
  6.   uint32_t Endianness;                                                
    3 x+ \2 W2 F" D3 M
  7.   uint32_t SourceInc;                                              - D, ^5 p+ }9 i4 n" `! O, x
  8.   uint32_t DestinationInc;                                       
    - Q' K* C0 M' i& x
  9.   uint32_t SourceDataSize;                                         % f# v8 ?  |: y
  10.   uint32_t DestDataSize;            
    9 N8 V- c- s7 U1 q* l( r
  11.   uint32_t DataAlignment;          % ?$ g0 X, k& C5 }% V: A9 q
  12.   uint32_t BufferTransferLength;    & c6 G) c) N/ p; @2 i) a
  13.   uint32_t SourceBurst;                                            ) Y7 ?! l! n% {) ]" p% h1 Z
  14.   uint32_t DestBurst;               
    2 g. e' W+ Y2 T3 Y$ a9 w# j* ?
  15.   int32_t SourceBlockAddressOffset;                                                                            # r! G: A1 _; T) T
  16.   int32_t DestBlockAddressOffset;      
    4 A, {% ~$ ]$ i- h
  17. }MDMA_InitTypeDef;
复制代码
, |. y5 B4 Z# g3 _/ A+ B3 A( o
  @$ i2 u9 `, @6 n

/ I8 x( C' ?/ _  ^1 O下面将这几个参数逐一为大家做个说明:
. o+ s- P& }6 S2 b# [* p. M- i2 V5 \3 `8 a$ b7 r2 ]
  uint32_t Request5 ^1 z7 V5 j$ Y3 R; Y% `/ a
触发MDMA的请求源,支持请求源如下:
3 A% J' g3 m  L; M0 E) J
9 X) _( L: \3 i' P- ]; v5 _/ W
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)  , P1 Z8 _6 O& z+ `. s& r# s* W
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  ; {  a' V3 ~# G
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U) ' ]( G5 |0 }  ?1 Y& s# ~! j- G7 h
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U)  
    # n9 B- `8 M+ R/ X& z, q' C5 B
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)  7 D! Y/ R3 N; ]. ]5 W& E2 l% Z9 q
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U) 4 t# ~: T1 u) c4 i
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)  
    5 P2 j8 ^. ?/ u( R/ E
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U)  ! H: s% d. e( x& ^
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  
    ! W+ O1 M* h: L3 Q) i: g0 B
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)  
    : Y+ p, j2 M' |1 B. p# Y8 A- b
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  , \; a& K$ e7 e( T! [6 r! V
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU)
    / D: U7 \* p0 y2 |" A$ K" Z
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    4 p! t: j1 Q7 G& i
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU)
    & L& v* b) {: k. X
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  - z* ^/ ]7 d8 x0 k) q+ x
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)  " {; ?  D6 z- }" F" }5 a) U( {
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  
    4 F- u6 _% A/ w. |4 v
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U)
    % z4 {0 ^" r4 t8 S- o% n
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U)  ; _# U0 W% o! I0 a# U* Z
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U)  0 X) c4 r4 v9 }& O* ^. g$ v  j$ E
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  
    $ n2 Y# C3 R2 Y+ D1 |2 @
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  $ n: e5 t% f) Z% U! H- X( W; I5 x
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  
      h4 K0 ~  m/ z
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)  
    0 m* T, p! Q+ E+ W; ]
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)  + W9 R. O) X7 O
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U)  & L4 N+ N2 a" m! N$ X/ c; g& w& s" E
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)  & r" d; O! {- t, Q+ h
  28. # n+ `' t% D* c! B
  29. #if defined(DSI)
    % R2 X* `0 m9 @7 d
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU)  
    ; E( c; M- O* S
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU)  
    - {8 D6 [( Y6 A' r& x8 r' ]. ]
  32. #endif /* DSI */# p3 Z9 u- x: S( b+ O' R0 t

  33. " m/ |" |7 l9 y1 o) i
  34. #define MDMA_REQUEST_SDMMC1_END_DATA      ((uint32_t)0x0000001DU)
      T- Y. L+ f9 T' J6 y- h1 L
  35. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U) 8 ^+ `% [! N, U( R- b
复制代码
& b" q1 t- Y( s; X, y
1 n  W( w4 e" ^  g
  uint32_t TransferTriggerMode$ t2 E: w" I% F% z2 g3 y
MDMA的传输模式,具体支持的参数如下:
7 e, V& k& Q# m3 U9 c( w' `9 R6 G3 M, O# k9 S) U
  1. #define MDMA_BUFFER_TRANSFER          ((uint32_t)0x00000000U)      /* 缓冲传输 */2 E( [: {$ Y5 \+ f, `
  2. #define MDMA_BLOCK_TRANSFER           ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */6 B) N6 P- @) C" T, e* F" l% f
  3. #define MDMA_REPEAT_BLOCK_TRANSFER    ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */
    ; p; z8 ^. H$ `  K- z+ @4 M  [
  4. #define MDMA_FULL_TRANSFER            ((uint32_t)MDMA_CTCR_TRGM)   /* 链表传输 */
复制代码
$ R- d) W3 ~5 T$ u8 t

5 h" J+ O7 C4 {+ P  j4 ^# r3 |
$ Z3 w. L& l6 O  uint32_t Priority
$ e/ y3 j: A& Z6 [7 JMDMA通道的优先级设置,具体支持的参数如下:1 i8 ^( i/ |' O2 U

9 ~8 g- J1 f+ v2 c6 ^5 F! J! N1 N
  1. #define MDMA_PRIORITY_LOW             ((uint32_t)0x00000000U)     ' {/ z2 w$ {& [8 ]
  2. #define MDMA_PRIORITY_MEDIUM          ((uint32_t)MDMA_CCR_PL_0)  
    5 C' t' j5 W; f, ^" U$ m0 d
  3. #define MDMA_PRIORITY_HIGH            ((uint32_t)MDMA_CCR_PL_1)  
    ( g3 \: j5 ^1 g( @5 |  P8 I
  4. #define MDMA_PRIORITY_VERY_HIGH       ((uint32_t)MDMA_CCR_PL)   
复制代码

" b! K% n/ Z, x, G9 w( M
  s3 F: z$ g% g; c, _, Q1 }% S& I
" [9 H! N+ F. k  E0 }( c8 h6 d  uint32_t Endianness' s1 N8 x  u# u  G! r: [% w$ a
MDMA数据传输格式,具体支持的参数如下:
- T  o, b4 l  {% u! z0 Q
0 B1 Y$ H: z$ W0 }" F* ]
  1. #define MDMA_LITTLE_ENDIANNESS_PRESERVE          ((uint32_t)0x00000000U)  
    2 n% {" v. m( M6 }& @  B- K3 s0 S
  2. #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_BEX)  
    * @2 {- ]  o2 s0 e& G& ?
  3. #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX) # x# g$ R7 F. a' B
  4. #define MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_WEX)  
复制代码
( P$ l; I% }1 A2 A* `" o/ i' {

- U1 ~7 K% m, nMDMA_LITTLE_ENDIANNESS_PRESERVE:正常的小端格式。
! Q) n1 F4 b. |3 J, _) R
, H' X) y! g; V& k' JMDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE:以半字为单位,交互高低字节。
8 ^$ O: k+ o+ ], U! @+ D- e: g% R, I6 [5 w1 `
MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE:以字为单位,交互半字。; I* o5 q8 A9 Y

- t0 t4 G; V/ E5 O1 P5 J4 nMDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE:以双字为单位,交换字。
% ^/ }& W, o! a. ^+ Y2 B' k7 F
1 P" D- k: O6 k) K. @  uint32_t SourceInc5 O+ H: g; N8 h% s
MDMA源数据自增或者自减模式,具体支持的参数如下:
( }# |) k1 w0 N: @0 }+ G- ?
  1. $ J: q, c8 r+ C6 N" S# q2 M+ c
  2. #define MDMA_SRC_INC_DISABLE      ((uint32_t)0x00000000U)                                    5 i6 w1 c4 b# @) Q9 H0 n  J  O
  3. #define MDMA_SRC_INC_BYTE         ((uint32_t)MDMA_CTCR_SINC_1)                                , F. w+ A' d( o# Z' V$ m
  4. #define MDMA_SRC_INC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)
    / o+ l* ~- W4 ~  T# _
  5. #define MDMA_SRC_INC_WORD         ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1)
    + h7 O; P/ e+ c6 q2 S5 m: _. D
  6. #define MDMA_SRC_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS)  
      A! R/ o8 y0 b) y
  7. #define MDMA_SRC_DEC_BYTE         ((uint32_t)MDMA_CTCR_SINC)                                  * B: V$ G2 r8 j
  8. #define MDMA_SRC_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0)   
    - c8 c% k( ?2 V
  9. #define MDMA_SRC_DEC_WORD         ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1)   5 k7 }" r3 |, T. M- o- m% N: p
  10. #define MDMA_SRC_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS)   
复制代码

, J: R( y5 M1 f" J6 e* J$ l5 \3 \+ r$ J/ C6 H& X

  ]! C% M' {- t0 J; E  DestinationInc
2 t% s! C; w% m4 o0 ]8 v$ |MDMA目的数据自增或者自减模式,具体支持的参数如下:
0 m7 V4 \7 K; u2 L/ c
7 n) r' K6 A8 n) N# k7 l$ S7 ^
  1. #define MDMA_DEST_INC_DISABLE      ((uint32_t)0x00000000U)                                    
    ) |9 F( m( C* z  H- P" k, ~! _0 T
  2. #define MDMA_DEST_INC_BYTE         ((uint32_t)MDMA_CTCR_DINC_1)                               ! |7 _! \! O) y! P$ N: p8 N$ l
  3. #define MDMA_DEST_INC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)
    ( Y2 A) z  f  v- T( {, }8 \7 C  x6 O
  4. #define MDMA_DEST_INC_WORD         ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1) : N  b6 `7 l# y2 Y+ L( g
  5. #define MDMA_DEST_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS)   & m0 M' Z  m1 O) Y- q
  6. #define MDMA_DEST_DEC_BYTE         ((uint32_t)MDMA_CTCR_DINC)                                5 r9 u' L. ]7 o) }
  7. #define MDMA_DEST_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0)   - {5 K) D$ C" k) `6 _1 N% T
  8. #define MDMA_DEST_DEC_WORD         ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1)   
    7 F- c# t6 C( ]+ `+ ]+ ~
  9. #define MDMA_DEST_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS)  
复制代码
- v3 y7 A! _) `/ c

. `  t! a. x: i5 g
, e6 g: K% B8 u3 X  SourceDataSize& D" j6 g/ B. g9 J2 J2 r+ _1 t7 l
MDMA源数据带宽,具体支持的参数如下:
: v  h$ r  a) g  O) L) H5 Z, B. N5 Y3 Y2 {* Z& U
  1. #define MDMA_SRC_DATASIZE_BYTE        ((uint32_t)0x00000000U)        
    6 b5 |& j& _) {! b6 U/ a4 s
  2. #define MDMA_SRC_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_SSIZE_0)     - P0 c' M9 ?8 S; S
  3. #define MDMA_SRC_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_SSIZE_1)  / K7 j" S. ~' |4 \
  4. #define MDMA_SRC_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_SSIZE)   
    - S" X, h+ P+ N, G0 m/ {# v
复制代码

* [! }( \) B5 m1 c
1 x4 `) }9 q8 p# |0 M% v' Y  DestDataSize
( {. }" T. w; s$ O% ^( g' r) XMDMA目的数据带宽,具体支持的参数如下:  X+ K/ r1 {4 \3 b

9 [! |0 m5 o8 T  u
  1. #define MDMA_DEST_DATASIZE_BYTE        ((uint32_t)0x00000000U)        
    * N, @$ j0 ]% \8 T& I& Y1 c8 F! \
  2. #define MDMA_DEST_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_DSIZE_0)   
    . [0 G' D9 Y/ i* D
  3. #define MDMA_DEST_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_DSIZE_1)  2 P2 w, T, M1 j8 P* H2 J
  4. #define MDMA_DEST_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_DSIZE)     
复制代码
% l4 \  }/ _2 k. H9 B+ o

: v  E- |3 F$ W8 \# f( C4 \& ?( z! z  G: F+ F: z6 P9 x
  DataAlignment" S9 |  D+ c; e5 q3 X
MDMA的填充/对齐设置,具体支持的参数如下:3 r4 O9 I6 m* k! ~# Z/ ^
  1. #define MDMA_DATAALIGN_PACKENABLE        (uint32_t)MDMA_CTCR_PKE)       V1 I7 u3 b4 o6 b9 }
  2. #define MDMA_DATAALIGN_RIGHT            ((uint32_t)0x00000000U)     8 e/ r# k. _% u) U' q
  3. #define MDMA_DATAALIGN_RIGHT_SIGNED     ((uint32_t)MDMA_CTCR_PAM_0)  1 G# a& f6 m  ^9 c3 Z$ ^  f3 Y8 I
  4. #define MDMA_DATAALIGN_LEFT             ((uint32_t)MDMA_CTCR_PAM_1)  
复制代码

/ i7 i; [0 l! v. F+ n, v8 f. ]# l9 r- t0 X  {! |

1 [2 B+ I; L0 \. WMDMA_DATAALIGN_PACKENABLE:/ G: u. R$ \  k+ P: [
( L8 W( `! F0 ^& x1 w
将源数据封装/解封为目标数据大小。所有数据均右对齐(采用小端模式)。: G4 Q2 }# D( b

' ?& ?0 _" E8 kMDMA_DATAALIGN_RIGHT& n' a1 \3 x) p, W, ~

4 D; p6 W9 B5 c( w0 l4 K+ h) N8 C右对齐,用 0 进行填充(默认值)- G; y& M7 t! }+ {4 z' v4 D- v

$ R0 g' Q$ X  s: g' I9 NMDMA_DATAALIGN_RIGHT_SIGNED, E' R1 T. G( U; R7 q

) @' r* e  C1 U0 i右对齐,符号扩展
9 V- `+ V' I* X$ L( U
4 m. I4 I- d; S3 j% L# M; d- D- w0 LMDMA_DATAALIGN_LEFT
6 w! V+ r; }' ^* f" ?  r, M! V8 ^* E0 h  G
左对齐(用 0 进行填充)
3 s  R3 A7 S! N) ^
1 q- [+ m! Q1 I) l  BufferTransferLength
  I; h9 ?3 X! F& |, U单次传输长度设置,范围1-128,单位字节。+ X* \) M4 M- K( E

7 ^/ a5 Q" `4 j  SourceBurst+ F9 S" x5 X5 S  @/ }0 y: s8 U
源数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下:
# |9 u7 Y4 ]* n% F! v; p5 i2 D$ k
  1. #define MDMA_SOURCE_BURST_SINGLE        ((uint32_t)0x00000000U)                                      
    : ~, p& i' c9 x8 a
  2. #define MDMA_SOURCE_BURST_2BEATS        ((uint32_t)MDMA_CTCR_SBURST_0)                               #define MDMA_SOURCE_BURST_4BEATS        ((uint32_t)MDMA_CTCR_SBURST_1)                               #define MDMA_SOURCE_BURST_8BEATS        ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_1) % y" v; c' u6 K6 t; x6 w+ V4 R/ n* e3 k
  3. #define MDMA_SOURCE_BURST_16BEATS       ((uint32_t)MDMA_CTCR_SBURST_2)                              
    % w9 N) F# O$ d; j9 I' D& |9 \) g
  4. #define MDMA_SOURCE_BURST_32BEATS       ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_2) 2 I* g/ @4 l* ^$ C6 n( U
  5. #define MDMA_SOURCE_BURST_64BEATS       ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2) ( |" r' }: d. n- ]
  6. #define MDMA_SOURCE_BURST_128BEATS      ((uint32_t)MDMA_CTCR_SBURST) 5 ]  R; b% h- I* H6 C8 v
复制代码

. v  r0 v( T- @
  h0 [+ f) W6 S4 r2 o2 ~  DestBurst
& q$ O3 r8 W! r9 u+ E. a" G目的数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下
/ [6 d3 p7 N( L
  1. #define MDMA_DEST_BURST_SINGLE        ((uint32_t)0x00000000U)                                       - k4 ^, d" [$ f+ |6 S
  2. #define MDMA_DEST_BURST_2BEATS        ((uint32_t)MDMA_CTCR_DBURST_0)                                 $ J' l/ `( p1 }* O8 |  t) E
  3. #define MDMA_DEST_BURST_4BEATS        ((uint32_t)MDMA_CTCR_DBURST_1)                                 #define MDMA_DEST_BURST_8BEATS        ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_1) ! o! q3 C2 G& |" E# c9 W4 b5 P
  4. #define MDMA_DEST_BURST_16BEATS       ((uint32_t)MDMA_CTCR_DBURST_2)                                 
      ~& Q( v& k3 M
  5. #define MDMA_DEST_BURST_32BEATS       ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_2)  
      P( X3 }+ I) V5 D$ a6 b1 g
  6. #define MDMA_DEST_BURST_64BEATS       ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2)
    # b4 i/ P4 h; w7 [/ R1 B4 {
  7. #define MDMA_DEST_BURST_128BEATS      ((uint32_t)MDMA_CTCR_DBURST)  
    , N2 k3 q9 c3 @/ E+ e
复制代码
% Z- _6 W0 C- \0 D
  SourceBlockAddressOffset
4 l% ]$ @: d/ x" Z4 A) z用于设置源地址端数据偏移。6 n8 O+ m  J7 A: Y. Y

2 j7 h+ f$ ~" G2 K  DestBlockAddressOffset$ K0 R( O, I5 s: W
用于设置目的地址端数据偏移。. x0 n* v0 T& T$ d9 L

4 B) R7 k& X( L2 G3 J3 c61.3.3 MDMA结构体句柄MDMA_HandleTypeDef
5 d, i' u2 x1 H* ^& K0 L; p, ]HAL库在MDMA_Channel_TypeDef和MDMA_InitTypeDef的基础上封装了一个结构体MDMA_HandleTypeDef,定义如下:$ g6 o# W9 b, f! M2 k2 ~7 `- ?

. x! A+ C, C! n% D
  1. typedef struct __MDMA_HandleTypeDef
    ) s3 ^) A1 X; I4 ~$ r* W: G$ A: b
  2. {
    6 ]# q1 n. G# ]4 k3 B
  3.   MDMA_Channel_TypeDef *Instance;                                                                                                                                                                                             
    . m8 p: ?+ k- }0 D# N
  4.   MDMA_InitTypeDef      Init;                                                              $ C" |3 j% _; w; h- E% L
  5.   HAL_LockTypeDef       Lock;                                                                  
    , P# D: w: d+ f! A5 G  N0 R7 c$ O
  6.   __IO HAL_MDMA_StateTypeDef  State;                                                           : `  \8 b: o) v9 y+ p$ x$ ~# O
  7.   void                  *Parent;                                                               ' O. G' Y+ r' _) Q4 A! }
  8.   void                  (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);           * @8 P( V/ @# t
  9.   void                  (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     
    0 w9 f; ^4 M  H( p. w
  10.   void                  (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);      
    ( y1 O! I9 K+ p4 _  P
  11.   void                  (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
    $ d! L" R+ r/ k2 |, M
  12.   void                  (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);           5 b* q0 g* q9 u1 V, ?
  13.   void                  (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    % k# W0 {5 t8 C0 R) r5 _
  14.   MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;                                             
    4 ]& r- }' r) X5 }) v. N
  15.   MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;                                             / D3 b6 [# w9 y
  16.   uint32_t LinkedListNodeCounter;                                                                                                                                                                                      & N+ g! g8 ^7 P4 h% C
  17.   __IO uint32_t          ErrorCode;                                                            6 m, E0 d- w! ~2 d- d* o+ T) H& N4 {
  18. } MDMA_HandleTypeDef;
复制代码

/ E1 {( D$ d; N! n8 l1 x. m下面将这几个参数逐一做个说明。
2 ^% M3 @, _+ S: h, `  E' k0 O0 U! q$ y
/ Z4 w9 j" }9 M5 N) f5 O' J! @  MDMA_Channel_TypeDef  *Instance! l, y6 s) v% k
这个参数MDMA通道的例化,方便操作寄存器,详见本章3.1小节。/ K' c6 P! d0 T% T, `9 C2 N
; S6 A# t2 y6 n+ ^& J1 s
  MDMA_InitTypeDef      Init
9 r* b7 ?0 S, V这个参数用于MDMA的通道参数初始化,详见本章3.2小节。! S, ~2 }) a) K2 j' ]

# `' b# I, Y$ n  i) ]  void   *Parent
1 Y* f/ C  d2 T/ p* r! B0 ?7 @8 d9 |2 Z用于记录MDMA关联的外设。$ O7 i! Y6 ~5 E. ?" ^( r

# b* B" ]! B8 [7 t' f    void   (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);         
, ~! n8 H! x3 p$ V    void   (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);   
' \. Q6 ~9 p4 v# a6 {3 H& {    void   (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     4 N! }2 v% y0 J' r! p: K/ c; h6 d
    void   (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);% I  u1 ?' I( Y' y
    void   (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);          + ?  x, l' w7 x
    void   (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);   6 |, M* I7 Z1 }$ \0 J! x
MDMA的各种回调函数。   
0 L' r  I+ o: ~9 ^2 O$ B5 r0 W" W. R+ k9 T( g4 D
  MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;
+ f6 r3 d$ r  d$ \- \# T: u  MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;5 n" S) N. n) c
  uint32_t LinkedListNodeCounter;- F9 Q% S) _0 G
用于MDMA的列表模式。7 h, M. q9 k2 @6 ]" e1 N

% H1 F7 o- I0 P$ K, Y  HAL_LockTypeDef          Lock           
4 \- S, ]  j! W0 S0 f  __IO  HAL_DAC_STATETypeDef  State           
0 P; \! @2 f8 ~* g3 N1 Y8 a: D  __IO  uint32_t           ErrorCode      , G( h6 n' i0 J. F8 v2 o+ a
这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。
6 c6 _0 b4 n# K3 i
8 s$ B; X2 y: p; a61.3.4 MDMA初始化流程总结0 F( g* \# O; J( }6 Z
使用方法由HAL库提供:
4 B0 _" y2 r6 F8 O( r& P& j* n5 O
0 M" @- p$ m' C! F, O  第1步:基本的初始化。
; U! W" M8 X4 G% i# Z" V9 A6 W# F) j' {6 N% |
  函数HAL_MDMA_Init配置MDMA的基本参数。
$ t) o( @" P# n+ W' k& Q
' ^) m7 l8 t) p7 U  u" I/ \
# E6 w6 l9 g& Z5 k# ^  第2步:列表模式。
" m% L4 }8 }/ r0 C2 D1 n
& p6 R2 @3 ~) z/ @% D6 ^' |# O如果使用列表模式,用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。
* |8 W5 f; K8 \, j4 ?
1 m  ?; b6 g2 t# [* Z; H& T' h+ b% c9 {
  第3步:查询模式。
8 T  |: F2 Z+ b8 u* h" e
1 z: I& l7 L, G. `, }9 O( k  函数HAL_MDMA_Start 启动传输。
2 W* ~) Z' _2 y5 u; J1 [- i  函数HAL_MDMA_PollForTransfer 查询传输完成。
4 X3 f8 `; b- @& l  函数HAL_MDMA_Abort 终止传输。$ `& e6 A" ]7 `1 g+ w; U

& D  ^4 p! [; j, a; ]5 F+ F- _3 N. G& Z
  第4步:中断方式。' D3 n# r1 P! C3 c" s* o7 J8 u& `% w
5 f' H4 t: x( K6 A- g
函数HAL_NVIC_SetPriority设置MDMA中断优先级。) U2 v. f& C4 r
函数HAL_NVIC_EnableIRQ使能中断。
( ]9 I  z. \$ A+ @- s3 h 函数HAL_MDMA_Start_IT启动中断传输。3 a# @" `- S1 e% S
MDMA的中断服务程序MDMA_IRQHandler里面调用HAL_MDMA_IRQHandler,如果用户注册了各种回调函数,会在此函数里面执行。
6 J& _  \; k& i* j; G. d5 ] 函数HAL_MDMA_Abort_IT可以终止MDMA中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)* L& H# w+ p: O" U6 j. N

" a* q- r" }5 s, z3 P6 k# Q  J& _' r- @* K1 ]
  第5步:中断回调函数。
* S, q9 ]' X$ H7 T, S/ @# }5 E6 a! L9 d% l5 W0 b+ {1 p
函数HAL_MDMA_RegisterCallback注册回调函数,函数HAL_MDMA_UnRegisterCallback取消注册回调函数。' X+ W7 s2 }9 z0 r( H

& {* ?( B( L  C- w/ e$ x  XferCpltCallback            : 传输完成回调。% i* L1 V3 b5 B7 G9 ?
  XferBufferCpltCallback      : buffer传输完成回调。
' \" c: j1 D* ?0 t& q6 a# H6 |& W  XferBlockCpltCallback       : block 传输完成回调。
5 C% d8 {9 t) P; ^9 L( H  XferRepeatBlockCpltCallback : repeated block传输完成回调。  e! `" {2 N7 N3 n
  XferErrorCallback           : 传输错误回调。6 G" _" y- Y, s- j
  XferAbortCallback          : 传输终止回调。4 t! x3 C' D1 }+ J# U4 U# k. [

! o5 S1 m0 d% u& T# s$ {2 _( t2 m9 [5 n2 b% G, V, y" Y" _
61.4 源文件stm32h7xx_hal_mdma.c' T* T: V+ S- K) ^! |& C. @
这里把我们把如下几个常用到的函数做个说明:
# [. F8 x1 D+ ^! N5 @6 |% j! C6 I8 e) X1 z0 B
  HAL_MDMA_Init
1 ^* w3 E4 S6 a! I3 P  HAL_MDMA_Start_IT
8 `  l( K" c1 \$ D61.4.1 函数HAL_MDMA_Init
1 S" @, ^& S% i+ t+ A# e4 ^. i2 X. k3 H函数原型:7 ?+ d9 \1 s5 r
1 l: U$ s" E7 t& W/ t4 p
  1. HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)7 G0 k% f& g7 \2 y
  2. {/ O- C! y, I/ O6 Y
  3.   uint32_t tickstart = HAL_GetTick();
    : q- t& {5 B4 X8 E% |) k
  4. ; |6 M- J* H% [# s6 i0 x) Y
  5.   /* 检测句柄是否有效 */2 y8 L$ z; b) h5 t) }1 `
  6.   if(hmdma == NULL); M; P% h( _3 S  m6 v) |
  7.   {0 n6 @* \0 ~' I1 r6 U* S
  8.     return HAL_ERROR;
    & U) h: C4 v. `0 m& o* b" K
  9.   }
    * a$ j0 F  c* p: n0 Q. v( F8 s1 _
  10. ; g9 O% @  r4 K4 I7 \6 y
  11.   /* 检测参数 */0 Z# ^9 _& C" V$ S% X
  12.   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
    " o4 S: k8 `. E1 l4 A" j9 o
  13.   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
    0 t3 o& |1 \3 C; L3 R
  14.   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));5 z; X6 Q2 }: P
  15.   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
      n  ]. `7 Y9 h: [% A8 Z
  16.   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));" w5 T& |' d" [4 A' _$ `
  17.   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));2 M0 L, o) j$ T5 F8 P
  18.   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
    4 E" c: O7 j% M& G
  19.   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));# E# F* S! p" k. R" ^: L. J+ J
  20.   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));1 V3 |9 n: \* I" o8 x6 I' y
  21.   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));
    # L* X. I  A. v- V# W
  22.   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));( t; B; Q& L' ?- \
  23.   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));) w- Y* J6 F( Z
  24.   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));! s: v6 @4 q9 j2 |$ |8 P
  25.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
      W2 u5 u2 u9 x. r
  26.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset)); & O, ^0 D% s: y# p  N

  27. " T1 E; F" X' S- |# `# f
  28.   a) B( c* j8 ^2 W7 w6 I
  29.   /* 解锁 */7 f5 A9 {) J6 n1 Q
  30.   __HAL_UNLOCK(hmdma);
    # F) b5 F5 e' T" G& U; E

  31. 7 h4 _( X: O8 S5 A8 y% I  L
  32.   /* Change MDMA peripheral state */
    4 H6 z" x; _/ M. g/ J2 J5 @2 j& V
  33.   hmdma->State = HAL_MDMA_STATE_BUSY;
    # c, ]7 A; f9 }+ }6 [4 F1 b0 ]

  34. 4 v  [" p5 I! O
  35.   /* 禁止MDMA */3 B) d" [; A2 Y7 [4 d. l
  36.   __HAL_MDMA_DISABLE(hmdma);
    " a7 [6 ]6 G7 z: R/ r. m4 f
  37. $ O3 K/ g- M' q9 q5 m7 v
  38.   /* 等待禁止成功 */: x* o: x0 Y+ y7 ~, {  M1 n  O7 t
  39.   while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET)
    9 u+ P6 Z, C4 F' o7 T
  40.   {
    ) [% v) V  @' s; t& \
  41.     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)7 S' B7 L- Q* w
  42.     {
    ! `# J! o* {" z7 n- y
  43.       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;& r; R- P: ~- F9 j
  44. ( ?, D$ e6 C) t2 ]6 S& _' @
  45.       hmdma->State = HAL_MDMA_STATE_ERROR;
    ; `8 _7 ^6 x' `& N2 R% @
  46. 8 F; G( ]) H9 h/ F* l
  47.       return HAL_ERROR;, ^0 _2 w5 h/ g2 g$ S
  48.     }' j$ j( o: i% ]& d* G
  49.   }
    # O! v& ?$ ]2 P4 g0 u6 i% N: e7 g: o
  50. 3 ^" I/ {! P; v+ k. Y
  51.   /* 初始化 MDMA  */  w% n% J4 k% N& s% b8 r
  52.   MDMA_Init(hmdma);/ I& X2 D; L' J; q: s$ H( t

  53. " I3 q/ D: c% f; ^, ^4 E4 I
  54.   /* 复位列表模式相关设置 */* E: J6 \& ]6 d
  55.   hmdma->FirstLinkedListNodeAddress  = 0;
      K; g! r4 o* G; W& U
  56.   hmdma->LastLinkedListNodeAddress   = 0; 0 x% B& u" V" T2 K
  57.   hmdma->LinkedListNodeCounter  = 0;  
    ' ^: R, t" f7 y9 J
  58. ! z7 A9 h+ Z6 ~0 q/ n  D- ]
  59.   /* 设置无错误 */# i+ A9 v9 H5 d: f3 q! A( M
  60.   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
    + k. u: M, ^! b: }) M7 p) N

  61. 3 G3 P5 O9 a! Z6 C7 X( z3 m
  62.   /* 设置就绪 */
    : M, H5 t4 I  N0 Z
  63.   hmdma->State = HAL_MDMA_STATE_READY;
    ) a* A- @3 A& Y+ B) X
  64. 3 {) c9 v# W. c" T8 K
  65.   return HAL_OK;* W: [; y5 r. m% j$ C1 B2 O! ^; P/ h
  66. }
复制代码

3 z  }/ A1 M; |1 e: S; a7 i  r  F; A, r; G' L/ A/ l

! G: X& ^, _/ K  G! o3 Z/ P函数描述:+ \9 l* b. p$ r0 O
  D3 U" G' P! R( s
此函数用于初始化MDMA。
" m/ y( s& z+ ]* ~; I$ d! S7 y- C! }" d) }
函数参数:
. y. `6 Q* d1 a+ T$ @( |7 r
1 }. R, W0 u& Z0 s/ j5 ^4 M  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。
  @5 i, @$ W% ^! r0 |( e  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。- y* e4 Y8 T( T1 S7 g
使用举例:
' I8 C" R' a- S( t' z% X2 U2 N. ^  r0 l; h: t- F
  1. MDMA_HandleTypeDef  MDMA_Handle;
    - C8 I* E, k- U2 j, N

  2. ; }$ d/ ]0 P0 S' D
  3. __HAL_RCC_MDMA_CLK_ENABLE();  8 X( t: f) y7 T: \4 q- E7 p  G3 S9 e. ^
  4. 7 Y6 o: m/ e5 R& |6 T. E0 [
  5. MDMA_Handle.Instance = MDMA_Channel0;  0 V0 r; }. [- g8 E9 j" M# r6 H
  6. # ^$ Y9 m$ y; C' X! A2 n. M
  7. MDMA_Handle.Init.Request              = MDMA_REQUEST_SW;         /* 软件触发 */
      U! h# e/ }/ g
  8. MDMA_Handle.Init.TransferTriggerMode  = MDMA_BLOCK_TRANSFER;     /* 块传输 */' f$ m: G- a. O* b: G  Z5 w
  9. MDMA_Handle.Init.Priority             = MDMA_PRIORITY_HIGH;      /* 优先级高*/+ M5 n5 Y; g/ k4 e. [# K
  10. MDMA_Handle.Init.Endianness           = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */
    6 l! t6 i  b9 v) z% C
  11. MDMA_Handle.Init.SourceInc            = MDMA_SRC_INC_DOUBLEWORD;         /* 源地址自增,双字,即8字节 */- Y* e* J. S: E* Y4 |7 l
  12. MDMA_Handle.Init.DestinationInc       = MDMA_DEST_INC_DOUBLEWORD;        /* 目的地址自增,双字,即8字节 *// b, B& I+ \$ S6 @* D
  13. MDMA_Handle.Init.SourceDataSize       = MDMA_SRC_DATASIZE_DOUBLEWORD;    /* 源地址数据宽度双字,即8字节 */
    # r8 z$ N9 _( o; S  @, X
  14. MDMA_Handle.Init.DestDataSize         = MDMA_DEST_DATASIZE_DOUBLEWORD;   /* 目的地址数据宽度双字,即8字节 */
    0 K* H) ~  i' C; J% r, ^* x2 w
  15. MDMA_Handle.Init.DataAlignment        = MDMA_DATAALIGN_PACKENABLE;       /* 小端,右对齐 */                    
    ' H6 X  u! N  Q& l  S8 m& k1 @
  16. MDMA_Handle.Init.SourceBurst          = MDMA_SOURCE_BURST_16BEATS;      /* 源数据突发传输 */- ?) e. i1 B- I+ \4 M! U/ D
  17. MDMA_Handle.Init.DestBurst            = MDMA_DEST_BURST_16BEATS;        /* 目的数据突发传输 */) d3 G# _# \1 t. {' {, n7 L7 ?
  18. / G. \' T' W# i# T# R& k- K0 h
  19. MDMA_Handle.Init.BufferTransferLength = 128;    /* 每次传输128个字节 */
    $ T9 D( ~* s6 F" h9 a, j

  20. ) x6 X. q. S4 t
  21. MDMA_Handle.Init.SourceBlockAddressOffset  = 0; /* 用于block传输,地址偏移0 */
    , x3 x# I" a( }: Z
  22. MDMA_Handle.Init.DestBlockAddressOffset    = 0; /* 用于block传输,地址偏移0 */* Q' m; g+ S9 s  I+ e
  23. - `# L! \4 ]( u' M
  24. /* 初始化MDMA */
    6 \3 T% N0 [! R! Z8 c
  25. if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)
    3 |6 M& i- f6 Y& ^$ M! c, Z; q
  26. {
    + R! H# o+ {# ]9 H
  27.      Error_Handler(__FILE__, __LINE__);
    6 ?0 F  L& ], x- |/ V8 `" Y8 k+ q
  28. }
    % j9 w2 g1 C8 R0 D# q6 \
  29. 6 m8 [& [; b7 A  O4 V# W
复制代码
9 Y( \2 U+ P' Q3 Z: C
61.4.2 函数HAL_MDMA_Start_IT
5 Z2 Z0 A1 L6 `6 ~& `$ z函数原型:+ W! m: H! W' T$ x: n! O0 j
, M* L7 m0 n; W8 T
  1. HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
    , n$ e) _9 {; O% R
  2. {4 i* v' }3 O  q9 F/ n$ |
  3.   /* 检测参数 */
    : u, Z# W) Y* r6 B9 U
  4.   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
    1 [  T% {4 ^# O: o
  5.   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount));
    0 N$ C( {0 l4 v& v  G
  6. . W3 l: ~, a% G- ^
  7.   /* 检测句柄是否有效 */
    0 J; N# A9 o3 Y/ d% A5 c* i
  8.   if(hmdma == NULL)
    - P$ j' A1 _, e7 u1 r3 e
  9.   {$ u! |9 C- ~4 f& Q* h
  10.     return HAL_ERROR;4 \: x4 `% i9 n* {
  11.   }
    ( C6 f8 a, M6 g2 a* L

  12. ; Q" h  h* }: g) R$ |
  13.   /* 上锁 */
    ! u1 B0 R* |3 i' E* `
  14.   __HAL_LOCK(hmdma);$ K) n! C9 W3 }8 ^& K: g

  15. 8 l* P1 B$ q3 r% h
  16.   if(HAL_MDMA_STATE_READY == hmdma->State)/ ]2 }) A  f3 S% {1 G; T
  17.   {$ ^! l+ N+ C$ f" G
  18.     hmdma->State = HAL_MDMA_STATE_BUSY;( R2 q+ ]4 L' {2 |/ L9 T7 T
  19. . D$ X, S) O. ?1 E  G
  20.     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;     # a& C* x2 b- I* e5 k3 ~  T. c
  21. 8 ^' k! A4 E9 N  S3 A& R
  22.     __HAL_MDMA_DISABLE(hmdma);
    + D  j; m4 L. E) t3 i# ]' e. B
  23. # \5 {" O' `# r/ i
  24.     /* 配置MDMA */8 x! J, b' q' q3 ]$ l+ G: s+ S
  25.     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);& I1 F9 N) e9 S
  26. , M9 b: O2 n6 P
  27.     /* 使能传输错误和传输完成中断 */
    ! G! Z% B8 c$ `4 e3 s
  28.     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
    * ~/ n. X8 R, x% g+ D
  29. 9 m" O; B+ E8 w, Z, r. [- \8 `3 d
  30.     if(hmdma->XferBlockCpltCallback != NULL)
    ! b, ~% L4 V! W# T* X! ^- l+ I( F7 O$ u
  31.     {) b( v! Q# N! j* j5 {) j
  32.       /* 使能块传输完成中断 */+ K0 Y' G' m6 `6 L' e% d5 X1 d( C
  33.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);   
    6 K- f8 ^* V5 w6 F/ K
  34.     }. M/ o0 L" V' f) c

  35. % j" K; f: E4 \4 s, J& ?
  36.     if(hmdma->XferRepeatBlockCpltCallback != NULL)
    ' o6 J; \: r- `  L/ q8 m1 H
  37.     {& i  o3 L) ]. z$ D$ J7 S4 b# w
  38.       /* 使能多块传输完成中断 */      
    . L  ?( {7 Y7 H* e, x" I
  39.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);   
    - S! X% |+ }/ }" |, E' P
  40.     }  : l6 p( ?, }0 q8 `

  41. # C: y. G4 k8 [7 j
  42.     if(hmdma->XferBufferCpltCallback != NULL)
    3 R2 e. L) H$ l( ?8 Z
  43.     {
    . a) L! N5 {2 ~1 r- ?$ v! z  g
  44.       /* 使能传输完成中断 */4 [& w) [/ ^% G
  45.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);' {7 h. M4 Z" w2 h+ i
  46.     }- M1 v$ c1 q/ d: m3 N4 h
  47. ; c1 N  j& J! [6 j
  48.     /* 使能外设 */
    ) {( f- N: u% n; Z9 o
  49.     __HAL_MDMA_ENABLE(hmdma);
    ; u" g; C5 E* |1 b, L' ~+ B- [. e: e& O
  50. 4 I4 C' j2 U+ @" w1 b2 I0 R+ j; S& w
  51.     if(hmdma->Init.Request == MDMA_REQUEST_SW)
    + g, E! ~7 A* o: l+ f% s
  52.     {) W) `, n  h# T' s. v; ]
  53.       /* 使能软件请求 */( M7 y5 F* I" H
  54.       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;# s5 s5 |7 m4 }) u
  55.     }  
    , l& ~6 z  b: {% T+ R& \. ?, d
  56.   }
    $ S* j1 ]  I5 z
  57.   else' i0 m2 c- m3 f
  58.   {
    ; j. a' b2 |! \7 A
  59.     /* 解锁 */. X1 b8 X0 ~( \' D
  60.     __HAL_UNLOCK(hmdma);
    9 s" n! ~' g1 U) _$ M
  61.   I" b# F  t3 |5 S7 K  V
  62.     /* 返回忙 */
    0 T: _- y0 q" M- s" I
  63.     return HAL_BUSY;
    7 |" M1 A' I: l. j+ L& V
  64.   }( q: i$ x6 B! ~# V3 O

  65.   C. {( n& _* [+ R
  66.   return HAL_OK;
    6 y3 L% L! l$ V( V9 M) s+ g
  67. }
复制代码
5 U7 Q3 K! @' X

3 l" N, y1 a5 \; O+ w7 B; o3 C2 k3 K! L3 Y
函数描述:
6 F6 x. o/ h. L* {7 Z" Y: @+ P* S
2 A: F$ X6 ~! e4 Z+ {4 b此函数主要用于配置MDMA的中断方式传输。# b0 D0 \( o/ m8 J

* W+ y0 W% C, d" U8 T; N" H6 J, E+ T函数参数:
8 n) u& P1 x! V- S; N* B
# J  L+ ~3 e( ]# l* o- y! A4 ?' _  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。% V3 B6 e, _/ e1 g
  第2个参数是源缓冲地址。2 @+ r# m( U1 Q4 {( G
  第3个参数是目的地址。
! s1 J. ]; \, Q7 E) Q  第4个参数是传输的块大小,单位字节,范围不可以超过65536字节。
& I5 ^8 \! c# B$ ]" b8 r. b1 d( h  第5个参数是传输的块数,范围不可以超过4095块。
# L- R0 r$ [$ F% @/ L( N& z' h  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。  d! C) Z0 E, v/ y' J% `
使用举例:
5 h" H0 J; X' Y: \2 ~6 k7 J8 y, C% P' a2 ]: C6 [
  1. /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 */! k2 K* z5 X" E5 `
  2. HAL_MDMA_Start_IT(&MDMA_Handle, ! R* ]" z! \! U# S2 e; S6 w! B5 r
  3.                   (uint32_t)0x24000000, ' z" G" l  A9 m$ y; k8 Q$ i% C" h
  4.                   (uint32_t)(0x24000000 + 64*1024),
    & m. O  \0 M8 P3 l3 Z# O7 {1 s
  5.                   64*1024,
    ! u# a) k. K7 ]& C$ p) ~
  6.                   1);
    3 B: ~% U4 P$ X* g# S
复制代码

/ p" e* Y9 u4 b) a
- r: x  D0 w- `3 Y61.5 总结% U) D2 b' D; j' ]5 ^" A
本章节就为大家讲解这么多,MDMA功能用到的地方还是比较多的,后面的章节会为大家做讲解。
1 I) R' a  X# b% r% [, H; r
* Y" \  J) l8 B$ j5 t: b! E( e! f# }) m& I7 k* k+ A8 L
收藏 1 评论0 发布时间:2021-11-1 08:00

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版