一.潜在的危机
1.在uc/os操作系统中设计串口编程时,由于ISR和多个任务并发执行,情况比较复杂。尤其是接收状态为被动状态时,只能靠串行口中断来接收数据。
2.在进行串行通信时,双方遵循相同的通信协议。由于波特率不变,因此相邻两次串口中断的间隔时间基本固定。
3.在以下两种情况时会使接收过程出现错误:
Ø 第一种情况是系统关中断的最长时间大于相邻两次串行接收中断的间隔时间,这时将可能导致遗漏一次中断,造成数据丢失。
² 实时操作系统内核的关中断的最长时间是已知的,通常很短,它不是问题关键。
² 系统关中断的最长时间往往是由用户软件造成的,例如:我们编写的中断服务函数过于复杂,导致系统为了处理中断服务函数而导致关中断时间过长。
Ø 第二种情况是在串口程序正在运行期间有一个比它优先级更高的中断程序中断了串口程序。从而造成数据丢失。
² 在这里提一个概念:把不能响应串口接收中断的这段时间称为“死区”。
² 因此解决问题的关键是:死区时间不能比相邻两次串口中断的间隔时间长。
二.如何解决危机
l 任务在访问比较耗时的共享资源时不要采用关中断的方式(改成互斥信号量)。
l ISR要尽可能简短,将可以剥离的工作转交关联任务去完成。
(此处的设计方式和Linux中把中断分为上半部分,和下半部分的原理有着同工异曲的含义)
采用上面的方法来缩短死区时间。
另一中方法是:
加长相邻两次串口接收中断的间隔时间。
l 方法一:降低波特率,这个方法简单,但因此也导致通信效率的下将。其次,一般在进行串口编程时,波特率一般是固定的。因此此方法一般不太适用。
l 方法二:在波特率不变的情况下减少中断次数,达到加长相邻两次串口接收中断间隔时间的效果。
ARM芯片的串口具有16字节的缓冲区,可以设置每接收1,4,8,14字节产生一次中断。如果设置每接收8字节中断一次,则比1字节中断一次要延长8倍的中断间隔时间。
Tiger-John说明:
l 在使用有数据缓冲功能的串口编程后,比较容易满足相邻两次串口接收中断的间隔时间大于死区时间的条件,但仍然存在潜在的危险。
想要可靠的避免这场危机:必须要满足以下条件
² 相邻两次串口接收中断的间隔时间必须大于系统死区时间
² 接收缓冲区的空闲时间必须足够存放在“死区”时间内接收到的新数据。
< 若设置每接收8字节中断一次,则空闲空间也为8字节。由于死区时间比中断间隔时间短,故接收的新数据必然少于8字节,才不会出现数据丢失现象。
即在满足中断间隔时间大于“死区”时间的前提下,将中断条件设置为接收缓冲区的1/2,则死区时间接近中断间隔时间,接收过程是可靠的。