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

STM32 DMA编程注意事项

[复制链接]
STMCU小助手 发布时间:2023-1-11 14:04
有人使用STM32H7芯片做些事情,发现基于ST公司的HAL库开发UART1的DMA收发时可以轻松实现,而当使用ST的LL库组织代码时,却没法实现UART的DMA传输。感觉上就是使用HAL库编写代码功能正常而基于LL库则不行。真是这样吗?

. U: X! m! o+ q4 Z8 ^" E
使用STM32CubeMx进行图形化配置,并生成基于HAL库的初始代码,要实现UART收发功能的DMA传输的话,除了安排好的收发缓冲内存外,再就只需调用下面两个HAL库的API函数即可进行功能验证。

' _4 S$ k# W7 e* \" \' k
微信图片_20230110185835.png

4 q$ L# x* d1 p( A- f. [/ G) Y3 ?
从功能实现上讲,使用HAL库及相应API还是很方便、很简单的。每个API函数就像个黑盒子,对于里面的内容,如果你不点进去阅读是不会知晓的。不过,建议尽可能地多点进去瞧瞧,那里往往别有洞天。

8 X: z& c+ `: h0 a. s8 o5 x; o
如果基于LL库来组织代码的话,先使用STM32CubeMx进行配置并生成基于LL库的初始化代码。
% I% q7 m- c, F, j# n
微信图片_20230110185749.png

2 p/ k% W' B! J4 U" ^+ ~( n7 {
微信图片_20230110185746.png
* W' _2 z' V  K& z3 j
基于CubeMx配置完毕后生成初始化工程,准备收发缓冲内存,然后添加用户代码。
刚开始用户代码是这样编写安排的。见下面代码截图。
' z9 ^. I  H* v
微信图片_20230110185741.png

' S6 B5 Z' f$ d0 Y
上图中A处代码的作用就是开启两个DMA stream的功能,即对相关DMA Stream的控制寄存器的使能位进行使能置1。
编译无错后运行代码,可是根本没有数据的收发动作发生。看来,跟反馈者的症状一样。

& D7 C% S9 E5 r5 Z
没办法,硬着头皮核查代码。除了核查我添加的用户代码外,还核查UART及DMA的初始化代码。看来看去,似乎该有的都有了,该写的都写了。
4 s% r. `6 k( M
后来,根据代码里涉及到的寄存器去跟STM32H7手册里寄存器做比较阅读。在查看DMA各个stream配置控制寄存器【DMA_SxCR】内容时,突然发现并想起了点什么。其实也是之前在别的DMA应用场合也碰到过的类似问题。下面为该寄存器的内容布局截图。
$ e  O: _0 j: \8 j/ r$ i
微信图片_20230110185736.png
) G9 D; n  j1 `3 S' T6 c
隐约记得,该DMA Stream或Channel的控制使能位为0时才能做DMA相关其它参数的配置的。我们可以在手册里找到针对该位的明确描述:
* i; z4 Q* Q! z) C4 U* }5 b
微信图片_20230110185730.png

; l' p& t. j1 G* ?- r, t
这里的意思是说,要想让某DMA stream工作,必须令该EN位为1。不过,当该EN位为1时时,是不允许对DMA及相应FIFO寄存器做配置的。换言之,若要针对某Stream做DMA相关配置,得先让该控制寄存器的EN位保持为0状态。

' W1 ~) M8 }$ }" q
而在我的用户代码里,对EN位写1操作则放在了对DMA做各种配置的前面,即上面代码截图的A处。

) F; n) h+ V; I7 G
微信图片_20230110185726.png

; A' r9 J9 v5 G  C  ]& N% v2 S
微信图片_20230110185724.png
, Q; G( g! i2 }
既然这样,我们把对DMA控制寄存器EN位的置1操作放在其它DMA相关配置之后就应该可以了,即从上面代码截图中的A处拉到B处。然后,进行测试,结果果真正常了。

+ i+ N! N) r4 `! [: H( n
其实就是一个配置代码顺序问题,卡了半天。
; B, @7 M9 }; H3 p, t
如果不是用LL库而是用HAL库可能就不太容易碰到这个问题。前面说过了,基于HAL库的API函数像个黑盒子,它帮我们处理了很多细节性、判断性的东西。
% R  Q+ H5 d" c+ O- r" ^
基于LL库组织的代码,相比HAL库组织的代码,代码精简、流程清晰、运行高效。不过,使用LL库做开发需要开发者对芯片各个模块的工作原理,操作流程有更清晰、更精准的了解,同时往往还需要开发者对应用相关的寄存器有更细致、深入的把握。
& |# n1 r% ~' S+ Q; V& L
而HAL库往往事先帮我们充分考虑到了基于硬件需求的操作流程、时序,基于软件层面的诸多事件及状态的互斥管理,以及不同STM32系列的代码兼容性,并做了很好、很全面的封装。所以我们在利用HAL库来实现相应功能时,往往无须对操作流程、时序以及寄存器本身做过多的了解就可以完成。从开发角度讲,利用HAL库往往比利用LL库能更快地完成任务,同时基于HAL库的代码也有更好的移植性,代价就是代码相对LL库要庞大些。对应STM32开发者而言,即使基于HAL库开发了一些STM32项目,对于芯片的诸多功能细节以及寄存器的了解往往可能比较有限。当然,这点因人而异吧,不可说死。
1 ^9 T, }" z1 [* Z
对于HAL库和LL库的选用,我们每个人可以根据自身情况来。比方,对芯片软硬件不熟悉时、任务紧急时先使用HAL库,等对芯片及库函数熟悉、任务不紧急时可以切换到LL库。或者说,只是做些功能性验证确认,使用HAL库组织代码也是非常快捷方便的。当然,一个工程里HAL库、LL库是可以同时并存的。另外,当我们对芯片寄存器、内核指令系统足够熟悉时,甚至可以尝试使用汇编语言做MCU编程开发。作为开发人员,基于HAL库组织代码和基于汇编指令组织代码实现相同功能时,对我们自身的挑战及相应的收获是不可同日而语的。

4 [/ x3 L9 e: v  }  ?& @
转载自:Miler
& y0 _( v. N5 `8 r8 v# b
收藏 评论0 发布时间:2023-1-11 14:04

举报

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