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

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

【实战经验】串口工作在DMA模式下有时接收异常

[复制链接]
zero99 发布时间:2016-7-12 14:44
串口工作在DMA模式下有时接收异常

$ Z9 ~0 o* u# e, Z8 e前言
( j# {1 ?9 g8 t4 I  T客户反馈在使用STM32F205的串口工作在DMA模式时,有时能够接收数据,有时完全没有数据,但如果换成中断模式来接收又能100%正常收到数据。5 c) D% a; z6 c7 c3 B* z2 n2 ?* ?1 `
; ?. K' |/ E5 U8 t3 E) d
一 复现现象
8 B8 I* k$ I9 q6 g/ i0 V8 H: g问题背景
; Y& F# O7 {, }4 L* T% U与客户沟通,客户使用的是STM32F2标准库V1.1.0,串口波特率为1.408Mbps,不经过串口RS232,直接连接主CPU和从MCU(STM32F205)的串口发送和接收引脚,如下图所示:# J9 N5 M5 v6 m

' y4 W1 t& K# f0 ]5 _* ]2 J# J 1.png 8 r- K" f1 @- E/ I1 t% l1 X

% s! j  o5 u6 \1 U尝试重现问题4 V! d3 r( w, Q) ^' B2 C
由于客户使用的是主从架构,实验采用两块STM3220G-EVAL评估板来重现现象。一块用来不间断发送串口数据,另一块采用串口DMA进行接收,直接通过杜邦线连接串口PIN脚并共地,不使用评估板上的RS232收发器。接收端使用STM32F2xx_StdPeriph_Examples\ USART\USART_TwoBoards的示例代码。代码片段如下:
  k9 ?& B& ^- H) r3 D# z' T' F" S) D/ O+ H: b- V: D/ K
2.png $ |: Z0 V4 ^; N1 q: C

' b4 U) H( I$ v 3.png * N! D" B' t. f9 C! a4 j

