IMX6 Linux系统下串口丢包错包问题研究二之进一步分析原因

 

前一篇文章分析到了中断之间可能相互影响,导致一个中断执行的时候,另外一个中断得不到及时的相应,从而可能导致串口中断在没有硬件流控的情况下,FIFO溢出导致丢包的情况。

串口接收数据过程

IMX6 Linux系统下串口丢包错包问题研究二之进一步分析原因

 串口FIFO最短溢出时间:t = ( FIFO字节数 × (8 + 协议开销比特数) ) / 波特率,以IMX6为例,设置串口模式为 115200 8N1,串口接收FIFO大小为32字节,那么 溢出时间 = (32 x 11) / 115200 =  0.0030555555555555557 ~= 3.06 毫秒。而产生CPU中断的时候,FIFO里面已经有一些数据了,所以从串口发生中断,到CPU响应并处理中断的时间,必须小于溢出时间。

单CPU核处理中断,中断之间干扰,有溢出可能

IMX6 Linux系统下串口丢包错包问题研究二之进一步分析原因

 某一时间,CPU0正在处理EMMC中断,由于EMMC数据量传送比较大,CPU0需要较长时间来处理。在处理的过程中,串口异步的接收到了数据,并且达到了引发中断的阈值,但是由于CPU0当前还处在EMMC中断中,无法响应串口中断,因此,只能延迟处理。

 内核代码,主动关闭中断,有溢出可能:

IMX6 Linux系统下串口丢包错包问题研究二之进一步分析原因

 

 在内核代码中,有很多地方需要主动的将当前CPU的中断暂时的屏蔽掉,来处理一些竟态操作,比如:local_irq_save(),local_irq_restore(),这时候,CPU将暂时无法响应中断。如果这时候串口数据来了,但是得不到及时的处理,那么也将有溢出的可能。

 将串口中断单独绑定到另外一个处理器核上,降低溢出可能:

IMX6 Linux系统下串口丢包错包问题研究二之进一步分析原因

 

 IMX6这个平台,跑linux的时候,IRQ一般都放置在CPU0上面进行处理,这加剧了中断之间的干扰,增加了串口FIFO溢出的可能性。但如果将串口中断绑定到CPU1上面进行处理,这将大大降低中断之间干扰的可能性。

 串口中断绑定到CPU1上面后,因主动屏蔽中断,还是有溢出可能:

IMX6 Linux系统下串口丢包错包问题研究二之进一步分析原因

 

 找出主动屏蔽中断时间过长的点,将进一步降低串口FIFO溢出的可能性:

 由于多核的原因,内核代码将同时运行在两个CPU核上(或者更多核),类似于local_irq_save(),local_irq_restore()这样的代码,也将同时运行在多个CPU核上,从而还是带来了跟串口中断某种程度上的竟态关系。溢出还是存在可能性的。

所以,要进一步降低串口FIFO溢出的可能性,那么得想办法测量,找出主动关闭中断代码所在的位置,并且降低占用时间的长度,可能是某种优化,也可能是改变一下实现的方式。