61.1 初学者重要提示# n* T% a3 q$ Y$ I/ X& [2 H: e8 E( V
MDMA位于D1域,使用的64位的AXI总线,可以操作TCM空间(前面章节讲解的DMA2D,通用DMA和BDMA不支持操作TCM空间)。. s7 J) s, Q% K6 w: w3 H
对于本章节,重点要了解MDMA的buffer缓冲传输,block块传输和list列表模式的区别,详情见本章2.2小节。
( _# @0 a8 Q- j# ^, s+ e61.2 MDMA基础知识
* H# B0 c5 i1 }4 O4 b) O( }) A对于STM32H7的MDMA了解到以下几点即可:
: U6 {2 t2 K" c- m3 B) n- b# Q( n3 I
- D3 O9 U9 r# f5 Y6 m; e 由于总线矩阵的存在,各个主控的道路四通八达,从而可以让DMA和CPU同时开工,但是注意一点,如果他们同时访问的同一个外设,会有一点性能影响的。
0 s4 _5 }) `' v4 k$ F2 | MDMA有两个主控总线接口,一个是AXI/AHB总线接口,主要用存储器或者外设访问,另一个是AHBS总线接口,仅用于TCM空间访问。+ j; k( R* v; r* ?
有个16个通道,32个硬件触发源。每个通道都可以选择1个触发源,当然,也可以通过软件触发。
2 r; y& _9 ?" R/ P [8 j; \ 16个通道的传输请求,既可以外设,也可以来自DMA1或DMA2! Y- z) K0 @. u) l! E2 z h
MDMA具有一个256级的DMA空间,被分为两个128级空间使用。
" Q& Q$ i0 [+ Q. k j0 C) Q MDMA的优先级可通过软件配置,支持very high, high, medium, low四个等级,如果配置的优先级相同,则由channel的序号决定,channel0最高,channel15最低
1 Y6 j; q- X; i+ {/ ]7 V 数据宽度可以设置字节,半字,字和双字。源地址和目的地址的数据宽度可不同。
7 d+ w" N5 y# S1 G, n) s: M 源地址和目标地址的大小和地址增量可以独立选择。* M% q" w( m& j8 ~& x* k; E, o. v) H
数据的打包和拆解是采用的小端格式。( J( K: s% `% L2 E8 A2 H
支持突发模式,最大可传输128字节。
: o3 L1 {" j! z' X* x3 W+ k 当源地址和目的地址的增量和数据大小相同,且位宽小于等于32bit时,才允许TCM使用突发模式。) {; V- ?! H5 g+ x+ x5 P3 B; Q& w0 K! D
61.2.1 MDMA硬件框图
7 _9 {. r/ h1 K+ n, L$ k. P1 B认识一个外设,最好的方式就是看它的框图,方便我们快速地了解MDMA的基本功能,然后再看手册了解细节。框图如下所示:5 [& [0 ~! g7 i
! g$ M9 _% }( Q9 o0 n5 t8 u, p# [
通过这个框图,我们可以得到如下信息:! R, v& p4 n7 \5 r
5 t2 d" N2 P; _3 ?
mdma_it
- I, Z/ g" P. c% M7 k7 C; _' c5 nmdma的中断触发信号。; r# n7 Z- Y& C$ f. d
. c: ]/ `* j2 o$ N% u4 U: e) w/ c mdma_str0到mdma_str31触发源
" C1 w, Y0 E7 v# r" Omdma的输入请求。: M: J/ C4 Q# E' V: @5 g
$ g7 R9 i0 V) ?& N4 A mdma_hclk* g" T {, c6 L6 j
MDMA的HCLK时钟。1 v$ o" h; s& @
! T9 A- q4 O- V
61.2.2 MDMA块传输,缓冲传输和列表传输区别: p( A/ s& t* z/ {( G+ M# ^! _
初学MDMA,要搞清除MDMA支持的块传输,缓冲传输和列表传输的区别。
* r7 {( C% H' U% K# q9 I R& W# Q% j$ f
缓冲传输(MDMA_BUFFER_TRANSFER), i2 ^* A8 j1 G% Q/ _
这个模式主要用于QSPI,DCMI,硬件JPEG等外设上。每个请求都会触发BufferTransferLength(最大128字节)大小的数据传输,此大小由HAL_MDMA_Init调用的参数配置。6 g4 V$ H" Q* e1 w
, Q0 V$ l0 R! X% |: Z5 T4 o9 W- D- L3 C
块传输(MDMA_BLOCK_TRANSFER)0 `; r5 N y4 h8 Y
此方式与DMA1和DMA2的数据传输相似,每次请求,触发一次块传输,块大小由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。5 p& j- ^; Y: s1 E$ }: _
' X4 m# w1 G4 |# I$ h3 w8 m% o, t2 Q
多块传输(MDMA_REPEAT_BLOCK_TRANSFER)4 r% }- t+ [+ R: n
顾名思义,多块传输就是执行多次块传输,每次请求,触发多次的块传输,块大小和块数由 HAL_MDMA_Start/HAL_MDMA_Start_IT定义,或者列表模式里面的参数。8 L) h4 Y' m& t
/ v! p' E8 k% v1 ?
$ N$ d( ~7 y0 j6 C( f9 T
列表传输(MDMA_FULL_TRANSFER)
' N4 g5 K2 _) x这种模式可以方便的实现多种MDMA配置进行切换,轮番实现,而且可以实现列表的循环方式。每次请求,将触发所有块和节点的传输(如果用户调用了函数HAL_MDMA_LinkedList_CreateNode \ HAL_MDMA_LinkedList_AddNode),
' S% b4 ~ i) e% z- [# b
5 x' y h$ Y7 u+ R61.2.3 MDMA列表模式及其循环方式
3 H3 E& |* \8 x+ t4 c* ]4 C( F6 F列表模式包含多种MDMA的配置表,每个表包含一组完整MDMA配置。用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。
: o4 |- x: g% P- B
! R3 N' s4 y0 L( p 使用列表模式的话,函数HAL_MDMA_Init创建的是节点0。
Q2 J1 S. Q# ]4 e9 `- p6 ] 使用函数HAL_MDMA_LinkedList_EnableCircularMode使能循环模式,注意是从节点1开始循环的,将节点1和末尾的节点相连,不包含HAL_MDMA_Init创建的节点0。" E2 D& M) E1 P2 @5 n6 l( I
节点0是初始配置,仅在初始化MDMA传输时使用一次,比如调用函数HAL_MDMA_Start_IT。+ r: |. [# x4 u/ }( c: T: {6 d
如果要禁止循环模式,可以调用函数HAL_MDMA_LinkedList_DisableCircularMode。% m' D0 w3 W; \# q4 M4 F
通过函数HAL_MDMA_LinkedList_RemoveNode还可以删除指定节点。
5 t M5 Z8 [# t7 q" @/ @61.2.4 MDMA的触发源. D" V: p5 {- X, l6 w2 E# J
MDMA支持的触发源如下,主要包含DMA1,DMA2,DMA2D,LTDC,JPEG,QSPI,DSI,SDMMC和软件触发:+ Z3 o0 ~, }1 Y, l+ _9 Q/ R
2 x% `% x2 }! K% j5 E/ Q+ G- ]: O
- #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U)
! w% }- g! ]* D8 }; I8 D - #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U)
; B" e: j0 {3 l; J: r - #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U)
* N; v& I; _' W U. V - #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U) " o" X& ]1 j+ d& V6 r
- #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U)7 R7 K5 V" j7 ^( B- n q9 t
- #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U) 9 [) [0 G1 x* V/ H1 i# y1 H. K3 _
- #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U)
6 K+ e+ {4 c0 r - #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U)
. a2 ]# h( b8 F ]+ t ^; f - #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U) 3 S q4 @: U' K* _$ p
- #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U)
1 W/ n2 X L8 M - #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU) $ B( g/ E2 T" |' L' `3 ^
- #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU) ( v; }/ l. Y2 ]
- #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU)
/ M9 g: I9 ?. A' k - #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU)
4 A2 r, i/ Y2 x: r# \; C" l! T/ @. c* u - #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU)
- Q( G# v) ^: }( t; @) q - #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU)
3 q6 b+ @- m" T( g& c( _- ? - #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U) ) @' v# {1 e% V6 D2 \
- #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U) 4 D& E& d! L$ l1 `
- #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U)
2 R# M& Z) V) _ - #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U)
' g4 I! M" k$ Q( G: w9 W+ K - #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U) 2 Y3 E; ]- a1 B& M. L
- #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U)
8 a i4 C- x2 H/ W0 u' v - #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U) 6 ^$ W' O- b2 t# h
- #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U)
, t) Z1 @, \1 H* C - #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U)
; Z- K4 `0 {2 p* g - #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U) / H( ?% `3 j$ W9 n, ^
- #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU)
& ~! Q9 K" f- e( H: A
& x4 ^9 N0 v% I+ c1 [( ^% k- #if defined(DSI)
- p- |; r$ f/ f/ x% \' [ - #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU)
5 v7 n/ o$ M' u& D - #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU) 3 V6 B6 P1 d* j* h0 a
- #endif /* DSI */% L$ W8 M# X/ }# e
- - B- I g( i/ |' v$ x
- #define MDMA_REQUEST_SDMMC1_ED_DATA ((uint32_t)0x0000001DU) 1 i* w B* U( k3 R# p0 I& U) l0 s
/ [; Q7 M; n. m1 u- #define MDMA_REQUEST_SW ((uint32_t)0x40000000U)
复制代码
1 @0 i6 u. ~" W
1 L8 N3 p& R! B* |
! N; i7 U9 c6 q) K5 i0 h6 F% C4 @6 X61.2.5 MDMA的软件触发方式
. [* J+ w! }( _ Q: `2 Q2 nMDMA配置为MDMA_REQUEST_SW软件触发时,可以通过函数HAL_MDMA_GenerateSWRequest产生触发请求,使用此函数要注意以下两个问题:
* O- \$ K% Q4 t) K3 w0 Q
7 N8 r% _4 H1 k 如果传输结束或者传输还没有启动,调用此函数会返回error。
Q1 s, O, c5 G 如果传输还在进行中断,调用此函数会返回error,这次请求会被忽略。3 I8 Y" Y* `6 _; x! ^" i
9 A A8 ^5 M; t. Y) Q/ k, e0 G" `8 [. ^! O9 G# K
应用示例1:/ I# I3 x: v# i/ z4 a
1 R5 x" q2 j7 S5 p: ` MDMA配置为MDMA_BUFFER_TRANSFER模式,软件触发。
/ n! K& y# ^3 _: u+ |0 Q/ } 注册回调函数HAL_MDMA_XFER_BUFFERCPLT_CB_ID。" k7 f. C' e& a1 W) x3 ]
调用函数HAL_MDMA_Start_IT会触发一次BufferTransferLength长度的数据传输。! s7 i1 f5 C) f2 v# m2 b8 O+ h
传输结束会进入回调函数,用户可以在回调函数里面再次调用HAL_MDMA_GenerateSWRequest启动传输。0 f) p1 e1 I k) N/ Z
! t s p$ O% m0 \7 d; l9 }
; c, C1 Q" W& f! g: L2 ? ?( V应用示例2:1 D/ b: d/ C3 s3 B/ ~" G
4 h! ^8 Q5 E4 l$ l$ E MDMA配置为MDMA_BLOCK_TRANSFER模式,软件触发。' H* d/ F5 x. Q' r' \, K
注册回调函数HAL_MDMA_XFER_BLOCKCPLT_CB_ID。
/ T, [' n* ^& U 调用函数HAL_MDMA_Start_IT会触发一次块传输。
; F' y7 I# F! }3 y/ o' _ 传输结束会进入回调函数,用户可以再回调函数里面再次调用HAL_MDMA_GenerateSWRequest再次启动传输。) C" K' z# g7 N- f
61.3 MDMA的HAL库用法 @2 i# Z! ?5 {0 U% [ i4 R
MDMA的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置时钟,并根据需要配置NVIC、中断。下面我们逐一展开为大家做个说明。& D5 u/ X( n4 n+ n; _
1 f% b7 q; V, p7 N! i' x3 p9 m% O3 ^( }61.3.1 MDMA寄存器结构体MDMA_Channel_TypeDef和MDMA_TypeDef
1 k: m: q( n) F$ M; W$ m i) s% Q5 SMDMA相关的寄存器是通过HAL库中的结构体MDMA_Channel_TypeDef和MDMA_TypeDef定义的,在stm32h743xx.h中可以找到它们的具体定义:
A7 G+ C3 m3 T7 U y0 h
8 [# q) R: p9 U, o- typedef struct+ b: Q4 r+ F: T+ W! r5 w b
- { z* g$ k8 F$ f, s4 {0 T
- __IO uint32_t CISR; /*!< MDMA channel x interrupt/status register, Address offset: 0x40 */
. Y$ W) A9 w' \/ d - __IO uint32_t CIFCR; /*!< MDMA channel x interrupt flag clear register, Address offset: 0x44 */: D# r. p! B* }5 D0 b+ ^" G
- __IO uint32_t CESR; /*!< MDMA Channel x error status register, Address offset: 0x48 */1 [. X+ [1 O ~. I' P
- __IO uint32_t CCR; /*!< MDMA channel x control register, Address offset: 0x4C */ ; x2 D) D2 r0 Q! {( |
- __IO uint32_t CTCR; /*!< MDMA channel x Transfer Configuration register, Address offset: 0x50 */
0 h7 { g8 O. M: Z: x8 F - __IO uint32_t CBNDTR; /*!< MDMA Channel x block number of data register, Address offset: 0x54 */' f3 y/ N! D6 E) ~- e: u9 }, _
- __IO uint32_t CSAR; /*!< MDMA channel x source address register, Address offset: 0x58 */
+ P& \7 D$ [" M - __IO uint32_t CDAR; /*!< MDMA channel x destination address register, Address offset: 0x5C */: ` ?4 Y! ^+ ^- M" N+ o; N
- __IO uint32_t CBRUR; /*!< MDMA channel x Block Repeat address Update register, Address offset: 0x60 */
$ g$ m6 J7 z" ` - __IO uint32_t CLAR; /*!< MDMA channel x Link Address register, Address offset: 0x64 */& Q5 M$ ^6 X5 B
- __IO uint32_t CTBR; /*!< MDMA channel x Trigger and Bus selection Register, Address offset: 0x68 */
/ f1 o7 ^/ N( G* I+ {* i/ V - uint32_t RESERVED0; /*!< Reserved, 0x68 */ & y; C# n+ D; |# X4 {% U- D
- __IO uint32_t CMAR; /*!< MDMA channel x Mask address register, Address offset: 0x70 */
( z3 Z* ~4 p2 \+ E( w! R - __IO uint32_t CMDR; /*!< MDMA channel x Mask Data register, Address offset: 0x74 */
. n7 Q1 L8 K4 _% \& { - }MDMA_Channel_TypeDef;
6 k7 S5 P" _3 h) j' H0 j - 8 m0 b4 c! o8 _
- typedef struct
, Z% E; ]( a* u' k) R" |7 D5 M - {* O* v7 r: N8 D9 D9 T: v- D
- __IO uint32_t GISR0; /*!< MDMA Global Interrupt/Status Register 0, Address offset: 0x00 */* z' f$ F" v0 A
- }MDMA_TypeDef;. S# R8 }3 H& P
复制代码 2 s5 ]) Y& V# w- ?" @! r
8 k' m. T; B' @/ |9 u2 L__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:
$ R* W* v' ^, o6 y8 c- #define __O volatile /*!< Defines 'write only' permissions */
+ q: N: i/ p1 m& q8 g [ - #define __IO volatile /*!< Defines 'read / write' permissions */
复制代码
" w+ V& j& Y3 s. d* m4 ]2 L下面我们再看MDMA的定义,在stm32h743xx.h文件。
2 l* _( l/ |' d. V7 F& c$ _- d& d( o1 T8 \/ {
- #define PERIPH_BASE ((uint32_t)0x40000000)
9 }! k6 M- D7 P" s* N2 \9 \# T$ F - #define D1_AHB1PERIPH_BASE (PERIPH_BASE + 0x12000000)
- `5 O: N% M) H* w - #define MDMA_BASE (D1_AHB1PERIPH_BASE + 0x0000), d e0 ^, ?, v, C- y$ D2 G
- ' z) s2 j" Y! d; i5 t
- #define MDMA_Channel0_BASE (MDMA_BASE + 0x00000040)( w' n4 \8 x, ^
- #define MDMA_Channel1_BASE (MDMA_BASE + 0x00000080)
) S0 c5 `6 U% f) v$ F - #define MDMA_Channel2_BASE (MDMA_BASE + 0x000000C0)- ^3 p$ j! [ r5 u
- #define MDMA_Channel3_BASE (MDMA_BASE + 0x00000100)# J9 I& _/ Z. \# z" p
- #define MDMA_Channel4_BASE (MDMA_BASE + 0x00000140)2 O6 h: z1 K8 w( F9 u
- #define MDMA_Channel5_BASE (MDMA_BASE + 0x00000180)
. W5 n: k/ F: [* h0 G2 E3 C0 s D$ e - #define MDMA_Channel6_BASE (MDMA_BASE + 0x000001C0)! ]: d! c6 b: k E2 Y, O6 t
- #define MDMA_Channel7_BASE (MDMA_BASE + 0x00000200)
2 s8 Y9 W) X3 W - #define MDMA_Channel8_BASE (MDMA_BASE + 0x00000240)
* D, n; s2 z! `; L6 A% ~/ z - #define MDMA_Channel9_BASE (MDMA_BASE + 0x00000280)2 H v# S& G( f j
- #define MDMA_Channel10_BASE (MDMA_BASE + 0x000002C0)
/ s6 O9 O1 @, L! O' v9 y9 D - #define MDMA_Channel11_BASE (MDMA_BASE + 0x00000300)& C5 s* c) @6 [7 _/ I
- #define MDMA_Channel12_BASE (MDMA_BASE + 0x00000340)" n& p- E7 w% P- _/ R
- #define MDMA_Channel13_BASE (MDMA_BASE + 0x00000380)# P) w0 e4 b! M2 Q8 v1 Z* H
- #define MDMA_Channel14_BASE (MDMA_BASE + 0x000003C0)
. H( a) [7 z D0 M% ]& R - #define MDMA_Channel15_BASE (MDMA_BASE + 0x00000400)
$ S6 j$ b! o& S - # N/ {6 q; v3 U
- #define MDMA ((MDMA_TypeDef *)MDMA_BASE) <----- 展开这个宏,(MDMA_TypeDef *) 0x52000000
. F* D! A4 N) W8 U - #define MDMA_Channel0 ((MDMA_Channel_TypeDef *)MDMA_Channel0_BASE)
/ C- d; K! U) |4 Z5 \& Y, q - #define MDMA_Channel1 ((MDMA_Channel_TypeDef *)MDMA_Channel1_BASE)" w! L5 ?, A: O4 g( a
- #define MDMA_Channel2 ((MDMA_Channel_TypeDef *)MDMA_Channel2_BASE)
; F: `% {! _: S! C4 j/ M - #define MDMA_Channel3 ((MDMA_Channel_TypeDef *)MDMA_Channel3_BASE)
+ p- ]) O7 e, Z7 H9 U - #define MDMA_Channel4 ((MDMA_Channel_TypeDef *)MDMA_Channel4_BASE)7 e9 O7 K" O2 W
- #define MDMA_Channel5 ((MDMA_Channel_TypeDef *)MDMA_Channel5_BASE)- J& x' g% W$ R6 O
- #define MDMA_Channel6 ((MDMA_Channel_TypeDef *)MDMA_Channel6_BASE)
3 u2 V0 \, n' s T) ^+ f, H - #define MDMA_Channel7 ((MDMA_Channel_TypeDef *)MDMA_Channel7_BASE)
, b0 B) y& D2 T7 k* t: W - #define MDMA_Channel8 ((MDMA_Channel_TypeDef *)MDMA_Channel8_BASE)* q) p: R5 r/ t0 ?5 z
- #define MDMA_Channel9 ((MDMA_Channel_TypeDef *)MDMA_Channel9_BASE). M* u6 \$ y) f j2 g. j
- #define MDMA_Channel10 ((MDMA_Channel_TypeDef *)MDMA_Channel10_BASE)
+ B9 l" b" T* N: { - #define MDMA_Channel11 ((MDMA_Channel_TypeDef *)MDMA_Channel11_BASE)
1 _+ ^: E& `& s/ R) {7 Z2 I - #define MDMA_Channel12 ((MDMA_Channel_TypeDef *)MDMA_Channel12_BASE)
: g5 a$ \0 D& }& E$ I8 P2 Q8 r6 r - #define MDMA_Channel13 ((MDMA_Channel_TypeDef *)MDMA_Channel13_BASE)
" t6 Q: M* ~! R ^9 R" q/ R - #define MDMA_Channel14 ((MDMA_Channel_TypeDef *)MDMA_Channel14_BASE)
% ]+ w) _- w9 T& t/ H - #define MDMA_Channel15 ((MDMA_Channel_TypeDef *)MDMA_Channel15_BASE)
复制代码 % x1 t5 t) e n# ]% ~% J. W
( n0 X, ~ s! i1 g0 y
2 p9 @/ {, {& M+ s) ^* c6 F我们访问MDMA的GISR0寄存器可以采用这种形式:MDMA->GISR0 = 0。
; F7 a% x1 H6 ]& N% [+ m7 S7 x
* _. j7 p: J1 ^61.3.2 MDMA的参数结构体MDMA_InitTypeDef
6 x7 g% ~6 I& F: a此结构体用于MDMA的参数配置,具体定义如下:
* A5 h8 j9 ~7 T; ]1 t9 a3 |( E$ U& i; _
- typedef struct) [6 b6 S1 k, }6 l7 Y. d
- {0 d4 k- v1 m+ @: o
- uint32_t Request;
' h& Y- r# T) a& ], ~ - uint32_t TransferTriggerMode; 5 d: X/ F9 d3 }! I6 p
- uint32_t Priority;
- C) _: Y' G: _$ B2 \5 n - uint32_t Endianness;
4 x* e( K. z8 t! Q, Z2 c) z - uint32_t SourceInc;
/ X+ x. L6 I5 x - uint32_t DestinationInc; 6 g6 E4 Z3 z8 t& p4 P
- uint32_t SourceDataSize; - m) E8 l: D& ~9 u. A0 \
- uint32_t DestDataSize;
# c$ w2 |; x; m8 s5 D- l( H - uint32_t DataAlignment;
: ^; k3 ~% K6 l7 ~" e' K) f6 y - uint32_t BufferTransferLength;
+ E# i' w' K& |) f$ U5 Y - uint32_t SourceBurst;
# W2 p1 B9 R3 [- S! G - uint32_t DestBurst;
% t: [1 r& Y9 c y& ~* L6 B V - int32_t SourceBlockAddressOffset; $ M- ^0 i* \7 d: n9 o" K5 x. V
- int32_t DestBlockAddressOffset;
% W3 L) _# t* [ i: u$ {0 j* D - }MDMA_InitTypeDef;
复制代码
( K& {! {- _2 J1 j* ^- l" }
8 a$ w4 X. X4 O, L, q
9 n9 _! I5 x Z! ]下面将这几个参数逐一为大家做个说明:5 a# b, Y9 H3 v3 D4 H
; m" W& f P7 Y h uint32_t Request o/ H) z# p5 `2 e. t1 I5 u
触发MDMA的请求源,支持请求源如下:
4 V( D& ^! K1 x/ T/ Y/ z
1 [( t+ ^6 I- e/ p. w( x- #define MDMA_REQUEST_DMA1_Stream0_TC ((uint32_t)0x00000000U)
& ~' l5 \6 h, Z! M$ P+ h) G - #define MDMA_REQUEST_DMA1_Stream1_TC ((uint32_t)0x00000001U) 5 `% F6 _* q# o+ M! }; G# V( E
- #define MDMA_REQUEST_DMA1_Stream2_TC ((uint32_t)0x00000002U) ( o) H) G) [ N1 C; A& F
- #define MDMA_REQUEST_DMA1_Stream3_TC ((uint32_t)0x00000003U)
t- f# u+ |. w - #define MDMA_REQUEST_DMA1_Stream4_TC ((uint32_t)0x00000004U)
$ z$ S. W8 u+ }6 l - #define MDMA_REQUEST_DMA1_Stream5_TC ((uint32_t)0x00000005U)
' B5 k; r- I$ a" u% z7 x9 K6 e - #define MDMA_REQUEST_DMA1_Stream6_TC ((uint32_t)0x00000006U)
- u% Q2 S' a$ e k9 j5 i* q9 m4 X - #define MDMA_REQUEST_DMA1_Stream7_TC ((uint32_t)0x00000007U)
8 o; m) b7 |% S; S& ^ - #define MDMA_REQUEST_DMA2_Stream0_TC ((uint32_t)0x00000008U)
: D1 ]7 c6 V" ?) j- \7 q$ b5 c: e/ R - #define MDMA_REQUEST_DMA2_Stream1_TC ((uint32_t)0x00000009U)
; F2 O- o0 E& O" x# ~' m3 V - #define MDMA_REQUEST_DMA2_Stream2_TC ((uint32_t)0x0000000AU)
- c7 ?* d' Q' v5 x) F - #define MDMA_REQUEST_DMA2_Stream3_TC ((uint32_t)0x0000000BU)
' x+ F" r3 Q1 e- q - #define MDMA_REQUEST_DMA2_Stream4_TC ((uint32_t)0x0000000CU)
& Q% n F1 a6 v5 n7 m - #define MDMA_REQUEST_DMA2_Stream5_TC ((uint32_t)0x0000000DU) ( D2 t; X5 w. l" A4 B& \
- #define MDMA_REQUEST_DMA2_Stream6_TC ((uint32_t)0x0000000EU)
1 K4 Y5 u4 t7 |3 Y) F - #define MDMA_REQUEST_DMA2_Stream7_TC ((uint32_t)0x0000000FU)
) s: |4 k h) u' K2 n - #define MDMA_REQUEST_LTDC_LINE_IT ((uint32_t)0x00000010U)
4 V% X' Y" s U: o - #define MDMA_REQUEST_JPEG_INFIFO_TH ((uint32_t)0x00000011U)
4 x% J2 _+ b, o# A; `! i6 X, g7 o - #define MDMA_REQUEST_JPEG_INFIFO_NF ((uint32_t)0x00000012U) 4 K7 y; [- ?: _7 W
- #define MDMA_REQUEST_JPEG_OUTFIFO_TH ((uint32_t)0x00000013U)
( i$ n. X( h7 _ - #define MDMA_REQUEST_JPEG_OUTFIFO_NE ((uint32_t)0x00000014U) 7 V \/ K, c/ p: r& `
- #define MDMA_REQUEST_JPEG_END_CONVERSION ((uint32_t)0x00000015U)
; u- @- W4 S0 i, ?9 D - #define MDMA_REQUEST_QUADSPI_FIFO_TH ((uint32_t)0x00000016U) ) }5 ]6 @9 P# }: U4 k L8 ?
- #define MDMA_REQUEST_QUADSPI_TC ((uint32_t)0x00000017U) : S1 V9 t) d! m' }1 p
- #define MDMA_REQUEST_DMA2D_CLUT_TC ((uint32_t)0x00000018U) % e0 ~% j* @9 i1 Z4 H+ N) a
- #define MDMA_REQUEST_DMA2D_TC ((uint32_t)0x00000019U)
, \2 G& }7 I* L" [1 U: w - #define MDMA_REQUEST_DMA2D_TW ((uint32_t)0x0000001AU)
, [0 B! |. g& n/ ` N. l) c - ( P9 p, G* V0 ^/ B* z& t8 U2 i
- #if defined(DSI)
' c. @- l9 }/ `! l. e1 a' k - #define MDMA_REQUEST_DSI_TEARINGE_FFECT ((uint32_t)0x0000001BU)
: G5 @. n1 F4 U9 Q3 r) ^7 A2 N$ a - #define MDMA_REQUEST_DSI_END_REFRESH ((uint32_t)0x0000001CU) 8 i* a' g1 {! e T1 @
- #endif /* DSI */
( D1 @* t' p/ e/ h0 t5 v" |
3 H/ D+ }6 p& B- #define MDMA_REQUEST_SDMMC1_END_DATA ((uint32_t)0x0000001DU) ' n+ ~- k+ R4 l
- #define MDMA_REQUEST_SW ((uint32_t)0x40000000U) 2 c9 q: g; N9 u, Z! I* X5 X5 O
复制代码
& z: A% \- B( Y- R7 |/ [* W
( D: G9 g; [9 {6 G; ? uint32_t TransferTriggerMode- ~5 E9 s! c6 g
MDMA的传输模式,具体支持的参数如下:+ w6 y! n, T: m$ Q' H) W
' |2 m% L: H7 D" o$ }, \- #define MDMA_BUFFER_TRANSFER ((uint32_t)0x00000000U) /* 缓冲传输 */! h2 S, r' l8 I2 Q! ~
- #define MDMA_BLOCK_TRANSFER ((uint32_t)MDMA_CTCR_TRGM_0) /* 块传输 */
% ] B# f0 ?' \0 D% h9 M% O8 O" v) j% L - #define MDMA_REPEAT_BLOCK_TRANSFER ((uint32_t)MDMA_CTCR_TRGM_1) /* 多块传输 */
$ \; S4 G# p5 R* p9 h - #define MDMA_FULL_TRANSFER ((uint32_t)MDMA_CTCR_TRGM) /* 链表传输 */
复制代码 6 O3 k* H$ z) S: z
; ~: |7 c+ u8 n* ~8 h6 Q+ N: j
* H! C! H4 U7 R# E uint32_t Priority
5 q, Z; Y5 z& u% e# MMDMA通道的优先级设置,具体支持的参数如下:+ M( z c* \3 B' U" @
" n9 \* X2 H; K7 ^
- #define MDMA_PRIORITY_LOW ((uint32_t)0x00000000U) * z# j: T3 m( U
- #define MDMA_PRIORITY_MEDIUM ((uint32_t)MDMA_CCR_PL_0) % R: \0 K! d/ k3 V
- #define MDMA_PRIORITY_HIGH ((uint32_t)MDMA_CCR_PL_1)
2 @8 a* J+ L' G - #define MDMA_PRIORITY_VERY_HIGH ((uint32_t)MDMA_CCR_PL)
复制代码
6 K6 S: @: P: z V) v( @6 e2 d, i9 @3 p* @, F- o; ]
9 |7 h8 j# P" `9 W+ U
uint32_t Endianness
6 i" A+ n0 Y7 x8 RMDMA数据传输格式,具体支持的参数如下:
' c3 b2 h4 l6 Y- P( p6 e7 {; v
2 r3 S, z$ S4 Z; l7 | x- #define MDMA_LITTLE_ENDIANNESS_PRESERVE ((uint32_t)0x00000000U)
/ c4 \0 ?1 U% P. T8 a( V" t# y - #define MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_BEX) ; Z% I' ^" [2 G8 Y# Q
- #define MDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_HEX)
6 I3 v: y7 l" q6 K& _# e - #define MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE ((uint32_t)MDMA_CCR_WEX)
复制代码 9 k$ `: n$ I7 n3 A+ m L
! P# `3 f2 ]: k# Z/ o& k" M# [, ^
MDMA_LITTLE_ENDIANNESS_PRESERVE:正常的小端格式。- V, B" U4 _ _% i3 v& g( q1 G
7 @) C" N5 F: ~& c/ oMDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE:以半字为单位,交互高低字节。/ ]; t4 j: O: }8 t+ o1 D
" E$ F8 |; O" ?7 C( ~' eMDMA_LITTLE_HALFWORD_ENDIANNESS_EXCHANGE:以字为单位,交互半字。: v% U" L" m) [/ d9 Y0 K3 K, F
6 W% a6 h' s7 N% a2 L
MDMA_LITTLE_WORD_ENDIANNESS_EXCHANGE:以双字为单位,交换字。2 R( k. f r M* J5 }
9 q7 ?. v' }% G( } ^4 o uint32_t SourceInc) \0 L9 s7 _5 n5 Q U3 o, d0 d
MDMA源数据自增或者自减模式,具体支持的参数如下:
9 D; G, D- S+ U/ `/ Z5 h* G
2 A P% C6 A6 Y7 w( F" O- #define MDMA_SRC_INC_DISABLE ((uint32_t)0x00000000U)
8 @5 i" w/ Y$ U i. F- { p - #define MDMA_SRC_INC_BYTE ((uint32_t)MDMA_CTCR_SINC_1)
8 Y! `0 w: P* I, b6 ]! u - #define MDMA_SRC_INC_HALFWORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_0)
/ u' n, g+ h1 |& Z; C( B/ G6 ` - #define MDMA_SRC_INC_WORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS_1) ! j( I3 N# k$ m/ e3 ^1 M
- #define MDMA_SRC_INC_DOUBLEWORD ((uint32_t)MDMA_CTCR_SINC_1 | (uint32_t)MDMA_CTCR_SINCOS)
/ Q% y+ v: }) W, r9 L8 P7 x% x( } - #define MDMA_SRC_DEC_BYTE ((uint32_t)MDMA_CTCR_SINC) # k/ g7 H H6 n# [6 Z+ a) D
- #define MDMA_SRC_DEC_HALFWORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_0) & w; j9 m: Y" k- Y6 P" t S |- e7 Y
- #define MDMA_SRC_DEC_WORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS_1) 8 o6 R0 n& M/ _/ U1 a) J+ O! P
- #define MDMA_SRC_DEC_DOUBLEWORD ((uint32_t)MDMA_CTCR_SINC | (uint32_t)MDMA_CTCR_SINCOS)
复制代码
) {% A& s7 B+ J+ X( V5 ] ^: J. M" a" ~# m2 D
, e9 i( X3 o/ C- y DestinationInc& P Z8 j! L3 F/ i$ A2 }- Q. A
MDMA目的数据自增或者自减模式,具体支持的参数如下:
' Q" L1 F) R+ y5 w$ U9 o" B. {6 C- ~
7 K- B S4 t- c6 _9 _& Y% p- #define MDMA_DEST_INC_DISABLE ((uint32_t)0x00000000U) 5 }/ P! L1 |2 O: ~& W1 y4 e, ^' d S
- #define MDMA_DEST_INC_BYTE ((uint32_t)MDMA_CTCR_DINC_1) 5 t6 K" p9 k8 u" i$ I
- #define MDMA_DEST_INC_HALFWORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_0)
' z6 L1 a5 ~% F& I* V - #define MDMA_DEST_INC_WORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS_1) 6 C- {8 Q, m2 y, N% j
- #define MDMA_DEST_INC_DOUBLEWORD ((uint32_t)MDMA_CTCR_DINC_1 | (uint32_t)MDMA_CTCR_DINCOS) 5 J$ ]* K% F' _4 a3 c" ?& B" A
- #define MDMA_DEST_DEC_BYTE ((uint32_t)MDMA_CTCR_DINC) 5 P" U+ q% U. m6 f& H
- #define MDMA_DEST_DEC_HALFWORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_0)
: Y6 F0 W: n9 s5 w' T - #define MDMA_DEST_DEC_WORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS_1)
& `; W% @2 L2 u - #define MDMA_DEST_DEC_DOUBLEWORD ((uint32_t)MDMA_CTCR_DINC | (uint32_t)MDMA_CTCR_DINCOS)
复制代码
3 {( e$ }3 [0 }; o# l
/ K& p. T/ E7 Z* Y, q9 S: X2 X0 D; a j, R2 `+ q! D- z5 s
SourceDataSize
3 K7 X1 t/ n) v& D) D; [7 R3 Z; jMDMA源数据带宽,具体支持的参数如下:
3 Z" x) h# F N% k# m6 e7 X B5 h+ S5 l
- #define MDMA_SRC_DATASIZE_BYTE ((uint32_t)0x00000000U) " F; U O, U. c& j; W
- #define MDMA_SRC_DATASIZE_HALFWORD ((uint32_t)MDMA_CTCR_SSIZE_0)
P6 A* ?5 b2 R - #define MDMA_SRC_DATASIZE_WORD ((uint32_t)MDMA_CTCR_SSIZE_1) # J, ~2 B1 I: \9 ~0 v, o
- #define MDMA_SRC_DATASIZE_DOUBLEWORD ((uint32_t)MDMA_CTCR_SSIZE)
4 `9 w5 i4 E3 p; V
复制代码 ( i7 E. v9 B6 k- ~) {
1 W' S0 z; U( C! G DestDataSize0 s) Y. y: q1 `8 A; e* c
MDMA目的数据带宽,具体支持的参数如下:& L2 J0 i7 x) g+ Y3 {
& q, p4 z R. _8 z- #define MDMA_DEST_DATASIZE_BYTE ((uint32_t)0x00000000U)
7 Z- {% ]! ]0 E - #define MDMA_DEST_DATASIZE_HALFWORD ((uint32_t)MDMA_CTCR_DSIZE_0) ) T! R: W: e# o5 \% \' @- f& l
- #define MDMA_DEST_DATASIZE_WORD ((uint32_t)MDMA_CTCR_DSIZE_1) 8 G- `& c9 P8 U6 Z5 l
- #define MDMA_DEST_DATASIZE_DOUBLEWORD ((uint32_t)MDMA_CTCR_DSIZE)
复制代码 , E- P. v: I; K* D2 g
" _ j, `& y7 L# m4 |4 W
: e3 m: X3 c9 I2 H1 u x DataAlignment
4 } o2 j# R# d0 H, W# V6 xMDMA的填充/对齐设置,具体支持的参数如下:0 u1 I1 i$ b2 u0 O4 L. f
- #define MDMA_DATAALIGN_PACKENABLE (uint32_t)MDMA_CTCR_PKE)
' }( w& ?; {2 T- }% i - #define MDMA_DATAALIGN_RIGHT ((uint32_t)0x00000000U) 3 `) W8 ]% @' C: K! b% ^' C
- #define MDMA_DATAALIGN_RIGHT_SIGNED ((uint32_t)MDMA_CTCR_PAM_0)
0 `, v9 V$ j2 O; Y$ b2 f - #define MDMA_DATAALIGN_LEFT ((uint32_t)MDMA_CTCR_PAM_1)
复制代码 ! ~: v7 I5 {$ E ?2 Q" S+ r
2 R; K" \0 a, `8 b' h2 L$ N( [0 A7 D
MDMA_DATAALIGN_PACKENABLE:9 Z8 _8 l/ X6 {; |4 n# B$ E
. H# e5 {- a* b6 n4 |% f将源数据封装/解封为目标数据大小。所有数据均右对齐(采用小端模式)。1 {" _+ ^9 @5 A/ R" [1 s5 d# e/ [0 i
: s: X+ P+ B! e, u! Y
MDMA_DATAALIGN_RIGHT
4 ]7 ?- T/ W: V$ b; m$ v# y- j3 h. G7 L# {, M. E8 R! W
右对齐,用 0 进行填充(默认值)9 g8 p% {. f: A; H. i
% l$ \ d( \) r8 m$ l, ^
MDMA_DATAALIGN_RIGHT_SIGNED5 Y6 b* @1 e4 y3 K
9 r5 |: w( i5 r0 C1 c/ m右对齐,符号扩展& P- A* ]0 @8 M$ T0 A
' K, R" \) W. Z" \7 N: R: B1 d
MDMA_DATAALIGN_LEFT
. ~1 u; u6 h% S9 Y, L# R4 Q/ b
- S7 A/ r G* g' N$ X左对齐(用 0 进行填充)3 L: P" C( S0 g B; i% i+ {! l
# \* H, ]) m# s/ L" n8 x- B BufferTransferLength
& \ A8 x. L8 U5 m8 k7 I6 f' Q+ ^- j单次传输长度设置,范围1-128,单位字节。6 N3 o! _3 m' f% h, g3 M
3 E% s. ~+ u( J
SourceBurst. Q7 W5 O6 `4 O+ v
源数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下:$ h# J3 p. D6 j+ Q3 q* S0 ?
. Z0 }- x9 N6 g( A( @- #define MDMA_SOURCE_BURST_SINGLE ((uint32_t)0x00000000U)
1 \6 `/ t. J8 A7 x) h( A - #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) , W$ U( T" x0 I5 M3 |
- #define MDMA_SOURCE_BURST_16BEATS ((uint32_t)MDMA_CTCR_SBURST_2) - _8 x: l' }- n: n
- #define MDMA_SOURCE_BURST_32BEATS ((uint32_t)MDMA_CTCR_SBURST_0 | (uint32_t)MDMA_CTCR_SBURST_2)
9 v ? @8 K* m- c; l' } - #define MDMA_SOURCE_BURST_64BEATS ((uint32_t)MDMA_CTCR_SBURST_1 | (uint32_t)MDMA_CTCR_SBURST_2)
5 V. F: W7 p. x. i& S3 y - #define MDMA_SOURCE_BURST_128BEATS ((uint32_t)MDMA_CTCR_SBURST)
/ j- F/ y3 l6 T' H# Q: I
复制代码
2 C: l. G7 a" r+ b! V
+ o8 Q$ Z2 b% U3 u1 S6 D; ] DestBurst& \, F$ `! t ^
目的数据端突发设置,特别注意突发传输的数量不能超过BufferTransferLength参数设置的大小,具体支持的参数如下
6 x6 Y8 D! n V; I) g8 n- #define MDMA_DEST_BURST_SINGLE ((uint32_t)0x00000000U)
& \# ?: g9 K, D8 \- s+ _0 C+ k - #define MDMA_DEST_BURST_2BEATS ((uint32_t)MDMA_CTCR_DBURST_0)
: h! x1 g9 a/ s9 l - #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)
7 B! v# m/ X: N+ D: q$ K3 b - #define MDMA_DEST_BURST_16BEATS ((uint32_t)MDMA_CTCR_DBURST_2)
. {* [" m1 D0 q - #define MDMA_DEST_BURST_32BEATS ((uint32_t)MDMA_CTCR_DBURST_0 | (uint32_t)MDMA_CTCR_DBURST_2)
9 u8 o* H2 V b4 F - #define MDMA_DEST_BURST_64BEATS ((uint32_t)MDMA_CTCR_DBURST_1 | (uint32_t)MDMA_CTCR_DBURST_2)
3 h+ T' P) M4 G) N+ R" ^/ u - #define MDMA_DEST_BURST_128BEATS ((uint32_t)MDMA_CTCR_DBURST) 1 K1 @8 ^; N# h/ @0 H/ U
复制代码
3 t7 \- }! E3 K9 _- |( ` SourceBlockAddressOffset! \/ X/ u3 |1 a0 n
用于设置源地址端数据偏移。' y% @; d( Z. V W; ~! @
0 U- v6 \3 G" b. N: n
DestBlockAddressOffset
6 B5 ^. F( l' a0 _7 s2 @: U用于设置目的地址端数据偏移。
5 h1 G) ?1 n# ~1 j' O2 S% T1 l- Y0 Y- w; {, ]! R3 Y* n' z
61.3.3 MDMA结构体句柄MDMA_HandleTypeDef
$ N# Z- Y( q& }( W6 a) PHAL库在MDMA_Channel_TypeDef和MDMA_InitTypeDef的基础上封装了一个结构体MDMA_HandleTypeDef,定义如下:: P' b; T1 Y" |) e
2 V7 m9 l) v* ]1 [ R) P- typedef struct __MDMA_HandleTypeDef3 c: Y" u2 L1 o, F! E( U
- {
% e/ {; ]3 U4 U4 [ - MDMA_Channel_TypeDef *Instance; . I2 |8 M7 `* ?. O- ?& J$ T
- MDMA_InitTypeDef Init;
% N. E s8 a, W$ D - HAL_LockTypeDef Lock; * _& Q" s5 S% d+ x. n
- __IO HAL_MDMA_StateTypeDef State;
8 c# \9 Z( a- A2 N$ \1 f& ~) ^ - void *Parent;
2 Y( y ^9 O0 ~& R! ] - void (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
) \3 {; G3 l9 z$ Z1 p" X5 @2 b7 h) u - void (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma); # _; f, }" a; @" A2 }- [3 d- j: b
- void (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
: q5 z) Y. C3 F7 u! z% J - void (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);4 u0 x! g) s: S( F1 H C
- void (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma);
. @/ a+ }$ ~5 H - void (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma);
/ n( l' Y7 a" E. \4 A' R - MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress; 2 d" T$ P3 y6 L H3 L
- MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;
( V7 Z; T% R: ~ - uint32_t LinkedListNodeCounter; 5 z! k; {! D/ Q% I; S
- __IO uint32_t ErrorCode; % C3 Y4 Q% Y% s7 X$ A
- } MDMA_HandleTypeDef;
复制代码
4 \# ]" F, m: V$ L) K下面将这几个参数逐一做个说明。2 C% H% \" [ ^ h; ~$ c
! J& l) `+ q# A+ e9 d- b z MDMA_Channel_TypeDef *Instance
0 A0 ^$ V( M; _, ~0 J" F) s这个参数MDMA通道的例化,方便操作寄存器,详见本章3.1小节。/ V% @- ~1 k1 U0 V9 u
% U. K# U2 [! ~ MDMA_InitTypeDef Init
! Q" S5 I% v8 t( R% S这个参数用于MDMA的通道参数初始化,详见本章3.2小节。) k H2 y: V! Z8 {
) i8 z# b; s$ Z" y* L
void *Parent
4 m# u$ Z, ?- }( J! Z+ n用于记录MDMA关联的外设。, i2 p: D2 Q: J, c* P
/ m- \$ P8 }! S$ h4 w
void (* XferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma); + O( |( r- o6 A% e5 e& ?, W: }
void (* XferBufferCpltCallback)( struct __MDMA_HandleTypeDef * hmdma); ! X& z9 Y0 X. x: B4 Z( E$ o
void (* XferBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
2 `" p( O( u9 D4 H( o, t9 B void (* XferRepeatBlockCpltCallback)( struct __MDMA_HandleTypeDef * hmdma);
: ^2 r3 l1 s$ l* m, L7 k' D void (* XferErrorCallback)( struct __MDMA_HandleTypeDef * hmdma); 7 \# p, U+ Y9 J5 A
void (* XferAbortCallback)( struct __MDMA_HandleTypeDef * hmdma); 3 Y+ h: c4 C& k5 c% t
MDMA的各种回调函数。 D3 t8 o$ l0 ~# ~8 ?( }
* L x8 O8 X9 T3 m! l/ ^& {+ a
MDMA_LinkNodeTypeDef *FirstLinkedListNodeAddress;: n' O( G; N) b# h. l" @# v
MDMA_LinkNodeTypeDef *LastLinkedListNodeAddress;
3 z1 J. p) ^6 z R6 B: G' r uint32_t LinkedListNodeCounter;. p; m1 t# [6 y. Q
用于MDMA的列表模式。% k6 s( N& N% O, V' V0 z
, [% [6 C7 v6 Y
HAL_LockTypeDef Lock
* }6 K5 w1 L- `% W __IO HAL_DAC_STATETypeDef State $ H/ D1 J% N/ \% r7 N5 \) Y5 l
__IO uint32_t ErrorCode % r4 r( v4 B* p+ A$ x/ N# M. S2 b
这三个变量主要供函数内部使用。Lock用于设置锁状态,State用于设置DAC状态,而ErrorCode用于配置代码错误。
3 f* w4 V# Z- M! x& w1 i+ D
% V/ c! f! o. g3 U: B61.3.4 MDMA初始化流程总结
0 V3 W* [' j: r" z% q使用方法由HAL库提供:
8 j3 v( \. ]- c! ?) W/ f
: ^/ T7 V7 ?# }! M 第1步:基本的初始化。
# z5 W/ C, Z& O/ x6 ?3 z' H8 U, Y
# T( C. |4 k) [9 Q* d1 |) a 函数HAL_MDMA_Init配置MDMA的基本参数。
/ N# ^; E: d* Q. }$ [+ P9 R
7 `. n" b5 l$ u) H
- y) R- L L% P 第2步:列表模式。
5 Z8 p5 i0 Z' P
0 k) M3 J* @) z如果使用列表模式,用户可以使用函数HAL_MDMA_LinkedList_CreateNode创建节点,再通过函数HAL_MDMA_LinkedList_AddNode将节点添加到列表里面。
6 r% ]) C0 L, [5 H# | ^4 `
8 d; h! P" n6 v* \6 `" w ?2 g7 {. B
第3步:查询模式。1 c9 i( t2 f0 d. n \4 k' v. A6 H
; Z7 l ~! b) Q
函数HAL_MDMA_Start 启动传输。
* g# n/ V$ ^, t0 V2 Y' ?, V 函数HAL_MDMA_PollForTransfer 查询传输完成。7 F- O# s" l+ L4 t% B
函数HAL_MDMA_Abort 终止传输。/ O. b+ y$ U; ~- X
0 k2 G# Z/ q M
) a; W! e2 \& ^5 K4 g6 K' u 第4步:中断方式。. b- A/ l) i" w' L
5 s& e# V+ ] ~: ?" u
函数HAL_NVIC_SetPriority设置MDMA中断优先级。. d7 d: E) j; Z5 T) n& C2 i8 M) a
函数HAL_NVIC_EnableIRQ使能中断。
9 h4 h" @5 i4 Z: z; B. Z 函数HAL_MDMA_Start_IT启动中断传输。( @0 T5 s6 s+ k, p7 [8 A
MDMA的中断服务程序MDMA_IRQHandler里面调用HAL_MDMA_IRQHandler,如果用户注册了各种回调函数,会在此函数里面执行。$ I3 K+ ~' E Z* B% x; V$ Y9 j. h8 R
函数HAL_MDMA_Abort_IT可以终止MDMA中断传输,终止完成后,会调用回调函数XferAbortCallback(如果设置了的话)
( K5 q0 M3 _( x4 f# |
$ y# g' ^* X7 }2 |! }6 X2 _- o8 t1 Y7 ]# @% ` o2 n P
第5步:中断回调函数。/ p; N4 d4 j4 c7 D
5 V# p" @) ~4 ?* \函数HAL_MDMA_RegisterCallback注册回调函数,函数HAL_MDMA_UnRegisterCallback取消注册回调函数。' u3 A1 q' l+ p. Q" J$ i
' W& B) O. s8 \$ {( {
XferCpltCallback : 传输完成回调。% b- a6 k2 ^/ P: @
XferBufferCpltCallback : buffer传输完成回调。9 V1 c0 K' \' u
XferBlockCpltCallback : block 传输完成回调。/ N! H4 k: q' r- w6 |& h1 {- I
XferRepeatBlockCpltCallback : repeated block传输完成回调。
; i. H/ z& U3 o; p+ f, O# M XferErrorCallback : 传输错误回调。
) o2 Z: z2 f# ~9 L XferAbortCallback : 传输终止回调。% t! y1 |: c) `
. i( X) }7 l/ N4 m+ K; s3 [9 M- f( l0 U5 G( A4 G
61.4 源文件stm32h7xx_hal_mdma.c+ ]; s Q4 D D! z; I, I! h
这里把我们把如下几个常用到的函数做个说明:
3 C+ S" {/ \+ j5 m7 T* `2 C# I% V
& R/ @ }: ~) I p3 ^ HAL_MDMA_Init
# N5 U3 V+ V& _5 x. m# N( | l2 f HAL_MDMA_Start_IT9 T2 X! S3 I) W% y. \
61.4.1 函数HAL_MDMA_Init
" |2 x9 M1 g; T5 F- B3 ?函数原型:
+ S+ X1 O5 h% L8 x4 Q/ a( k3 ]+ S
- HAL_StatusTypeDef HAL_MDMA_Init(MDMA_HandleTypeDef *hmdma)
$ V; m* O u* @" P/ N' \3 g - {1 R# r. m! H8 S+ l
- uint32_t tickstart = HAL_GetTick();
0 d( l4 v/ Y3 H# ^% T9 ]. Y5 }; Q+ g
, l6 a' K( U7 G4 H* c; ?. d- /* 检测句柄是否有效 */
% f& A+ ?% c2 u1 i7 A2 c r - if(hmdma == NULL)
6 X0 h) n. M1 i8 j) n; n/ J5 A - {2 N8 L% V V( X& o3 i
- return HAL_ERROR;! j! Y0 Y+ j) z* a2 t7 Q. }
- }6 H0 S; R: m) j* v
- ( P$ E4 t: S0 j7 H$ [5 H3 W
- /* 检测参数 */) G) l) E! E% E$ [; L) R
- assert_param(IS_MDMA_STREAM_ALL_INSTANCE(hmdma->Instance));
2 K: t* n. N, { - assert_param(IS_MDMA_PRIORITY(hmdma->Init.Priority));
8 {( K* ^ Q) H" Q - assert_param(IS_MDMA_ENDIANNESS_MODE(hmdma->Init.Endianness));4 @( u/ w/ _2 Q* i. B3 H7 D
- assert_param(IS_MDMA_REQUEST(hmdma->Init.Request));& O. D# y c: i3 U8 q
- assert_param(IS_MDMA_SOURCE_INC(hmdma->Init.SourceInc));
, R" a8 r+ t2 I - assert_param(IS_MDMA_DESTINATION_INC(hmdma->Init.DestinationInc));
$ k: x+ C7 x# w7 V! X - assert_param(IS_MDMA_SOURCE_DATASIZE(hmdma->Init.SourceDataSize));
3 ~2 b% C* x3 |2 k$ J - assert_param(IS_MDMA_DESTINATION_DATASIZE(hmdma->Init.DestDataSize));
! ?& [- }: u0 \ - assert_param(IS_MDMA_DATA_ALIGNMENT(hmdma->Init.DataAlignment));
& @. R+ ]& r* ~% c - assert_param(IS_MDMA_SOURCE_BURST(hmdma->Init.SourceBurst));$ }3 Z* e1 _) F' a
- assert_param(IS_MDMA_DESTINATION_BURST(hmdma->Init.DestBurst));) y! G9 i- m' S
- assert_param(IS_MDMA_BUFFER_TRANSFER_LENGTH(hmdma->Init.BufferTransferLength));( V0 t6 `1 u& V0 s; O' q
- assert_param(IS_MDMA_TRANSFER_TRIGGER_MODE(hmdma->Init.TransferTriggerMode));
- i! O/ X! p$ J& e# X* o5 a. K - assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.SourceBlockAddressOffset));
# `, h6 v/ a3 |$ e: j9 B" ~) ? - assert_param(IS_MDMA_BLOCK_ADDR_OFFSET(hmdma->Init.DestBlockAddressOffset));
# {% q/ k4 p$ O! E
( {/ G( K E" G: d. P
5 h. n4 A% f0 I8 U$ d+ d- /* 解锁 */" R- g2 Q2 T# F+ _6 G/ m7 p+ A
- __HAL_UNLOCK(hmdma);
7 C) ^0 t; G. }& F2 X - ; J, L! w* x: z9 Z& X- P! G- X' N3 g
- /* Change MDMA peripheral state */! ~/ {- E* a7 Z o4 k
- hmdma->State = HAL_MDMA_STATE_BUSY;
$ o0 Y5 E: x5 A) l, M! Z- ]
# i) L8 V0 U3 g) x" {- /* 禁止MDMA */6 H5 [5 q2 v& Z: h& y; r
- __HAL_MDMA_DISABLE(hmdma);
! S0 v+ i) n: p0 n/ L - - |5 b, {* K: q! U5 r
- /* 等待禁止成功 */
! W3 N8 I: h* J; {$ T - while((hmdma->Instance->CCR & MDMA_CCR_EN) != RESET): E" f- [2 p% C
- {
2 c6 G* ` T \) U- Z4 z. s$ T - if((HAL_GetTick() - tickstart ) > HAL_TIMEOUT_MDMA_ABORT)+ L1 m0 w8 G, u2 v/ u
- {
# E& x- k. r# z- j6 v4 ]! A5 Z2 a - hmdma->ErrorCode = HAL_MDMA_ERROR_TIMEOUT;, c7 v: U' h3 S- ~4 T
8 c: E! s2 f; p! g- hmdma->State = HAL_MDMA_STATE_ERROR;
( x2 E8 ]+ V( I o
$ K/ y" l, H8 Y: m: @+ y- return HAL_ERROR;4 ?+ c9 L; h- l R- @% ?
- } v! K* q) h8 ~; Q3 I% F n6 P# |; b2 ~
- }
7 ?0 t+ ]- a, R; G - / F) R. e, s. k7 R- ?
- /* 初始化 MDMA */
/ z8 Z$ B S+ b( v5 |1 | - MDMA_Init(hmdma);# p3 Z7 G% K8 V4 p
- 9 z4 v! m1 C$ T6 _8 g O2 k' J
- /* 复位列表模式相关设置 */
4 ^+ [0 K( M- o$ u3 \" E - hmdma->FirstLinkedListNodeAddress = 0;
1 P; `1 y+ _ W, M - hmdma->LastLinkedListNodeAddress = 0;
, W5 `& e2 N3 Q4 [ - hmdma->LinkedListNodeCounter = 0; / B9 x3 _% s( l4 |* H
- ; Z! ?) G& g( p, A b5 G! F. D( {
- /* 设置无错误 */
* f. P' k& x. P/ d& U7 R6 W - hmdma->ErrorCode = HAL_MDMA_ERROR_NONE;
0 S: h$ @; n( K+ ~7 e% ]
) z* h r8 S, r$ s- /* 设置就绪 */
V& u$ ?9 s9 M - hmdma->State = HAL_MDMA_STATE_READY;
& t- q$ K3 {, a/ r, [1 } ^
4 e& a+ f5 \/ I- return HAL_OK;* w9 l1 ]) }' ?
- }
复制代码 ! h& _# U) V3 ?* }/ W* a
$ q& Z2 _) V0 I4 O4 g0 c
9 z* E7 K: x8 w# H4 q+ e
函数描述:
% ^; H, q3 p# \2 u% w2 r5 B: h5 f X: Y
此函数用于初始化MDMA。
" e$ a& h, f5 h0 p' a6 J' b
& a* f5 w5 h1 A; d) y函数参数:$ `$ n- o4 j3 ]$ k
/ c8 K5 d/ V% P7 k0 B+ l; J. W 第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。
& a+ X' ]! c/ T2 J( E& p3 O 返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。, S, B6 R8 q# K4 E$ H
使用举例:
" a) R# ?3 ^6 h( a1 d1 P& d
' u; t& b* M- T- MDMA_HandleTypeDef MDMA_Handle;) D" c# y% W ]8 i
' c7 }# N* J1 J7 V0 X- __HAL_RCC_MDMA_CLK_ENABLE();
: T- K {8 r5 P$ t3 H
- ^2 H. ?+ u1 j K& X- X+ I- MDMA_Handle.Instance = MDMA_Channel0; , t0 z" y1 `% F; J3 V( [1 ]
: {. o3 D7 E8 e4 s* g2 o1 x, {- MDMA_Handle.Init.Request = MDMA_REQUEST_SW; /* 软件触发 */
! _3 ~7 `" I* S) C* I/ W. t2 w9 S) K - MDMA_Handle.Init.TransferTriggerMode = MDMA_BLOCK_TRANSFER; /* 块传输 */
3 @2 v, |6 C7 Y( H% I( p - MDMA_Handle.Init.Priority = MDMA_PRIORITY_HIGH; /* 优先级高*/2 E1 E% X x2 O
- MDMA_Handle.Init.Endianness = MDMA_LITTLE_ENDIANNESS_PRESERVE; /* 小端 */
0 h% t+ _/ K% }0 ^2 g: ^ - MDMA_Handle.Init.SourceInc = MDMA_SRC_INC_DOUBLEWORD; /* 源地址自增,双字,即8字节 */3 n: K0 ?9 v* o
- MDMA_Handle.Init.DestinationInc = MDMA_DEST_INC_DOUBLEWORD; /* 目的地址自增,双字,即8字节 */# N4 D* f/ H; O
- MDMA_Handle.Init.SourceDataSize = MDMA_SRC_DATASIZE_DOUBLEWORD; /* 源地址数据宽度双字,即8字节 */
; c8 @, L6 F, w! r+ h9 v - MDMA_Handle.Init.DestDataSize = MDMA_DEST_DATASIZE_DOUBLEWORD; /* 目的地址数据宽度双字,即8字节 */& e" G: n% x+ W6 Q6 D+ s f) V( a
- MDMA_Handle.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE; /* 小端,右对齐 */
s+ H: M2 l; L - MDMA_Handle.Init.SourceBurst = MDMA_SOURCE_BURST_16BEATS; /* 源数据突发传输 */
4 ?: X* x4 M% |; s* l/ c0 N - MDMA_Handle.Init.DestBurst = MDMA_DEST_BURST_16BEATS; /* 目的数据突发传输 */6 G8 |3 J# U! L7 B% S
- / u; G/ V# ?0 T8 K2 |+ [2 U7 y" q
- MDMA_Handle.Init.BufferTransferLength = 128; /* 每次传输128个字节 */
) g9 a6 [: E7 i7 V5 @5 a" s - $ S) w4 J3 \9 g# l' a
- MDMA_Handle.Init.SourceBlockAddressOffset = 0; /* 用于block传输,地址偏移0 */- N( U- E% u5 } K$ u2 W
- MDMA_Handle.Init.DestBlockAddressOffset = 0; /* 用于block传输,地址偏移0 */% p$ K* C; u% E* w8 j% e" l+ g) s
( r" z/ {" a1 b+ U- /* 初始化MDMA */
$ M! X6 T( O8 C5 p$ ]- I" k - if(HAL_MDMA_Init(&MDMA_Handle) != HAL_OK)
# Q5 M% | C. P3 E { - {
' q+ c6 U5 O* S% i8 p5 y - Error_Handler(__FILE__, __LINE__); a- R) V6 N, Q& y9 j
- }
( z6 ` x' k4 O/ t! Y' U - " |( b/ v) U/ K- q7 x+ `
复制代码 8 C; N6 L1 p! \
61.4.2 函数HAL_MDMA_Start_IT) ]7 x7 k; K+ B- A
函数原型:
7 F* C3 h+ p: [; t3 ~* b$ P0 o9 W1 A
% H J# B$ \; Z- ]( d: D4 e- HAL_StatusTypeDef HAL_MDMA_Start_IT(MDMA_HandleTypeDef *hmdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t BlockDataLength, uint32_t BlockCount)1 H3 e' S* y' ]5 i, | H
- { ^: Q3 c. c0 c V4 D& d
- /* 检测参数 */: L Q" H5 F- q- [' f4 K
- assert_param(IS_MDMA_TRANSFER_LENGTH(BlockDataLength));
$ u9 a5 \6 d3 T8 Z& e K& M. O - assert_param(IS_MDMA_BLOCK_COUNT(BlockCount)); 4 | T- J* [# q, q; _* }
- , M5 w% w4 }+ Y$ F# V: h7 w
- /* 检测句柄是否有效 */1 v& U' ?3 j7 R' H# V- V8 y' E
- if(hmdma == NULL)/ A T- M2 N3 y" W. S: D
- {
. N# Y! L6 M8 O - return HAL_ERROR;5 c6 N( U5 z4 a1 q \/ y
- }& [( C: P; y) i
- 4 x: [6 o8 \3 H i8 O" w: Q) }
- /* 上锁 */6 L) {. ]8 d" I' c
- __HAL_LOCK(hmdma);
* F% s$ r9 N3 L
; L' J1 s, P4 _0 z- if(HAL_MDMA_STATE_READY == hmdma->State)) V2 x q* a3 H0 s( g) v
- {
/ P7 Y1 w% ^; Y - hmdma->State = HAL_MDMA_STATE_BUSY;, t5 k6 P4 P3 o6 q, P) m% s, I
% e! \ }: u3 N/ g- hmdma->ErrorCode = HAL_MDMA_ERROR_NONE; ) ~/ C5 q$ n9 Z
- Q: X" `5 L& E9 C* T! z- __HAL_MDMA_DISABLE(hmdma);5 c3 `5 K- Z% l
5 U, C' w [4 k! |. w3 X! Y9 p @- /* 配置MDMA */
' C+ _: W" Y5 D# q - MDMA_SetConfig(hmdma, SrcAddress, DstAddress, BlockDataLength, BlockCount);
* ] F) ?/ e0 V4 J( s
$ m* k4 W1 m9 h4 N2 b1 t; P J4 F- /* 使能传输错误和传输完成中断 */
2 y9 p6 X* `7 R4 O4 J - __HAL_MDMA_ENABLE_IT(hmdma, (MDMA_IT_TE | MDMA_IT_CTC));
+ Z" d4 l- y" \7 |; k# I; w - 1 f2 ^7 i5 `! V! u. K$ m7 f
- if(hmdma->XferBlockCpltCallback != NULL)7 V1 C% C" w [0 L, f2 ^ D7 m6 t
- {5 d8 R! G0 _6 z8 d7 [& i" _
- /* 使能块传输完成中断 */: ~' L5 ^. T5 c+ \+ `( d. C J
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BT); ; e2 ]: G D8 \- J
- }/ G% a4 C# [: ^/ Q
- # f- O1 v2 Q; q, w$ n
- if(hmdma->XferRepeatBlockCpltCallback != NULL)- h- A Y- l0 W2 r& b; m
- {
+ r- g- K" H1 `* |* o; U - /* 使能多块传输完成中断 */
" J+ D9 [! L3 }2 J - __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BRT); 0 `# Z8 w7 E9 ]6 \: Y
- }
1 z3 M# e) c: b/ X% C - 7 Y& ^- p" a' l+ X; @
- if(hmdma->XferBufferCpltCallback != NULL)
; w* ~5 x1 J0 T' B - {
2 X3 A K9 k0 N, s! q3 T - /* 使能传输完成中断 */6 W7 Q5 ^5 ?1 D$ M! t
- __HAL_MDMA_ENABLE_IT(hmdma, MDMA_IT_BFTC);1 T, {& }' C/ A3 K9 Y
- }2 e9 l0 O: z( W: R& b& F
- ! T/ a" ]8 B8 `: T. }, w
- /* 使能外设 */
7 B' R& g: `9 |" K5 a @ - __HAL_MDMA_ENABLE(hmdma);$ M% z/ s3 z* E# f
1 c. W, i5 _& T- }3 }% E- if(hmdma->Init.Request == MDMA_REQUEST_SW)
: f* d$ k a' y& G1 F - {) |3 R' b- D6 U: I. J
- /* 使能软件请求 */' n1 h+ \3 R# j. ^
- hmdma->Instance->CCR |= MDMA_CCR_SWRQ;
/ B0 b# m! Y9 n* ^' v: g" p - } 4 O; f. `8 l2 m- Y
- }
$ b4 j$ y) r! Y2 @* D) r - else0 E, q8 w) Z, A
- {
+ y8 c. r$ c. b k - /* 解锁 */
( Q+ @1 C3 m& ~0 C, ^4 ]+ N6 N - __HAL_UNLOCK(hmdma);
: d9 z% m* {- S+ t) \" I - ) n1 |" Z, O1 V% a+ c
- /* 返回忙 */4 p7 C7 ~0 r0 ?8 M, K, `' a, |
- return HAL_BUSY;4 s; `* l$ d# J( c) E
- }# a U! y! {2 G* d1 C7 J9 z" O9 }
- % T: L& g0 L; E( v" F0 ]' ^
- return HAL_OK;; h0 _: z! Q c$ k M: h1 w
- }
复制代码
& y7 k% A+ ~5 J6 U' ?' L. W8 k) T$ J$ u. y) F9 P5 G! D
1 |& L5 i1 c4 O: L2 g函数描述:9 Q- r( O1 O. H @% U1 G
5 W3 N. V7 j! K* g7 A; a# k, N$ _2 K
此函数主要用于配置MDMA的中断方式传输。% j- g, o2 J7 W0 \5 p9 T
( i, ^0 g" O R* N9 G函数参数:7 l, ]+ e) A# U
; m$ Z" X5 E+ B. ` 第1个参数是MDMA_HandleTypeDef类型结构体指针变量,结构体变量成员的详细介绍看本章3.3小节。
" ?% k& b2 w, {8 G; j. o 第2个参数是源缓冲地址。
2 M5 {$ O* D1 f 第3个参数是目的地址。
* ^: ~- H; L# J+ N" i: M$ \ 第4个参数是传输的块大小,单位字节,范围不可以超过65536字节。8 T3 i+ Q+ o6 {3 ^0 }) `& t
第5个参数是传输的块数,范围不可以超过4095块。* }1 q. P. _3 a- l/ N7 O2 o4 i
返回值,返回HAL_ERROR表示配置失败,HAL_OK表示配置成功,HAL_BUSY表示忙(操作中),HAL_TIMEOUT表示时间溢出。
/ {, `& X& M) R* A使用举例:
. ?$ G: B' W2 N. ^/ v2 d s) e/ K7 w9 h/ X4 ^6 Z, i
- /* 将地址0x24000000开始的64KB数据复制到地址0x24000000 + 64*1024 */
0 }& P: w- R5 C, F4 n" p+ A - HAL_MDMA_Start_IT(&MDMA_Handle, 8 p; ^: ~* U# B1 l
- (uint32_t)0x24000000,
0 Z3 g. [. _3 c# m& ^ U - (uint32_t)(0x24000000 + 64*1024),
) ]! _% t( w8 D) a7 J' G+ I - 64*1024, 4 f7 ` A" t4 j2 d
- 1);5 u, ^/ j: v9 f: T' @0 J! E
复制代码 ; Q1 n# z" [3 ]
\1 R- \" J2 [; T61.5 总结
0 P5 h9 y( a1 x, Z2 A) n本章节就为大家讲解这么多,MDMA功能用到的地方还是比较多的,后面的章节会为大家做讲解。- a3 B* W/ D: s+ u
1 \! _/ \; E% i3 U0 s0 N
* Z! w9 h& X4 r. f |