bluefishhttp://blog.yesky.com/Blog/vincentzhou/复制地址
公告栏
专注wince底层开发,学习linux 为生活而奋斗!
控制面板
日历
<2008年9月>
SuMoTuWeThFrSa
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011
留言簿(13)
文章分类
文章档案
日记档案
向强人学习

这两天让串口自发送的问题搞的差点疯掉。问题诡异之及,以前的一个版本,在自发送(tx和rx相连)时只能收到最后一个字节,改了下UCON之后可以自发送但是偶尔会丢发送字符串的最后一个字节(当然同时拌有另外的一些问题)。无奈又将UCON的值改为之前的一个版本,奇怪的是竟然可以自发送了。我向毛主席保证除了UCON的值之外没有动过其他的地方。

 

串口自发送的目的,是为了能处理(几乎)同时接收和发送,但是从驱动的实现原理上来讲是不可能绝对同时接收和发送的,因为一个串口只有一个外部中断,通过该中断可以判断是哪个串口发生了中断。至于是读或写中断是要在IST中根据子中断源寄存器来判断。这样也就是说实际上每次只能处理一个中断,因为如果是读子中断触发的话,需要将该串口外部中断和读子中断都要屏蔽掉(也就是说在IST处理读中断的过程中不会有同级的读写中断)。

 

写中断来的时候也是同理。

 

这样就可以很好解释为什么在115200波特率的时候丢数据的频率要比在9600波特率的时候高。然而同时又有一个奇怪的问题就是在38400波特率的时候自发送:第一次发送没有显示发送了多少个字节(也就是0),但是可以正常接收到数据并显示接收了多少个字节,也就是说实际上数据已经发送成功但是com_write没有返回。之后就不能再发送了。在关闭串口的时候才会显示第一次发送的字节数。

 

原因可能是因为38400的速度刚刚好。在串口发送完数据(也就是数据从fifo中到线上)会产生中断,不管这时是否已经完全发送完成,都要再处理一次这个写中断,如果确实没有数据可发了,才设置发送完成事件,这时com_write等到该事件并正常返回。如果在自发送的时候,在第一次发送的过程中,接收fifo一旦有数据就触发读中断,这样接着就要处理读操作,在读操作的过程中将发送完成所触发的中断给屏蔽了(还好这时数据已经发送完成了)。这样在SerialEventHandler中就没有机会去设置发送完成事件了。

 

丢数据的原因是在写操作的过程中线上的数据更新了接收fifo(也就是最后几个字节的会丢发送fifo比接收fifo大)
详细操作可见串口的mdd.c文件。接收和发送操作都是在SerialEventHandler这个中断派发函数中处理的。

 

关于串口自发送,在UCON寄存器中有个Loopback Mode位专用来设置自发送的,不过这个东西只能用来调试,没有什么实际价值。
最后将SerialEventHandler函数中处理接收部分加了临界区,以确保com_read(其中也有关于接收fifobuffer的临界)和SerialEventHandler中的接收fifobuffer同步。这样就都可以自发送,当然如果波特率太低,而接收的时间又太断(发送的太快)也会有部分字节丢失。

 

而发送部分由于直接是由DoTxData来处理,而这个函数中已经有了对发送fifobuffer的同步),所以这里就不用再加同步操作了。


作者:bluefish 阅读() 评论()  编辑 发表于:2008-05-19 13:15
相关内容
文章评论

暂无人对此文章发表评论!

发表评论
标题 *  
姓名 *  
内容 *  
   验证码: *       
       
版权声明:天极是本Blog托管服务提供商。如本文牵涉版权问题,天极不承担相关责任,请版权拥有者直接与文章作者联系解决。
Powered by:

Copyright © bluefish