请选择 进入手机版 | 继续访问电脑版

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

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

[复制链接]
STMCU小助手 发布时间:2021-11-1 08:00
61.1 初学者重要提示* m6 q2 p, @9 D$ I2 d8 M. B
  MDMA位于D1域,使用的64位的AXI总线,可以操作TCM空间(前面章节讲解的DMA2D,通用DMA和BDMA不支持操作TCM空间)。
$ \6 {7 b/ c4 w  对于本章节,重点要了解MDMA的buffer缓冲传输,block块传输和list列表模式的区别,详情见本章2.2小节。
  R1 }5 H' o* l' P61.2 MDMA基础知识
7 E2 w; f) U5 B- t7 x0 a/ @对于STM32H7的MDMA了解到以下几点即可:, ~1 ^( P- J9 o- `  G" i8 H# ]! T
* z, Z: `9 r6 u! S
  由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。# l6 V/ [# X6 X& T; R# C2 A2 v
  MDMA有两个主控总线接口,一个是AXI/AHB总线接口,主要用存储器或者外设访问,另一个是AHBS总线接口,仅用于TCM空间访问。
; J/ [$ g$ T) a; E. u* J7 x  有个16个通道,32个硬件触发源。每个通道都可以选择1个触发源,当然,也可以通过软件触发。, }0 O3 c4 g: ~
  16个通道的传输请求,既可以外设,也可以来自DMA1或DMA2; C4 z( Y! n$ R% e1 @9 _' i. z
  MDMA具有一个256级的DMA空间,被分为两个128级空间使用。
+ L% U; Z9 e% z% |: Y/ s  MDMA的优先级可通过软件配置,支持very high, high, medium, low四个等级,如果配置的优先级相同,则由channel的序号决定,channel0最高,channel15最低8 r* a" V- v3 l% O
  数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
3 O* Q- m2 r. V9 b7 u  B  源地址和目标地址的大小和地址增量可以独立选择。- W9 `9 h! g! T: G, d: [, }/ J* I+ g
  数据的打包和拆解是采用的小端格式。% b+ @( O* i. t7 {/ b* T2 t: |
  支持突发模式,最大可传输128字节。
: i+ c; S: w3 _% D) {. }, ]  当源地址和目的地址的增量和数据大小相同,且位宽小于等于32bit时,才允许TCM使用突发模式。6 N7 R, c  k& @3 m
61.2.1 MDMA硬件框图+ I. w0 |0 X4 H' R
认识一个外设,最好的方式就是看它的框图,方便我们快速地了解MDMA的基本功能,然后再看手册了解细节。框图如下所示:
9 d# A% M/ D8 E& a: u
  D/ `4 b/ _/ r' w
aHR0cHM6Ly9pbWcyMDE4LmNuYmxvZ3MuY29tL2NvbW1vbi8xMzc5MTA3LzIwMjAwMi8xMzc5MTA3LTIw.png
( l5 W3 j2 K* X9 p0 `
通过这个框图,我们可以得到如下信息:
( l. E& M: D/ M# T! k( E! a; @+ c& {3 s$ c7 U9 V
  mdma_it1 X: A8 D3 l* A
mdma的中断触发信号。
, ?' v4 }: u% j' l& x7 e8 i' |" D0 X. K. ]$ S' R+ C0 h
  mdma_str0到mdma_str31触发源
+ H5 t/ P5 Y( U4 h( ]" |mdma的输入请求。
& T+ Z* k1 G4 f" b9 W
+ e: z$ @" {4 x+ p' C  mdma_hclk+ q: {% G/ r! e* o9 Y
MDMA的HCLK时钟。
7 G6 P  n- j! X3 |$ t$ N, {/ t' e$ N" Z+ K- S% Q
61.2.2 MDMA块传输,缓冲传输和列表传输区别, W- Z$ |5 c/ }! l( u; m
初学MDMA,要搞清除MDMA支持的块传输,缓冲传输和列表传输的区别。$ c4 J9 N5 _4 C( M6 ]! i
4 T+ ~5 C- A% d' y( u* K
  缓冲传输(MDMA_BUFFER_TRANSFER)  z' L  }" u4 T3 G9 @7 m
这个模式主要用于QSPI,DCMI,硬件JPEG等外设上。每个请求都会触发BufferTransferLength(最大128字节)大小的数据传输,此大小由HAL_MDMA_Init调用的参数配置。
/ A# C1 h# K8 o) R4 v& I& ~
& i/ Y+ B! T# ?' w& v9 A
% ]. t4 A* B( k: c  K+ F/ j  块传输(MDMA_BLOCK_TRANSFER)$ }; f! h8 Y. p0 H
此方式与DMA1和DMA2的数据传输相似,每次请求,触发一次块传输,块大小由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。
, Y9 k& @6 c, ?. L* E
( K1 v& E9 D7 K  U# u
' o& O; M- k1 e+ V# ?/ P  多块传输(MDMA_REPEAT_BLOCK_TRANSFER)
8 i4 n2 S4 M( c! T0 a( ^( e5 d' o顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。
/ ^' v& N$ k$ Z; J) W" ~) c4 E2 P% C
( K$ i9 y- c2 o- C% o6 |
  列表传输(MDMA_FULL_TRANSFER)1 J* j7 O5 Q+ T- ?, |. r
这种模式可以方便的实现多种MDMA配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode),8 i7 \% T# x" s5 C* j2 h
7 m8 X( p$ O- N1 z  k0 [# D2 y! \
61.2.3 MDMA列表模式及其循环方式6 B9 [" k/ E( F5 v
列表模式包含多种MDMA的配置表,每个表包含一组完整MDMA配置。用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。. m& s, t# B& ?
. u! H6 s$ W& m6 i- {+ @8 H" I3 X" Z4 D
  使用列表模式的话,函数HAL_MDMA_Init创建的是节点0。* x6 s! d1 V" G- }: I1 s3 q
  使用函数HAL_MDMA_LinkedList_EnableCircularMode使能循环模式,注意是从节点1开始循环的,将节点1和末尾的节点相连,不包含HAL_MDMA_Init创建的节点0。! n$ z6 ^! p4 S# `
  节点0是初始配置,仅在初始化MDMA传输时使用一次,比如调用函数HAL_MDMA_Start_IT。
7 k6 o: a3 X9 z$ t  如果要禁止循环模式,可以调用函数HAL_MDMA_LinkedList_DisableCircularMode。( V' a. P6 s, G* q1 K9 C, U4 ?
  通过函数HAL_MDMA_LinkedList_RemoveNode还可以删除指定节点。
# E9 W' }3 ]% o# u61.2.4 MDMA的触发源4 |1 r+ `+ t3 h( V  x7 ], S
MDMA支持的触发源如下,主要包含DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:0 f4 p8 W, w( [: _" h5 u9 X

( M2 o( F9 b( J
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)
    : }. m3 l$ l- r8 S6 }+ j: Z4 H
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  ' W: u0 v$ B: F. N; U7 g1 i. K7 B2 T
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U) $ I# K2 I$ {/ J+ }; Y0 V# [% W
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U)
    " v& }. j' X( j9 T
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)
    ) H# I& T/ ]. \9 \# y
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U) / R) y8 k1 b5 G/ T' g
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)
    - c' G6 ~$ Y) q( L4 C
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U) 1 Z" K+ G- m2 \: d+ ?. R  H
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  
      a1 N1 e- p% G3 D  y
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)
    ' P1 y! m0 W- E! |9 Y8 U, O
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  5 `3 l+ }8 {2 G3 c9 u1 s! w
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU)
    ( B4 k, L# \1 b. Q
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU)
    # Y# J0 J1 F: O  c: F
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU)
    / T7 R# D6 k0 w) F
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  
    8 U) |1 k" n/ g6 i
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)
    . e# n" M4 D. Y9 Y9 ]  e6 F7 n
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  # Y! Z6 L; P1 g9 g1 P! G/ K
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U) - u) G4 y5 U& p  f' O( Z" J) c: F9 n' v
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U) / n' B+ \* Q! o# l! F% w7 e5 P) d* b
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U)
    3 _' p1 Y0 J" `- H0 p, s2 U
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  
    ( ?2 s5 a* v' K0 e- Z8 a5 [
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  4 k+ i- N1 N! n  _: T  ~
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  
    2 i1 o" J4 L8 K+ b. L# t
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)   x. y( O! E& d! f( I# @3 {! w' f
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U) 7 `1 {9 `: u3 \
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U)
    # ~) a6 M% L0 P1 C
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)1 T/ S3 [& ?8 _! S6 S: O
  28. ! N& g5 U  j/ A$ a  M$ f8 T. `
  29. #if defined(DSI)
    9 ~6 Y& }) l) f9 ]( J6 _/ y
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU) 1 i' m; D4 `9 B3 P5 t
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU) . S- I( w* D( ?
  32. #endif /* DSI */4 N4 @' K; m4 V# v  ]# ?: q3 A% T
  33. ! Y  u$ r! Y" K* R" a; T3 U! d
  34. #define MDMA_REQUEST_SDMMC1_ED_DATA      ((uint32_t)0x0000001DU)
    7 {5 |# S* n2 d0 v

  35. 3 j! p! @: B) |& S" W( F$ i
  36. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U)
复制代码

( m  B8 ~0 }/ _7 M: u" n
6 G& D0 z+ E+ G4 g: l8 T2 A6 [; q. N* T+ x  u) [
61.2.5 MDMA的软件触发方式6 S# C0 _; q- c: M" M( Z
MDMA配置为MDMA_REQUEST_SW软件触发时,可以通过函数HAL_MDMA_GenerateSWRequest产生触发请求,使用此函数要注意以下两个问题:9 n/ x% \. F0 a" x7 [* t6 z. W

# h7 n4 n) d) p5 A. G: S  如果传输结束或者传输还没有启动,调用此函数会返回error。; s% T8 m$ [. S6 ]1 H; a. \- Z
  如果传输还在进行中断,调用此函数会返回error,这次请求会被忽略。; S* J# F0 y" H$ X: e) r
7 u1 K0 m6 D, u
: F+ w: V3 V' C8 }/ f
应用示例1:
# ~1 N$ B7 @3 `% b% r1 R/ o/ B+ g& a( r# W0 D! x7 A
  MDMA配置为MDMA_BUFFER_TRANSFER模式,软件触发。' @( `9 ?3 y" B. R- Y( w' z
  注册回调函数HAL_MDMA_XFER_BUFFERCPLT_CB_ID。
$ d: ^; f/ ~- }2 V  调用函数HAL_MDMA_Start_IT会触发一次BufferTransferLength长度的数据传输。
) P/ O/ {0 r( ]4 s  传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest启动传输。
8 t! p$ a+ w) U- u( h  w8 z
* z9 c7 @/ I* C
7 S' v' V" q+ }$ _; G* x应用示例2:
9 s7 ~5 q+ r# s% i/ e  l' G8 a' G/ v) L5 f! Y4 L3 O8 L8 [
  MDMA配置为MDMA_BLOCK_TRANSFER模式,软件触发。# v9 \6 c( e* b  G4 n6 I' v
  注册回调函数HAL_MDMA_XFER_BLOCKCPLT_CB_ID。# ^6 {3 w0 }( t' I
  调用函数HAL_MDMA_Start_IT会触发一次块传输。7 K( O( a& Z' O/ m- q4 u$ n. V3 }
  传输结束会进入回调函数,用户可以再回调函数里面再次调用HAL_MDMA_GenerateSWRequest再次启动传输。
. S& r# Q  W) I61.3 MDMA的HAL库用法2 x' b: j5 M, N; L% Z
MDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。9 m: p$ }& ~$ b, y: r; c: |4 U- B
0 @. Z1 v' b/ W4 [- ^% a* ~! c
61.3.1 MDMA寄存器结构体MDMA_Channel_TypeDef和MDMA_TypeDef2 L, \4 ~( m+ p0 e
MDMA相关的寄存器是通过HAL库中的结构体MDMA_Channel_TypeDef和MDMA_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:
4 N: a" Z( v# O6 s" E" r
5 I, u& X8 F0 y' v; \2 H# ^# q" Z
  1. typedef struct, _: j) a# L. K0 ]% g0 b6 w
  2. {
    # y1 g7 ~, f" ]: L2 e& j2 D
  3.   __IO uint32_t  CISR;      /*!< MDMA channel x interrupt/status register,             Address offset: 0x40 */& n1 z& |+ P" W+ t& a2 t$ T
  4.   __IO uint32_t  CIFCR;     /*!< MDMA channel x interrupt flag clear register,         Address offset: 0x44 */9 j" S. [7 {1 [9 t' T  \
  5.   __IO uint32_t  CESR;      /*!< MDMA Channel x error status register,                 Address offset: 0x48 */% Z/ f7 c8 z; }8 U* Y  d
  6.   __IO uint32_t  CCR;       /*!< MDMA channel x control register,                      Address offset: 0x4C */ . e% n7 z( Q& f4 P9 D) }3 K; K
  7.   __IO uint32_t  CTCR;      /*!< MDMA channel x Transfer Configuration register,       Address offset: 0x50 */
    ( _+ `: O7 q* `+ ]8 Z5 C: Z
  8.   __IO uint32_t  CBNDTR;    /*!< MDMA Channel x block number of data register,         Address offset: 0x54 */
    ! P; R: X/ Y# j
  9.   __IO uint32_t  CSAR;      /*!< MDMA channel x source address register,               Address offset: 0x58 */
    ( q* B' ~- C1 D' P7 K" n; C, Z& i( m
  10.   __IO uint32_t  CDAR;      /*!< MDMA channel x destination address register,          Address offset: 0x5C */
    # G2 ~' V5 N( f# u  u; a/ W# i, t- E
  11.   __IO uint32_t  CBRUR;     /*!< MDMA channel x Block Repeat address Update register,  Address offset: 0x60 */
    1 q1 P' d5 b% O
  12.   __IO uint32_t  CLAR;      /*!< MDMA channel x Link Address register,                 Address offset: 0x64 */
    + D- D9 g9 L0 P4 I
  13.   __IO uint32_t  CTBR;      /*!< MDMA channel x Trigger and Bus selection Register,    Address offset: 0x68 */
    * j- e. o2 @3 o( ?
  14.   uint32_t     RESERVED0;   /*!< Reserved, 0x68                                                           */  
    2 U3 K* g9 q; y2 ~6 F! y4 r
  15. __IO uint32_t    CMAR;     /*!< MDMA channel x Mask address register,                Address offset: 0x70 */" q7 @2 O) P1 k# F  q! L: A7 T
  16. __IO uint32_t   CMDR;      /*!< MDMA channel x Mask Data register,                   Address offset: 0x74 */
      _; z0 {4 l' [3 Z& K' u- r8 c( \
  17. }MDMA_Channel_TypeDef;1 H! o7 b' L# Z# J: B% D: k

  18. 5 d* q8 D6 }0 a
  19. typedef struct2 ]5 I" V/ v8 o3 p/ G
  20. {0 l0 T) v- M7 y6 P2 i
  21.   __IO uint32_t  GISR0;   /*!< MDMA Global Interrupt/Status Register 0,          Address offset: 0x00 */# I) {: w+ X/ ?% Z/ W
  22. }MDMA_TypeDef;
    6 G1 V, J; ^4 v5 O; e2 G/ W+ C
复制代码

' k( s$ e/ ]4 Z2 x+ E
3 z( N, V- N2 e7 C" }2 H4 ^, J: L__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:5 q, |' S# l) {5 T
  1. #define     __O     volatile             /*!< Defines 'write only' permissions */
    : z1 L, @# `6 ~. ^
  2. #define     __IO    volatile             /*!< Defines 'read / write' permissions */
复制代码

& S9 }7 W9 T6 Q% Z% H1 J( Q: j下面我们再看MDMA的定义,在stm32h743xx.h文件。
9 w2 d9 P* W4 s
' D" J$ d( g. Q2 ^  Y
  1. #define PERIPH_BASE           ((uint32_t)0x40000000)
    : G* M: d: G( _5 }
  2. #define D1_AHB1PERIPH_BASE    (PERIPH_BASE + 0x12000000)
    / ~& c4 _& h- w1 Q
  3. #define MDMA_BASE             (D1_AHB1PERIPH_BASE + 0x0000); f  l3 z: L0 X! ?. S
  4. 2 R1 s$ _8 B/ t+ U# G9 y+ `
  5. #define MDMA_Channel0_BASE    (MDMA_BASE + 0x00000040)
    ! T  J5 Q- f! G. j5 e
  6. #define MDMA_Channel1_BASE    (MDMA_BASE + 0x00000080)
    / M5 ^4 r0 ~0 b3 C5 h
  7. #define MDMA_Channel2_BASE    (MDMA_BASE + 0x000000C0)0 `7 P2 {/ `2 ]& i
  8. #define MDMA_Channel3_BASE    (MDMA_BASE + 0x00000100)4 M' O, p: j5 X7 w3 ?
  9. #define MDMA_Channel4_BASE    (MDMA_BASE + 0x00000140)
    1 [% J3 U. x9 }0 f, M
  10. #define MDMA_Channel5_BASE    (MDMA_BASE + 0x00000180)
    5 o/ ?; r2 H/ N3 T5 W- M( r( a- j4 v
  11. #define MDMA_Channel6_BASE    (MDMA_BASE + 0x000001C0)7 d/ y. G' B9 E5 l  {
  12. #define MDMA_Channel7_BASE    (MDMA_BASE + 0x00000200)4 E$ w# l2 A% `0 t% Y
  13. #define MDMA_Channel8_BASE    (MDMA_BASE + 0x00000240)
    : W5 q* e5 t; n( V; G
  14. #define MDMA_Channel9_BASE    (MDMA_BASE + 0x00000280)
    0 M8 j" b8 \# e- C: l
  15. #define MDMA_Channel10_BASE   (MDMA_BASE + 0x000002C0)
    4 ?7 I0 f4 y6 L1 p; y  k; [
  16. #define MDMA_Channel11_BASE   (MDMA_BASE + 0x00000300)6 B' M5 M5 ~1 _$ y; C- |
  17. #define MDMA_Channel12_BASE   (MDMA_BASE + 0x00000340)
    ' j2 r# I9 W: v1 l4 B7 U! e
  18. #define MDMA_Channel13_BASE   (MDMA_BASE + 0x00000380)) ~! C9 J$ D2 c6 l: w
  19. #define MDMA_Channel14_BASE   (MDMA_BASE + 0x000003C0)7 ?0 S" r) r6 H& a' \
  20. #define MDMA_Channel15_BASE   (MDMA_BASE + 0x00000400)
    * K. F0 k0 h0 T. V# x6 D

  21. , Y7 A( r0 q; q7 C2 T" Q* w5 G
  22. #define MDMA                ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000
    , u& C* v: e, {3 |9 v
  23. #define MDMA_Channel0       ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)& r- y* n% n- P3 z/ @
  24. #define MDMA_Channel1       ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE), ^8 G0 V2 i; a" ]. ?: V
  25. #define MDMA_Channel2       ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)2 L" B+ S2 m4 n3 J% y4 I- ]' u
  26. #define MDMA_Channel3       ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)$ }8 f0 [# o$ O& d0 x/ M
  27. #define MDMA_Channel4       ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)6 ], L. G& ~9 X3 Q& M$ ]) ]. t  R& O8 C
  28. #define MDMA_Channel5       ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)
    6 V" j% J4 h2 \7 T
  29. #define MDMA_Channel6       ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)
    # o6 i% s. t+ }+ }  q8 f+ y
  30. #define MDMA_Channel7       ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
    # u1 E6 m6 E& f8 w; x
  31. #define MDMA_Channel8       ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)8 o6 C+ j7 ?) L( X) I
  32. #define MDMA_Channel9       ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE)
    , [$ |' n! ]. W0 J8 B& l% D, l
  33. #define MDMA_Channel10      ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)
    8 \+ m7 L: I1 y7 G  g6 Q
  34. #define MDMA_Channel11      ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE)
    4 P: \# t8 O3 s5 ~  H+ K3 O! ?; H$ N8 y% t
  35. #define MDMA_Channel12      ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)
    8 A# p( a5 _) |9 n, C: K* f
  36. #define MDMA_Channel13      ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
    5 }  S. B9 m6 Q* T% ?0 |! `
  37. #define MDMA_Channel14      ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)
    & r: x9 _: Y! `% u& t" O1 G
  38. #define MDMA_Channel15      ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
复制代码
! |2 H- S9 R' I3 v2 m4 b3 w, y

# B) E% A. [( S8 S0 e/ p) P9 D' f' {% K5 u7 d
我们访问MDMA的GISR0寄存器可以采用这种形式:MDMA->GISR0 = 0。* g# }) h6 m! m2 a5 H
5 Y: u; P7 r- q, Z$ A3 s: |" |3 c
61.3.2 MDMA的参数结构体MDMA_InitTypeDef
. B4 B' v+ O  H2 j此结构体用于MDMA的参数配置,具体定义如下:( m. h( \, o5 w$ M
0 O; H* ^0 m) Q6 D) ]8 X
  1. typedef struct
    # {, u2 P8 r6 M# z% n6 p
  2. {$ V: X3 X7 i6 M5 F
  3.   uint32_t Request;                                                
    ' p9 I/ U% L9 J/ [8 X4 J, a
  4.   uint32_t TransferTriggerMode;                                    
    ; ~9 A) N( W2 H+ X
  5.   uint32_t Priority;                                                     
    & k, |; c  e: m7 t1 F. ^- C
  6.   uint32_t Endianness;                                                
    $ x7 z* e/ D  }1 Y  @0 w0 @2 V
  7.   uint32_t SourceInc;                                              5 |) H& b3 I! d* C: D, m
  8.   uint32_t DestinationInc;                                        # [+ r$ o0 }# _3 I. H
  9.   uint32_t SourceDataSize;                                         
    ' W6 t- [; G6 o( W& f& U7 q0 p. k
  10.   uint32_t DestDataSize;            
    8 x. l* t9 @) v8 o$ ?5 v
  11.   uint32_t DataAlignment;          & l1 r5 E4 Y7 w; I2 w& |! e& o
  12.   uint32_t BufferTransferLength;    6 s! C: p* g( @+ a  O4 Y3 N6 g
  13.   uint32_t SourceBurst;                                            2 U4 Z; w( t9 q% d. u
  14.   uint32_t DestBurst;               
    ! L+ L' ~0 _9 P0 M) J/ P2 {8 e# b
  15.   int32_t SourceBlockAddressOffset;                                                                            9 ?3 i) i# E3 q" n+ x
  16.   int32_t DestBlockAddressOffset;         p2 z9 ]' X: f* E7 |
  17. }MDMA_InitTypeDef;
复制代码
: P8 i! t$ R; _% l4 P+ o3 v
2 |* T- b( ^% R; \) _5 c- m

- [1 Y* N0 f: p# b8 q' b下面将这几个参数逐一为大家做个说明:9 P! c# h. I. c
7 p/ A, z' z0 ~$ d: a* d
  uint32_t Request/ g+ i" L$ G1 k5 ~2 L& m
触发MDMA的请求源,支持请求源如下:
6 X! g: X9 H4 W$ _8 V
4 W$ R9 P+ |; l% n# d
  1. #define MDMA_REQUEST_DMA1_Stream0_TC      ((uint32_t)0x00000000U)  8 t) J+ y& U) h
  2. #define MDMA_REQUEST_DMA1_Stream1_TC      ((uint32_t)0x00000001U)  1 j. H7 Z% j3 g2 s! G4 ~
  3. #define MDMA_REQUEST_DMA1_Stream2_TC      ((uint32_t)0x00000002U) % V% h: n9 s# b
  4. #define MDMA_REQUEST_DMA1_Stream3_TC      ((uint32_t)0x00000003U)  / E9 f% o: n, y8 n: S
  5. #define MDMA_REQUEST_DMA1_Stream4_TC      ((uint32_t)0x00000004U)  
    0 g1 i" n! x3 O) W# z( m& X( B
  6. #define MDMA_REQUEST_DMA1_Stream5_TC      ((uint32_t)0x00000005U) 1 z3 U5 V4 y, ^+ R
  7. #define MDMA_REQUEST_DMA1_Stream6_TC      ((uint32_t)0x00000006U)  3 t1 y( j- S& V2 ^. W
  8. #define MDMA_REQUEST_DMA1_Stream7_TC      ((uint32_t)0x00000007U)  5 w% ]$ G1 Z. N9 p8 g
  9. #define MDMA_REQUEST_DMA2_Stream0_TC      ((uint32_t)0x00000008U)  ) b4 g7 ~5 m8 C2 V
  10. #define MDMA_REQUEST_DMA2_Stream1_TC      ((uint32_t)0x00000009U)  
    7 |8 k9 Y9 F& O" l& r/ H
  11. #define MDMA_REQUEST_DMA2_Stream2_TC      ((uint32_t)0x0000000AU)  8 Q, e/ B) [3 \
  12. #define MDMA_REQUEST_DMA2_Stream3_TC      ((uint32_t)0x0000000BU)
    6 }- M# j; E! n6 T+ H# ^1 b
  13. #define MDMA_REQUEST_DMA2_Stream4_TC      ((uint32_t)0x0000000CU) $ \3 I: q6 d8 v
  14. #define MDMA_REQUEST_DMA2_Stream5_TC      ((uint32_t)0x0000000DU)
    . ~3 n+ r2 E2 |
  15. #define MDMA_REQUEST_DMA2_Stream6_TC      ((uint32_t)0x0000000EU)  9 g- e5 K; \8 F: C3 Z/ O. k2 r
  16. #define MDMA_REQUEST_DMA2_Stream7_TC      ((uint32_t)0x0000000FU)  ' A1 y; \" j) s+ R8 S% ^* y0 S
  17. #define MDMA_REQUEST_LTDC_LINE_IT         ((uint32_t)0x00000010U)  % B( V: K1 E+ C
  18. #define MDMA_REQUEST_JPEG_INFIFO_TH       ((uint32_t)0x00000011U) 0 q% J" \# I- g- ]5 `1 L
  19. #define MDMA_REQUEST_JPEG_INFIFO_NF       ((uint32_t)0x00000012U)  
      c1 X6 }8 t" F- z1 j& k
  20. #define MDMA_REQUEST_JPEG_OUTFIFO_TH      ((uint32_t)0x00000013U)  / H) ?6 o* g+ ?6 D' H- {  H
  21. #define MDMA_REQUEST_JPEG_OUTFIFO_NE      ((uint32_t)0x00000014U)  
    , Y  V3 V  t% P! }8 A! F
  22. #define MDMA_REQUEST_JPEG_END_CONVERSION  ((uint32_t)0x00000015U)  7 ?& y( w1 S6 J6 Z7 O
  23. #define MDMA_REQUEST_QUADSPI_FIFO_TH      ((uint32_t)0x00000016U)  
    3 L3 q! F; `* G
  24. #define MDMA_REQUEST_QUADSPI_TC           ((uint32_t)0x00000017U)  . Z: y6 j, o( G1 f6 x  v
  25. #define MDMA_REQUEST_DMA2D_CLUT_TC        ((uint32_t)0x00000018U)  6 H  [4 J: ~- e/ O. G% C4 i
  26. #define MDMA_REQUEST_DMA2D_TC             ((uint32_t)0x00000019U)  
    4 O! M4 [  Q1 b- h; w. Y
  27. #define MDMA_REQUEST_DMA2D_TW             ((uint32_t)0x0000001AU)  
    3 r3 e' C: b* L, K0 k6 M
  28. / g# N/ T7 [( l1 o: w2 a
  29. #if defined(DSI)
    6 Y7 `& i" t4 y* u$ L0 U5 {( l( ]
  30. #define MDMA_REQUEST_DSI_TEARINGE_FFECT   ((uint32_t)0x0000001BU)  + P& g2 e! {+ [) B4 W; X0 g
  31. #define MDMA_REQUEST_DSI_END_REFRESH      ((uint32_t)0x0000001CU)  ) ?/ m- I5 w9 w- C
  32. #endif /* DSI */0 d! A: y- G8 S& x
  33. & i7 u7 K7 {1 F  z2 \3 H' v
  34. #define MDMA_REQUEST_SDMMC1_END_DATA      ((uint32_t)0x0000001DU)
    & b+ m$ E' a" e2 {; F5 y( D
  35. #define MDMA_REQUEST_SW                   ((uint32_t)0x40000000U)
    ! B+ l7 @" j" J* A
复制代码

3 D6 j" c+ a' o; ~
6 v5 |2 O4 C) w! [4 ^# G3 g5 [  uint32_t TransferTriggerMode  H. x! i, C& R. ^: t+ T* G3 r$ \
MDMA的传输模式,具体支持的参数如下:1 O: h$ P8 q$ L2 Z( j7 U0 w
  Y/ o- ^. ~0 b7 M: n, ?
  1. #define MDMA_BUFFER_TRANSFER          ((uint32_t)0x00000000U)      /* 缓冲传输 */7 W$ g# K% T& d  \, Z* J4 Q! ]
  2. #define MDMA_BLOCK_TRANSFER           ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */
    9 ~4 y% o8 @. N' e$ R
  3. #define MDMA_REPEAT_BLOCK_TRANSFER    ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */, L: L1 V# c/ t$ m6 B: q2 e
  4. #define MDMA_FULL_TRANSFER            ((uint32_t)MDMA_CTCR_TRGM)   /* 链表传输 */
复制代码

; U9 m2 v( |* _2 D: r9 x' M! z- s$ v/ U3 e3 q% ^4 g

' c  Q7 U! o( b8 g  uint32_t Priority
6 l4 N- y, N4 u" G: x& g8 c# @5 KMDMA通道的优先级设置,具体支持的参数如下:
3 v9 K2 S8 J6 s( g$ S/ U( v. I7 K2 B2 S* V4 {
  1. #define MDMA_PRIORITY_LOW             ((uint32_t)0x00000000U)     . `5 N- V; G7 m
  2. #define MDMA_PRIORITY_MEDIUM          ((uint32_t)MDMA_CCR_PL_0)  
    ; x7 p  ]9 R! w3 H6 l
  3. #define MDMA_PRIORITY_HIGH            ((uint32_t)MDMA_CCR_PL_1)  
    2 B" v% I  ?. J
  4. #define MDMA_PRIORITY_VERY_HIGH       ((uint32_t)MDMA_CCR_PL)   
复制代码

# e! @0 Y# p  E$ J% P* @* k7 F; |( c3 m4 Z$ q( _

& a: g, P5 n5 _$ k2 }  uint32_t Endianness' u, `- g% c: A( l
MDMA数据传输格式,具体支持的参数如下:
3 A2 C+ _; T3 v, s; r' q% }
5 _8 f" W7 \& b- D
  1. #define MDMA_LITTLE_ENDIANNESS_PRESERVE          ((uint32_t)0x00000000U)  / @: `) x; B0 @3 S' t
  2. #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_BEX)  
    9 D' d. S9 U. S5 `6 ~, k! \. W3 T
  3. #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX)
    ! N& _( S: M5 @% Z# ~& ^/ j
  4. #define MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE     ((uint32_t)MDMA_CCR_WEX)  
复制代码
" q+ |# \6 a7 D1 n  ^% n5 ]+ ^

8 u- e; }/ f; ~" }5 Q5 ]( U7 xMDMA_LITTLE_ENDIANNESS_PRESERVE:正常的小端格式。
1 {4 i* C# I* e# D! Q3 l, [& ]7 S1 i3 u2 r* p+ V0 a
MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE:以半字为单位,交互高低字节。
( B  _& l1 k' p7 f+ ^) A- t/ j4 y2 N/ b/ p. V9 |0 U8 y' Q
MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE:以字为单位,交互半字。1 v+ T8 g/ y5 C( e
5 _' s2 z  P8 k8 f( r, Z
MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE:以双字为单位,交换字。
+ H/ ?  X' V" l6 U4 \0 p* _6 g+ S$ F1 j, O' G
  uint32_t SourceInc
; P# y; B& O: D* s5 t. z! S  {- SMDMA源数据自增或者自减模式,具体支持的参数如下:$ Y0 Y% c5 H6 R. D
  1. & A3 G0 O$ t8 N4 I
  2. #define MDMA_SRC_INC_DISABLE      ((uint32_t)0x00000000U)                                    7 ~$ N# w- _/ {: W' H/ D7 |
  3. #define MDMA_SRC_INC_BYTE         ((uint32_t)MDMA_CTCR_SINC_1)                                6 [4 R# d, F) P% P$ ~" p
  4. #define MDMA_SRC_INC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)
    + u* A2 Y1 m- ?. d
  5. #define MDMA_SRC_INC_WORD         ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1)
    0 F( H4 E. B. S. f# O" U8 z3 ?
  6. #define MDMA_SRC_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS)  0 ]& O) O  L. _5 L
  7. #define MDMA_SRC_DEC_BYTE         ((uint32_t)MDMA_CTCR_SINC)                                 
    ) n7 W8 \! _4 u# n, W' H; r
  8. #define MDMA_SRC_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0)   3 X/ W0 k. o2 q; y: L6 h$ y
  9. #define MDMA_SRC_DEC_WORD         ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1)   
    . l( u; o& p: K
  10. #define MDMA_SRC_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS)   
复制代码
# {: J$ j8 J- Z

6 p5 v. v& ]+ h5 [5 _, `
$ q  U' y6 E& d  DestinationInc
" }2 o" G0 o7 I& K; A' RMDMA目的数据自增或者自减模式,具体支持的参数如下:
6 p4 E  P8 n9 k- s: F- d
5 y, w  u! l4 K* E
  1. #define MDMA_DEST_INC_DISABLE      ((uint32_t)0x00000000U)                                    
    8 ~; C4 d, S- z
  2. #define MDMA_DEST_INC_BYTE         ((uint32_t)MDMA_CTCR_DINC_1)                              
    & k6 N+ L% q, _3 k/ J
  3. #define MDMA_DEST_INC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)3 ~2 }( z; H( T, _( e" S1 s
  4. #define MDMA_DEST_INC_WORD         ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1)
    8 M0 j% b8 E1 ~  l2 [
  5. #define MDMA_DEST_INC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS)   
    , r4 d5 e) C# G5 j, w
  6. #define MDMA_DEST_DEC_BYTE         ((uint32_t)MDMA_CTCR_DINC)                                2 m. A/ l! S1 ?
  7. #define MDMA_DEST_DEC_HALFWORD     ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0)   # E5 _! [. @1 d! S- R: `& L
  8. #define MDMA_DEST_DEC_WORD         ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1)   : S6 {1 Q- r2 s6 u; ?
  9. #define MDMA_DEST_DEC_DOUBLEWORD   ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS)  
复制代码

# \3 O# V1 s( l9 j1 X7 ~0 T
/ _/ V( J5 g; u
) @* V/ B1 H+ T2 {8 I  SourceDataSize
  U# a8 ?" n: U& `) ^* S9 \2 U5 F+ cMDMA源数据带宽,具体支持的参数如下:
5 E  A5 T2 J! M$ B
/ a+ y& v& ~/ }, a3 m; @  A
  1. #define MDMA_SRC_DATASIZE_BYTE        ((uint32_t)0x00000000U)        8 Z) j0 W8 \  u3 @- n, v" ~/ O
  2. #define MDMA_SRC_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_SSIZE_0)     5 e( t# W' ]4 a1 k9 i
  3. #define MDMA_SRC_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_SSIZE_1)  
    * P7 b6 e( |- M8 F( v
  4. #define MDMA_SRC_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_SSIZE)   3 R3 M9 h4 a5 E% S
复制代码
7 L* n! p$ J! D4 v# p( L2 a
+ g6 s4 n. R" i6 M3 _5 m7 [
  DestDataSize( \$ y0 G( G. Z: {  q" n
MDMA目的数据带宽,具体支持的参数如下:
/ o  A, G, D+ |0 H; f7 t' z
& B; B: g8 p5 F* v( T
  1. #define MDMA_DEST_DATASIZE_BYTE        ((uint32_t)0x00000000U)        
    0 s( t( a- ?* y5 o4 V% B1 X
  2. #define MDMA_DEST_DATASIZE_HALFWORD    ((uint32_t)MDMA_CTCR_DSIZE_0)   
    : j+ A6 `' f; ~# w0 S( W
  3. #define MDMA_DEST_DATASIZE_WORD        ((uint32_t)MDMA_CTCR_DSIZE_1)  
    ) Q5 E# c- x+ }
  4. #define MDMA_DEST_DATASIZE_DOUBLEWORD  ((uint32_t)MDMA_CTCR_DSIZE)     
复制代码

4 q/ s% |9 m  s$ J! @9 l% ?# O: }- V  r9 F# I: d( l5 l& D
& w; N- g: ]; X: X4 _2 l' _
  DataAlignment
" ?$ @7 q8 w5 Y. p6 |* S& JMDMA的填充/对齐设置,具体支持的参数如下:
* M& G8 r- ]7 t$ P. J7 t* J
  1. #define MDMA_DATAALIGN_PACKENABLE        (uint32_t)MDMA_CTCR_PKE)     
    3 k4 @' i$ V1 K4 m% @- X2 J  Q
  2. #define MDMA_DATAALIGN_RIGHT            ((uint32_t)0x00000000U)     
    ' B2 m7 x( P' R( f
  3. #define MDMA_DATAALIGN_RIGHT_SIGNED     ((uint32_t)MDMA_CTCR_PAM_0)  4 P8 f. ?- U- O) b4 e
  4. #define MDMA_DATAALIGN_LEFT             ((uint32_t)MDMA_CTCR_PAM_1)  
复制代码

' e( q* F2 W; O) y3 h+ ~5 O+ P4 Q# ^# V$ S) ~

1 }  \0 C( \; M9 |0 V5 ]MDMA_DATAALIGN_PACKENABLE:( h" |9 f1 a, n3 ~

8 C( m$ _0 C  c1 D9 L将源数据封装/解封为目标数据大小。所有数据均右对齐(采用小端模式)。
! T" |* R2 ^! s+ c0 ?, E6 g# N$ ?% C5 X2 v" x# k( s+ }4 V
MDMA_DATAALIGN_RIGHT
1 m, e1 k, t5 O' x1 h
* d: O% |+ `% `+ x* c右对齐,用 0 进行填充(默认值)2 z9 Y& D! `4 l* j

8 E, {7 [3 H- j+ hMDMA_DATAALIGN_RIGHT_SIGNED- K- R) s- P- I4 c3 m! e/ j3 p
5 V1 @. v- Q% [+ z' @
右对齐,符号扩展. V; E4 L; y# p

6 z2 e9 H0 i: U! KMDMA_DATAALIGN_LEFT4 }, n, R- h/ C

. c) Z9 ?/ G  r) g# G左对齐(用 0 进行填充)
8 }: e4 U& `: b3 P3 m
# E9 S: T# V9 N  r8 ]9 f# t  BufferTransferLength* Y9 l: \& \/ g2 E: H
单次传输长度设置,范围1-128,单位字节。/ |) B. {0 j# h! \( O8 y' X& ]0 P, V! ~

8 j7 x+ ?# y% @. X" l  SourceBurst) ?' {& B( @' [$ b) \
源数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下:
7 o7 U8 y& P7 ]2 g+ [6 t# |! q# R( S% [! g# \3 |- I
  1. #define MDMA_SOURCE_BURST_SINGLE        ((uint32_t)0x00000000U)                                      
    3 N2 G* A! ]' S: R5 y7 K/ k; B' k
  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)
    ; e* Y7 a1 H. N0 Y
  3. #define MDMA_SOURCE_BURST_16BEATS       ((uint32_t)MDMA_CTCR_SBURST_2)                              
    : M0 b6 b- M- c, q& @0 p
  4. #define MDMA_SOURCE_BURST_32BEATS       ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_2) , x0 w$ c: {( l
  5. #define MDMA_SOURCE_BURST_64BEATS       ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2) - W6 h; y, j# H
  6. #define MDMA_SOURCE_BURST_128BEATS      ((uint32_t)MDMA_CTCR_SBURST)   u9 N1 V1 P8 \  W; ~2 @) T# K
复制代码

6 c( u) d  X$ |0 ]4 X
8 \. ~) z) }! I9 ]; M6 W  DestBurst- Q6 A: \* M) R6 A. K
目的数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下
: U# [" v. D4 b/ u+ [
  1. #define MDMA_DEST_BURST_SINGLE        ((uint32_t)0x00000000U)                                       ( {( A  T3 ^! E6 ^- ?
  2. #define MDMA_DEST_BURST_2BEATS        ((uint32_t)MDMA_CTCR_DBURST_0)                                 9 P8 y8 z& w2 N3 k, N* q. b4 ~, `
  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) " J! J  L" N! X1 d9 Q
  4. #define MDMA_DEST_BURST_16BEATS       ((uint32_t)MDMA_CTCR_DBURST_2)                                 6 s& b/ n7 J7 j0 V4 U
  5. #define MDMA_DEST_BURST_32BEATS       ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_2)  
      x$ X: |+ O: x/ ]8 m
  6. #define MDMA_DEST_BURST_64BEATS       ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2) # M7 j4 o* v7 i1 g7 D+ R6 t
  7. #define MDMA_DEST_BURST_128BEATS      ((uint32_t)MDMA_CTCR_DBURST)  ; s5 a2 B8 q: m
复制代码

8 ~  J6 c1 V3 d% h1 }  SourceBlockAddressOffset
. E& u: x! v1 @用于设置源地址端数据偏移。
4 O# x2 C  Q5 M1 w8 T+ V# z8 g/ _
+ C+ X8 I4 M" L6 [4 w  DestBlockAddressOffset
- i9 Z1 B5 v$ _. {: p  s用于设置目的地址端数据偏移。! n! N/ y* {9 S( u+ e, J- B6 ?6 x& x

3 L9 Y: X0 ?' Y- Q" f$ z6 T# _61.3.3 MDMA结构体句柄MDMA_HandleTypeDef
: W0 W" _5 Y( e3 PHAL库在MDMA_Channel_TypeDef和MDMA_InitTypeDef的基础上封装了一个结构体MDMA_HandleTypeDef,定义如下:
3 g9 a7 V! t9 m! O; K! c5 J8 t9 x$ C9 F" }) @3 H/ M. H
  1. typedef struct __MDMA_HandleTypeDef. ^. P/ F' X& }
  2. {1 M- k  ^0 v" `0 G
  3.   MDMA_Channel_TypeDef *Instance;                                                                                                                                                                                             
    % I# n7 ?7 b0 P8 c* K( y) ]. m
  4.   MDMA_InitTypeDef      Init;                                                              1 Q, D) ~$ \4 ^7 k8 [( W; t
  5.   HAL_LockTypeDef       Lock;                                                                  
    $ }7 Q* {2 T% X
  6.   __IO HAL_MDMA_StateTypeDef  State;                                                           
    5 o0 d6 h/ c, t. h! W4 ?
  7.   void                  *Parent;                                                               4 i* y2 ?& u! u
  8.   void                  (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);           " x7 X: F+ c6 E' V
  9.   void                  (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     ( d7 W9 k/ M, ~+ T
  10.   void                  (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);      % u& p$ Y/ G4 l. g' J
  11.   void                  (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);5 p. d5 V4 x7 N3 u, Q7 l- k& l
  12.   void                  (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);           
    7 A5 F; m/ o4 i$ v0 ~( t
  13.   void                  (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);           
      O; v7 N& D0 M! \- u" W
  14.   MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;                                             
    0 |1 Y* w- e) U2 `7 Z
  15.   MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;                                             + V+ b4 H0 f( m
  16.   uint32_t LinkedListNodeCounter;                                                                                                                                                                                      
    - O+ _4 {8 R6 c/ f- C9 T
  17.   __IO uint32_t          ErrorCode;                                                            
    9 n9 |) k5 C5 }& i7 ^
  18. } MDMA_HandleTypeDef;
复制代码

7 A) o3 F( x/ O  V6 @& {2 q下面将这几个参数逐一做个说明。
+ M& \( ^* y  ~1 U% L( E6 ~' O6 `0 A; M8 s6 G, [9 W
  MDMA_Channel_TypeDef  *Instance4 l0 Z4 t! [$ ~6 A3 t& |& _
这个参数MDMA通道的例化,方便操作寄存器,详见本章3.1小节。/ _( x8 D7 G/ K
; e: Z7 J: H: M
  MDMA_InitTypeDef      Init5 ^( S  }: J/ p' _$ Q( G% O3 {9 t
这个参数用于MDMA的通道参数初始化,详见本章3.2小节。# r0 m4 O5 @. ~6 X' }* T
8 G2 G. I3 l# j- T4 M0 g7 E
  void   *Parent
! D2 d# E+ L- o/ ~用于记录MDMA关联的外设。3 \3 z" G8 r1 E5 ^6 H- u8 l

' `0 ^0 f& J. S+ g- f+ A- k" G( o    void   (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);          - h1 L5 n! {$ f/ }. ?" U& H
    void   (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);    ( M0 W7 [& b- M1 H2 s
    void   (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);     
7 a$ c7 b! W' M" c# C# `    void   (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);- `7 j. T! q. |5 ?' i% {
    void   (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);          * r7 ]; I% u5 q  a
    void   (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);   - i4 Q: O/ g# A6 n+ g1 z
MDMA的各种回调函数。    : i8 [' V& y* v8 T

1 M7 e) A7 f. a& F8 [0 m8 ]  MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;
' W9 ^" s& r* X' j, l6 G/ e8 r  MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;
/ T7 v2 E6 H6 R  uint32_t LinkedListNodeCounter;
6 J! s7 K, L2 z* R' P用于MDMA的列表模式。
& P% ]  O/ o, P% |4 v' h5 ?& L: g. i) H* a. p7 s
  HAL_LockTypeDef          Lock           
. ~0 _; E# c2 _0 a  __IO  HAL_DAC_STATETypeDef  State           
6 M  _, o/ Z$ g0 E8 E/ N" m2 f  __IO  uint32_t           ErrorCode      
5 t* \3 G( B5 z3 h这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。
& T: z" l# @) ?0 B/ M* v- W( I
( X0 ^6 V: g  n& G9 R61.3.4 MDMA初始化流程总结
! \) s$ j. o' {% U  S3 P4 ~" i使用方法由HAL库提供:
  {4 w$ e- t  S- ~
- N5 h% P: f9 V( f3 A5 \9 J0 U- F  第1步:基本的初始化。
! R9 i; B1 R  ?- Z0 ~. q$ N
! i7 z  t& o/ n1 v6 U! t* t) ^5 t  函数HAL_MDMA_Init配置MDMA的基本参数。- P5 }) Z% x: [. C' a
+ Z0 ~5 i; |* a& ~  l* E/ R
9 P/ _; ^) x: V0 G# s' S) x
  第2步:列表模式。
$ a1 J& v" [7 g; d$ b" L8 F8 A& R, x. l% [) G5 C0 {, q* K) e% s. ]
如果使用列表模式,用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。% b4 T" A% J% R9 g* A  t, e
7 X" N6 Z, H- r7 M# K7 M
& f% S/ U+ A. ~/ p5 `
  第3步:查询模式。
, t0 }, l/ y1 B; K$ K: R: v/ O. `9 h6 W  V: O* _; E4 a: k
  函数HAL_MDMA_Start 启动传输。8 k8 f) \; v8 }+ V
  函数HAL_MDMA_PollForTransfer 查询传输完成。
" J" U; d  N: L  h' G  函数HAL_MDMA_Abort 终止传输。
- k' R& _* [7 {, B8 l5 ^4 U* ~3 P, S* V1 a1 L

* z* l5 n9 @3 ?9 S( ^* t/ F  第4步:中断方式。
% `: y$ S  I- p, e+ @+ Z/ L
0 Q4 J! G: V' A/ Q1 ~ 函数HAL_NVIC_SetPriority设置MDMA中断优先级。
6 ^4 {4 l4 A; c/ f0 @% W 函数HAL_NVIC_EnableIRQ使能中断。
' _" H8 g+ a& @$ l, Z- D) c% Z/ X5 v 函数HAL_MDMA_Start_IT启动中断传输。0 y( f" x  a. @9 C
MDMA的中断服务程序MDMA_IRQHandler里面调用HAL_MDMA_IRQHandler,如果用户注册了各种回调函数,会在此函数里面执行。
8 i7 J: u$ E& a$ O 函数HAL_MDMA_Abort_IT可以终止MDMA中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)
6 S, c) f$ m8 J; q; ?- k
1 e. O0 ^5 S4 ?! K6 |2 q, J" z) t3 E1 |0 I  s' y7 [3 v0 s  ^5 }- }
  第5步:中断回调函数。3 {9 F+ E' X0 H8 J9 v7 B% p
6 ?/ _8 h, J& @- Z9 P2 \0 b
函数HAL_MDMA_RegisterCallback注册回调函数,函数HAL_MDMA_UnRegisterCallback取消注册回调函数。
' Z, N& v# u! m& i$ ^$ m( N' w& J; W- `5 S* Z, b
  XferCpltCallback            : 传输完成回调。
1 i6 \5 N. l$ x5 @4 H  XferBufferCpltCallback      : buffer传输完成回调。
0 j8 ]' C  `  t7 `; ?4 Y0 _" X; u  XferBlockCpltCallback       : block 传输完成回调。
5 q' |. ~1 r, i' h1 }# d  XferRepeatBlockCpltCallback : repeated block传输完成回调。
7 c$ i. k8 G; q# n; C) X3 a) ]4 G  XferErrorCallback           : 传输错误回调。+ h9 |, y6 m6 E' P  q6 a
  XferAbortCallback          : 传输终止回调。$ j* X. \1 o& f) J% Z

# e  A, M$ |  t6 n3 |4 A
7 b7 g5 J- F* ?( G: Z2 D61.4 源文件stm32h7xx_hal_mdma.c
; f% c  u8 E) [, \5 ^- X这里把我们把如下几个常用到的函数做个说明:
! P: g$ c. g* u5 Q
( C' {8 V! _5 d  P8 [  HAL_MDMA_Init
0 m: l/ ]. X. g3 P1 W; \4 J  HAL_MDMA_Start_IT
  [  L. i4 @% ~; y: }7 w61.4.1 函数HAL_MDMA_Init  D  g; J; b, z5 F: q
函数原型:# Z4 k, p0 b, ^7 ~& h, n# v

% X# w; T$ b, }, I, Q
  1. HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
    & f- y2 Q1 l$ b+ z) t5 Z
  2. {
      u  n' I+ `) w( o' K1 S7 A; o
  3.   uint32_t tickstart = HAL_GetTick();
    ( S  ^+ {9 N! C& C
  4. ; G8 L( h. H4 Q' B% T7 T/ r
  5.   /* 检测句柄是否有效 */
    ) Z0 A* R$ m) }6 ]3 D7 B
  6.   if(hmdma == NULL)
    , s9 N9 H% x* P+ G. B7 [: m
  7.   {
    ) ]/ A  c+ u1 x- |5 O
  8.     return HAL_ERROR;' L' a# E8 J6 m$ U' z' }2 x
  9.   }" M8 K1 n% O' y

  10.   W. m( E% j7 P- U- J1 i/ m
  11.   /* 检测参数 */" z( i1 ]+ L2 F
  12.   assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
    7 \7 b6 k, l- D: g6 P2 B( n
  13.   assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));! `+ ^+ R! \; a& ~: F, |
  14.   assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));
    4 i( C( d, V9 F7 J/ s
  15.   assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));
    & P3 Q+ w7 H$ d9 Y
  16.   assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
    ; Q& H, g% Q, k7 E& |: F& w: {0 b
  17.   assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
    0 G$ Y$ K: v- ?# t' t, F
  18.   assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));% B, x! z+ l: O5 `8 ?) C
  19.   assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));- L. \9 z2 c) N
  20.   assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));3 @9 a. J- s4 o/ u0 P+ ~' [
  21.   assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));" R7 n' S& Q0 K+ ^' }
  22.   assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));
    7 I. F& ^8 A. P% N
  23.   assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));! c+ I) ~  Q! O. ^+ F( j1 q, X6 D
  24.   assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));1 g1 ~( {+ ]3 B* y& n
  25.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
    ' q6 y! _* x- n1 Q, |1 `# T
  26.   assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset)); " q& O9 E0 N+ |2 l- W

  27. 9 `1 \  E5 X9 I+ M1 d

  28. + J  f0 ?. i- j
  29.   /* 解锁 */
    1 d% |, ~1 z' R6 ^0 `4 h4 J8 s
  30.   __HAL_UNLOCK(hmdma);- E* m% L, R8 y$ x! F: y0 Z

  31. / ~+ @4 ^; }) x
  32.   /* Change MDMA peripheral state */1 k: o3 ~. X3 J
  33.   hmdma->State = HAL_MDMA_STATE_BUSY;
    : Y% N% Q, r5 e, R
  34. * ?8 _5 J$ C3 E7 q( t# ?4 w
  35.   /* 禁止MDMA *// O; N  e; k8 |) o8 H; ?  a+ w
  36.   __HAL_MDMA_DISABLE(hmdma);. L' J# P! S; H) M  `
  37. 4 C! o/ O0 _) @  e' s9 G
  38.   /* 等待禁止成功 */
    # _5 K, E) F5 v! ?% x; L+ q& u$ a
  39.   while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET)
    - q* \- J  d: S) Z5 r$ S
  40.   {
    , A2 ~4 p  ]% A! [) ^' A# e
  41.     if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)* u) a: u5 z5 F" S7 j
  42.     {
    ) }. E: G, ?! E0 B% F5 s4 D
  43.       hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;& x- a- U: [# A  E3 D

  44. $ H0 A  e, p! c7 O2 m, L
  45.       hmdma->State = HAL_MDMA_STATE_ERROR;
    4 W: [/ ~8 p4 D, m# F6 f
  46. : K( o- O, p' `% N* R# K) `
  47.       return HAL_ERROR;0 o* l3 n  r9 a! ?( \/ y9 \
  48.     }
    ; q6 U# {" c5 p$ n- X
  49.   }
    / b2 ]2 s3 I4 C. j# }2 j
  50. 1 [% X" g7 ?. v4 x; F" N
  51.   /* 初始化 MDMA  */
    5 }; ?9 j1 X3 k, ]* W
  52.   MDMA_Init(hmdma);
    8 Q9 @5 K6 _$ A/ v4 Z7 n

  53. , w6 r" M6 ^5 [$ F4 y
  54.   /* 复位列表模式相关设置 */
    $ a# B2 [8 B3 U* l. d9 J
  55.   hmdma->FirstLinkedListNodeAddress  = 0;
    ' j' Y; m* z8 E% |  D7 Z: E$ p. q
  56.   hmdma->LastLinkedListNodeAddress   = 0; / O# t2 b2 o5 D7 n
  57.   hmdma->LinkedListNodeCounter  = 0;  3 L& z! `  Z, K3 {

  58. ) c* W6 F8 q( L0 }; K$ B
  59.   /* 设置无错误 */
    9 U5 O3 z( q) p2 E# Q9 U5 x$ b
  60.   hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;- y6 }2 Z  H# V4 ~. \
  61. 8 T! E' j5 G: _% {1 ?& E
  62.   /* 设置就绪 */
    3 i( Q7 o5 d! ^8 s$ ?! @' q
  63.   hmdma->State = HAL_MDMA_STATE_READY;  b. s4 a3 i: L. q9 i4 z
  64. * R6 A$ O  b! E5 V+ g! E
  65.   return HAL_OK;/ ]2 A4 j, @. `
  66. }