9 k/ j2 g4 o% h! qUSART_Config()函数如下: 6 E  n0 l- M6 S5 G% n: }: U5 x4 R/ `
; B1 b  s3 S  |
4.png , ^6 z5 M" d3 v# \( [

. N, c/ `/ Q* w; S% |" l# r/ Z  b 5.png ; a7 \" `3 ~- F9 |4 J# o$ K
7 B/ O3 V' p3 S5 h2 s$ v
6.png 3 i8 \  G3 ]% G( N: V9 |$ [
0 }0 D/ @) b# ]- E# s  s% [
按如上代码,有如下现象:
* T7 T, U7 d+ d  s' n  H1 代码不做修改,若先启动接收端MCU再启动发送端MCU,接收端MCU的串口能正常接收。$ `% |& n' t- S4 f
2代码不做修改,若先启动发送端MCU再启动接收端MCU,接收端MCU的串口100%接收异常。
+ U7 X- }2 V+ }! H3 修改发送端代码,改为发送端MCU串口每1秒间隔发送一次,则无论启动顺序如何,接收端MCU的串口都能正常。
, M+ R% l% ?2 F
2 s( j; Y0 b5 e( y$ v7 V二 程序分析
* B& I: _, G9 `由上述代码可知,程序是先在USART_Config()函数函数内初始化串口并使能,然后再在接下来的main函数的while循环内初始化DMA并使能。这个是标准库内附带的示例代码,咋一看没什么问题,但仔细一想,针对用户的使用场景,这里就会产生一个问题:由于用户的主CPU有可能在从MCU启动之前就已经有可能启动,那么在这种情况下,在初始化完串口并使能后,到DMA使能之前这段时间内,若主CPU向从MCU发送串口数据,从MCU是否能正确接收?
+ X. P2 c5 |6 h2 ]3 v% W) L
; v: f) g3 J" m# H% N$ k" j从上述测试代码的结果2可以得出,若在串口初始化并使能后到DMA使能之前有数据来,MCU是不能接收的,经进一步调试,发现此时数据寄存器USART_DR存在一个数据,且在状态寄存器USART_SR中ORE值1,由此可知,串口的接收寄存器中已经接收到一个数据,但是后面的数据又来了,由于数据寄存器中的数据没有及时转移走(此时DMA还没有开启),从而导致后面的数据无法存入,所以产生了上溢错误(ORE),而一旦产生上溢错误后,就无法再触发DAM请求,及时之后再启动DMA也不行,无法触发DMA请求就无法将数据寄存器内的数据及时转移走,如此陷入死锁,这就是串口无**常接收的原因。这时反观一下代码的结果3,这又将做如何解释?0 q, Y9 x' f' m( f' i0 [1 T6 z+ F  L

0 {5 [$ Z1 {3 e仔细查看测试结果3,发现这个发送端每1秒间隔发送一次,那么就会存在这个一个概率,这个发送的时间点是否刚好在接收端MCU的串口初始化并使能和DMA使能之间还是之后,这个时间窗口非常关键,如果刚好在时间窗,那么串口接收就不正常,如果在这个时间窗之后,串口接收就能正常。由于测试代码采用的是1秒间隔,对于MCU来说这个是非常大的时间长度,还是很小概率能碰中这个时间窗的,因此,测试结果看起来是都能正常,实际严格来说,还是存在刚好碰中的可能。如果间隔时间缩短,那个碰中的几率就增大。由此看来,这也就能解释测试结果3了,也能解释客户提到的有时正常有时不正常的现象了。" o4 j0 {4 R) u! m9 K; n2 Q' }" y
. R" w* e3 s* Z; i+ y
三 问题处理
( A0 j' g# o; L1 Z处理有两种方法,第一种方法是在使能DMA后,及时将数据寄存器DR中的数据清除掉,如下代码所示:% \2 p8 P3 v# ?+ B# l6 l1 U
1 O* }6 q8 o# c, Y2 X
7.png 0 w' M% e* L, F8 g0 r1 }) C
5 r9 V0 X- y2 c+ }3 b
这里是使用读DR的方法来清除的,从参考手册中也提到使用这种方法来清除ORE标志:
1 q# d: Q% E! `2 y' f, ]: [
* ]7 J& R% f- ]" r* X; a! X9 v: R 8.png
$ S! i3 e" X4 U, j# F# d; Q7 Q1 `2 I) a4 @2 X- {8 w; x
第一种方法类似于一种纠错措施,下面介绍另一种推荐的方法,如下代码所示:
- X$ n! I+ J3 D* [
  y& z: d6 v7 l& ?! a3 f; ~7 N, Z 9.png ( p1 x% Z- ]1 a# J+ O# i6 ]/ \! ^
$ y  g) _( [. B9 u/ W2 a
如上所示,可以先使能DMA再使能串口,这样就彻底不存在那个时间窗了,不管数据何时过来能能被DAM及时转走。这个是推荐的解决方法。1 ~6 }; D. t0 R3 p
, W; y' i: D* L6 t
四 结论9 U3 a9 o+ q( @$ a
标准库中的示例代码一般来说只供参考,对于大部分情况来说都是能正常工作的,但偶尔也会出现不适用的情况,此时更需要我们针对问题进行思考分析,进一步找到原因才能解决问题。对于串口使用DMA来接收的情况,这里建议一定要先使能DMA,最后使能串口,这样就能避免类似问题出现了。
3 M3 g# C+ s( [( C/ M+ f4 Q
' S' e' V' Q% u, k8 n) v8 F* Z' y; ?: V8 ?$ V6 m2 ~- {
文档下载地址:3 m1 A  Y8 p( P& G3 T0 x
https://www.stmcu.org.cn/document/detail/index/id-217182

8 T: P$ t: @, J8 n. [  U: `0 u$ K) F2 K
实战经验汇总:+ o- |5 L- p; V/ e- X; @
https://www.stmcu.org.cn/module/forum/thread-576401-1-1.html
  N& Z" z, y+ J7 t+ K! K2 T  Z
, a) H; l. j9 i9 l& l( L0 m8 C+ X3 s" j
收藏 4 评论7 发布时间:2016-7-12 14:44

举报

7个回答
leiyijing 回答时间:2017-3-24 17:47:42
我们也发现了同样的问题,既然ST知道了有问题,怎么不更新库文件呢?
faye1 回答时间:2017-7-17 13:30:20
厉害,基本也是类似的问题,搞了很久
Abners 回答时间:2017-9-27 18:31:02
我用的是103的片子,也遇到一个问题,不过是发送的,特定长度,最后一个字节不对!苦逼呀!!!
任风吹吹 回答时间:2018-5-9 10:09:34
leiyijing2003 发表于 2017-3-24 17:479 E0 o! y' z# ^4 r+ _  W% O
我们也发现了同样的问题,既然ST知道了有问题,怎么不更新库文件呢?
- l2 i2 H; q7 U! L5 `8 p
这个属于应用层代码调用顺序问题,为什么要更新库?看懂了再说话
Nikola 回答时间:2018-11-22 09:53:39
不错,支持下
@LARRY@ 回答时间:2018-12-28 09:47:17
Abners 发表于 2017-9-27 18:31/ @5 k' G/ }6 F. E
我用的是103的片子,也遇到一个问题,不过是发送的,特定长度,最后一个字节不对!苦逼呀!!! ...

) |: ]0 V- b4 e# t- c$ e$ f, I你可以在DMA发送完成后检查一下串口是否空闲,因为DMA发送完了之后串口还要1到2个字节的时间,判断下串口发送完成标志位就好了
liudawei123 回答时间:2019-9-12 11:34:44
非常不错哦,支持下

所属标签

相似分享

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