请选择 进入手机版 | 继续访问电脑版
查看: 3052|回复: 3

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

[复制链接]
  • TA的每日心情
    开心
    2018-2-6 09:20
  • 签到天数: 1 天

    [LV.1]初来乍到

    1024

    主题

    4132

    帖子

    3

    精华

    管理员

    最后登录
    2018-4-24
    发表于 2016-7-12 14:44:41 | 显示全部楼层 |阅读模式
    串口工作在DMA模式下有时接收异常

    前言
    客户反馈在使用STM32F205的串口工作在DMA模式时,有时能够接收数据,有时完全没有数据,但如果换成中断模式来接收又能100%正常收到数据。

    一 复现现象
    问题背景
    与客户沟通,客户使用的是STM32F2标准库V1.1.0,串口波特率为1.408Mbps,不经过串口RS232,直接连接主CPU和从MCU(STM32F205)的串口发送和接收引脚,如下图所示:

    1.png

    尝试重现问题
    由于客户使用的是主从架构,实验采用两块STM3220G-EVAL评估板来重现现象。一块用来不间断发送串口数据,另一块采用串口DMA进行接收,直接通过杜邦线连接串口PIN脚并共地,不使用评估板上的RS232收发器。接收端使用STM32F2xx_StdPeriph_Examples\ USART\USART_TwoBoards的示例代码。代码片段如下:

    2.png

    3.png

    USART_Config()函数如下:

    4.png

    5.png

    6.png

    按如上代码,有如下现象:
    1 代码不做修改,若先启动接收端MCU再启动发送端MCU,接收端MCU的串口能正常接收。
    2代码不做修改,若先启动发送端MCU再启动接收端MCU,接收端MCU的串口100%接收异常。
    3 修改发送端代码,改为发送端MCU串口每1秒间隔发送一次,则无论启动顺序如何,接收端MCU的串口都能正常。

    二 程序分析
    由上述代码可知,程序是先在USART_Config()函数函数内初始化串口并使能,然后再在接下来的main函数的while循环内初始化DMA并使能。这个是标准库内附带的示例代码,咋一看没什么问题,但仔细一想,针对用户的使用场景,这里就会产生一个问题:由于用户的主CPU有可能在从MCU启动之前就已经有可能启动,那么在这种情况下,在初始化完串口并使能后,到DMA使能之前这段时间内,若主CPU向从MCU发送串口数据,从MCU是否能正确接收?

    从上述测试代码的结果2可以得出,若在串口初始化并使能后到DMA使能之前有数据来,MCU是不能接收的,经进一步调试,发现此时数据寄存器USART_DR存在一个数据,且在状态寄存器USART_SR中ORE值1,由此可知,串口的接收寄存器中已经接收到一个数据,但是后面的数据又来了,由于数据寄存器中的数据没有及时转移走(此时DMA还没有开启),从而导致后面的数据无法存入,所以产生了上溢错误(ORE),而一旦产生上溢错误后,就无法再触发DAM请求,及时之后再启动DMA也不行,无法触发DMA请求就无法将数据寄存器内的数据及时转移走,如此陷入死锁,这就是串口无**常接收的原因。这时反观一下代码的结果3,这又将做如何解释?

    仔细查看测试结果3,发现这个发送端每1秒间隔发送一次,那么就会存在这个一个概率,这个发送的时间点是否刚好在接收端MCU的串口初始化并使能和DMA使能之间还是之后,这个时间窗口非常关键,如果刚好在时间窗,那么串口接收就不正常,如果在这个时间窗之后,串口接收就能正常。由于测试代码采用的是1秒间隔,对于MCU来说这个是非常大的时间长度,还是很小概率能碰中这个时间窗的,因此,测试结果看起来是都能正常,实际严格来说,还是存在刚好碰中的可能。如果间隔时间缩短,那个碰中的几率就增大。由此看来,这也就能解释测试结果3了,也能解释客户提到的有时正常有时不正常的现象了。

    三 问题处理
    处理有两种方法,第一种方法是在使能DMA后,及时将数据寄存器DR中的数据清除掉,如下代码所示:

    7.png

    这里是使用读DR的方法来清除的,从参考手册中也提到使用这种方法来清除ORE标志:

    8.png

    第一种方法类似于一种纠错措施,下面介绍另一种推荐的方法,如下代码所示:

    9.png

    如上所示,可以先使能DMA再使能串口,这样就彻底不存在那个时间窗了,不管数据何时过来能能被DAM及时转走。这个是推荐的解决方法。

    四 结论
    标准库中的示例代码一般来说只供参考,对于大部分情况来说都是能正常工作的,但偶尔也会出现不适用的情况,此时更需要我们针对问题进行思考分析,进一步找到原因才能解决问题。对于串口使用DMA来接收的情况,这里建议一定要先使能DMA,最后使能串口,这样就能避免类似问题出现了。


    文档下载地址:
    http://www.stmcu.org/document/detail/index/id-217182


    实战经验汇总:
    http://www.stmcu.org/module/forum/thread-576401-1-1.html

    回复

    使用道具 举报

    该用户从未签到

    8

    主题

    33

    帖子

    0

    精华

    中级会员

    最后登录
    2017-10-12
    发表于 2017-3-24 17:47:42 | 显示全部楼层
    我们也发现了同样的问题,既然ST知道了有问题,怎么不更新库文件呢?
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    0

    精华

    新手上路

    最后登录
    1970-1-1
    发表于 2017-7-17 13:30:20 | 显示全部楼层
    厉害,基本也是类似的问题,搞了很久
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    1

    主题

    9

    帖子

    0

    精华

    初级会员

    最后登录
    1970-1-1
    发表于 2017-9-27 18:31:02 来自手机 | 显示全部楼层
    我用的是103的片子,也遇到一个问题,不过是发送的,特定长度,最后一个字节不对!苦逼呀!!!
    回复 支持 反对

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    小黑屋|手机版|Archiver|意法半导体STM32/STM8技术社区

    GMT+8, 2018-4-25 05:11 , Processed in 0.119563 second(s), 12 queries , MemCache On.

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表