复制代码
0 U0 G( c; Y1 ~* U$ A0 T- [4 Z+ d

" J3 N/ w9 V7 y0 n
; A/ P2 `6 m8 n, a, _( k函数描述:* ^: i# ]: O3 D1 Y. O4 P! a

. _- l& z3 ^! ]( l8 {% E此函数用于初始化MDMA。8 Q# d0 D+ e5 q3 {3 ]. A  k

* C3 w% \5 x: B( n6 R/ s函数参数:
( u1 U0 B3 |- Q2 V/ c# T( g% h0 N% x9 h( e, u0 {% }
  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。5 U- S5 i  H1 f
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。. V% T, t/ g" K2 ^
使用举例:
5 {" e$ m( w/ D" K- u5 ~- x" x
3 E! M. }, o& {$ H% g
  1. MDMA_HandleTypeDef  MDMA_Handle;6 N0 ]. s! R0 [# M7 n6 F

  2. 3 F, l4 i3 b& m8 ~2 ]
  3. __HAL_RCC_MDMA_CLK_ENABLE();  
    % }3 J7 g6 J  i8 P$ g1 ]

  4. - F% p- Z2 p0 b; j3 \
  5. MDMA_Handle.Instance = MDMA_Channel0;  ! z2 j" L  t' x0 `

  6. 1 P1 F6 C7 w2 ~" b3 C% G' Q3 y
  7. MDMA_Handle.Init.Request              = MDMA_REQUEST_SW;         /* 软件触发 */0 f3 E+ m+ n) c( e
  8. MDMA_Handle.Init.TransferTriggerMode  = MDMA_BLOCK_TRANSFER;     /* 块传输 */, ^6 @$ M/ O9 \3 r, b1 o4 |
  9. MDMA_Handle.Init.Priority             = MDMA_PRIORITY_HIGH;      /* 优先级高*/, V1 \$ [, d) K! @9 ~( z/ ]
  10. MDMA_Handle.Init.Endianness           = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */) \* j! `2 `8 W( n' A
  11. MDMA_Handle.Init.SourceInc            = MDMA_SRC_INC_DOUBLEWORD;         /* 源地址自增,双字,即8字节 */
    % ]9 `9 v7 _# m
  12. MDMA_Handle.Init.DestinationInc       = MDMA_DEST_INC_DOUBLEWORD;        /* 目的地址自增,双字,即8字节 */
    , R" m) _1 r. L/ O
  13. MDMA_Handle.Init.SourceDataSize       = MDMA_SRC_DATASIZE_DOUBLEWORD;    /* 源地址数据宽度双字,即8字节 */& v- o) |9 y" U  ]/ z- c& b
  14. MDMA_Handle.Init.DestDataSize         = MDMA_DEST_DATASIZE_DOUBLEWORD;   /* 目的地址数据宽度双字,即8字节 */
    2 @3 B# v" e* L9 I1 Y" @
  15. MDMA_Handle.Init.DataAlignment        = MDMA_DATAALIGN_PACKENABLE;       /* 小端,右对齐 */                    
    / \& ^! w6 x+ C% l3 K+ S0 e
  16. MDMA_Handle.Init.SourceBurst          = MDMA_SOURCE_BURST_16BEATS;      /* 源数据突发传输 */
    * c% \: F" w' H. a
  17. MDMA_Handle.Init.DestBurst            = MDMA_DEST_BURST_16BEATS;        /* 目的数据突发传输 */' n3 {- y) f6 n0 c

  18. 6 V2 {. l% t% L# N5 u5 t9 s
  19. MDMA_Handle.Init.BufferTransferLength = 128;    /* 每次传输128个字节 */0 J3 b3 @; L& ]* P) w4 M
  20. 4 j7 r( ^/ l3 L
  21. MDMA_Handle.Init.SourceBlockAddressOffset  = 0; /* 用于block传输,地址偏移0 */6 G, o* ~7 C- d( }& G; U$ k! B
  22. MDMA_Handle.Init.DestBlockAddressOffset    = 0; /* 用于block传输,地址偏移0 *// Z: h. S" K9 A* L! F) x) |+ N: X/ Z. Z
  23. % T# Q" L3 W% O2 S  }- b
  24. /* 初始化MDMA */
    ) J$ H$ h7 h* X9 G4 L* ?1 s
  25. if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)- J9 c8 P- H* F: Z) s$ w
  26. {7 |$ P( o0 z" o. ?4 x5 W4 C- a
  27.      Error_Handler(__FILE__, __LINE__);. M) @  e5 {* d( y
  28. }
    - k1 U4 @9 Y2 u- i/ ~6 d
  29. ; K7 y- K2 C7 `1 ?5 O7 h5 z3 h
复制代码
# F" H- x* a  s4 B
61.4.2 函数HAL_MDMA_Start_IT1 [" ?3 b: Q4 x: O
函数原型:
1 x4 r" o- w0 Q, l1 P4 e/ _! U. W( r4 `8 x4 H. Q( `( X
  1. HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)
    4 N' o5 S. t/ p$ @0 \
  2. {
    + f* x5 ]. ]+ ~! J+ z) Y; `- L; N6 v
  3.   /* 检测参数 */
    2 _* x' i, T5 J  S; l5 E
  4.   assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));. j. S3 e3 f/ a
  5.   assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); 3 v% c+ [  U4 ?) X! G  @, c4 t, {
  6. & Y5 }- d' L. y+ @% F0 |- U
  7.   /* 检测句柄是否有效 */$ |/ D0 p/ ?: O# x
  8.   if(hmdma == NULL)
    # h& P1 w) r' X7 p2 e1 X! o7 h! E( K
  9.   {# M3 s5 y0 z, F% w3 O6 [
  10.     return HAL_ERROR;
    6 ^8 O+ @3 A- O* A! n' z
  11.   }
    : x% Q6 O* ?6 I" j7 g6 k: b' r
  12. ) {7 x$ J& _8 ]- x8 L
  13.   /* 上锁 */$ U( p) j# E( A% c+ ^
  14.   __HAL_LOCK(hmdma);7 j. K; H9 e4 F4 ]

  15. , n8 Q& r( P7 i( K, l6 F
  16.   if(HAL_MDMA_STATE_READY == hmdma->State)6 p; @* z* V8 m) d$ U  y1 [
  17.   {
    ! x7 {7 i6 S+ y4 }8 P
  18.     hmdma->State = HAL_MDMA_STATE_BUSY;
    ) K8 w5 }, {$ c  J

  19. 3 N0 O5 u1 |! w  E/ \1 m
  20.     hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;     # @3 w; \7 f' n/ c$ @; y
  21. 0 R2 Z' k& E+ |( G( Z
  22.     __HAL_MDMA_DISABLE(hmdma);$ W6 A4 a' Y  h( Z  {4 K8 Q3 o

  23. 4 G8 ^4 i# @4 h' S/ U4 q  H
  24.     /* 配置MDMA */
    ! @9 j  q+ t! Y. x
  25.     MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);, {/ m( [* |+ S6 T

  26. 1 S- Z2 U8 S* w+ d% p0 |
  27.     /* 使能传输错误和传输完成中断 */4 Y4 R+ g, k* ^8 j7 T$ B4 L8 Z
  28.     __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));' k8 @5 }) h2 l6 t

  29. 6 o! b: n/ Z- Z, M, }) F# v
  30.     if(hmdma->XferBlockCpltCallback != NULL)$ m9 i4 A2 A2 V3 M* a
  31.     {
    ) ^1 R8 m" p. B$ K3 c7 a
  32.       /* 使能块传输完成中断 */' e* D1 ^* X- l4 Z$ j, K
  33.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT);   
    2 Y; e9 p/ S5 ?" p2 b% Q
  34.     }1 H: M% s- V0 O" _. G' j$ T! U* _

  35. 6 ^# }# |$ `4 n
  36.     if(hmdma->XferRepeatBlockCpltCallback != NULL)
    ( f' J( T8 V* b$ v& c
  37.     {* n# k9 g" }1 O( h; Y
  38.       /* 使能多块传输完成中断 */      - R& S& _0 q' m5 x0 h) Q3 Z* F6 `1 Y: x
  39.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT);    ! A, H2 c" `3 L. L! }4 K
  40.     }  
    : u: y4 z+ |' w

  41. 2 y) v5 B! {7 P6 X
  42.     if(hmdma->XferBufferCpltCallback != NULL)
    * ^# d8 z) X8 C( E5 t! p& ^
  43.     {: H5 O) g9 f/ l# h# S! R
  44.       /* 使能传输完成中断 */
    8 a0 _( X+ x2 m" o# P: Q
  45.       __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);1 D7 g! f0 c" X% w
  46.     }
      E3 \* V2 c7 A* O$ g% m1 P* W6 h
  47. 8 g- y- j$ m' k1 o$ c2 ]
  48.     /* 使能外设 */
    ' `; |& c& j3 ~! R; B  C" K
  49.     __HAL_MDMA_ENABLE(hmdma);( e6 T# K# E3 d' u: G) V7 U7 X

  50.   L0 e1 R8 e! T
  51.     if(hmdma->Init.Request == MDMA_REQUEST_SW)! U8 j4 t& x0 _' ]) l* B
  52.     {
    # u/ J$ g5 V1 m; ^$ c
  53.       /* 使能软件请求 */& o, w0 I" `% G% @
  54.       hmdma->Instance->CCR |=  MDMA_CCR_SWRQ;
    0 j; M0 r8 w7 f' m3 k- l: F4 r
  55.     }  0 y/ v0 Z! v& j. P2 Y: c
  56.   }
    ! F, Z  ^4 E) V4 W5 X9 b) l, |
  57.   else/ e& U1 ?. O/ D
  58.   {
    9 y( y' j6 K3 N# E" b7 O9 j& ~
  59.     /* 解锁 */
    5 {2 r7 z8 C0 y
  60.     __HAL_UNLOCK(hmdma);  }& C3 O) {/ p" M% y

  61. ! Y* `+ D1 e, d7 W2 f3 d
  62.     /* 返回忙 */
      {1 c2 r/ L* c2 V) X( ^
  63.     return HAL_BUSY;
    0 k8 F2 c# T& T$ s; A. b' q4 D! A# Z
  64.   }
    + t" y9 d) V3 U- _% n' k: n/ _6 d
  65. 2 Y6 l/ _0 t, U+ l; W) f$ o9 l
  66.   return HAL_OK;
    8 p/ J: u* `% V% q; k2 |
  67. }
复制代码

* x2 N: E3 P+ R4 x6 @' d/ ?+ m" i; q. o

6 ?$ D; _0 ]) Z函数描述:
$ c+ Q5 |% `9 d% w6 r: Z  l' K7 i1 G! Z) `2 l
此函数主要用于配置MDMA的中断方式传输。- u" z$ h: e3 x9 _, M# F  N* `' D4 p

4 a7 a5 b6 ]) W& _2 Y; N函数参数:& [0 f- c; [8 Z/ B2 u% k

% ~% E. R7 Z3 E+ \  第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。! s* ~' c5 Y' Y& E1 R) ?
  第2个参数是源缓冲地址。2 r! t* p3 S! {+ O" V- e* j
  第3个参数是目的地址。
2 ~* J2 z- f5 U, G3 C) r  第4个参数是传输的块大小,单位字节,范围不可以超过65536字节。+ p' a$ \& V7 S
  第5个参数是传输的块数,范围不可以超过4095块。/ C! F# H0 x6 j* ?" F
  返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。. Y/ m" ^5 A; L
使用举例:
. Q: W: Z4 Y' Q. ~" n
4 ]* T6 m+ y3 ~; o( M& p# C7 i
  1. /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 */
    / V8 c6 F( z$ ?3 W1 j. R, W/ k
  2. HAL_MDMA_Start_IT(&MDMA_Handle,
    - F1 n% `# m5 _  Y
  3.                   (uint32_t)0x24000000,
    ) ~5 ]3 S! h+ y% n, ?( k
  4.                   (uint32_t)(0x24000000 + 64*1024),
    * ^& o; u2 z# r% o; S
  5.                   64*1024, + R$ G& O* o/ v
  6.                   1);5 R. V4 @+ E/ A8 q' b0 ]
复制代码

$ B: a+ \- p& F% F$ Y/ c" N
/ P3 O4 I  m, Y' p2 ?61.5 总结9 N  l6 R# k! |$ o( m$ w& c
本章节就为大家讲解这么多,MDMA功能用到的地方还是比较多的,后面的章节会为大家做讲解。
/ ]* w3 [4 @0 t& m5 C5 b2 `3 J
1 O' C# s* e' V  r& v" h4 D% B; W" {! ~
收藏 1 评论0 发布时间:2021-11-1 08:00

举报

0个回答

所属标签

相似分享

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