IMX6芯片简介
摘自互联网
http://www.ic72.com/ZhanHui/2013-02-01/209182.html
1. IMX6 soc 芯片架构图
IMX6 SOC
2. 串口的使用情况
IMX6 SOC系列芯片有5个异步串口可以使用,可以用于连接蓝牙,单片机,GPS模块等等外围芯片。串口的作用,就像神经系统一样,连接各个器官。因此串口通信的稳定性,还是非常重要的。
3. 串口接口定义
引用CSDN其他博客
http://blog.csdn.net/yangshuodianzi/article/details/8997478
这里要讨论的两点:数据传输和流量控制。
数据传输:
一般使用串口的场景,使用三个引脚就可以进行正常的数据传输,TX,RX和GND。比如IMX6的调试串口,此时也仅仅是为了满足打印log这个需求,并不要求一个字节都不能丢,毕竟仅仅是为了调试方便。
流量控制:
流量控制严格的讲,应该要区分软件流控和硬件流控。软件流控,指的是采用软件的方式,来控制数据流的传输与停止,从而来避免缓冲区的溢出,从而保障数据的安全。硬件流控,顾名思义,是由硬件层面直接参与的,软件配置使能之后,就可以无人值守自动运行的流量控制方式。
但是,在嵌入式芯片里面,往往引脚的数量都是很有限的,需要在各个功能模块之间进行复用,因此,流控相关的引脚可能已经被其他功能模块占用,无法开启流控。
4. 串口丢包错包可能原因分析
串口线的问题:
噪声干扰严重,导致数据某个比特位出现反转,1变成0,或者0变成1。造成这个问题的原因,一般是线路受损了,比如导线破损铜线外露,这个情况一般更换一根好的串口线一般可以解决。
串口FIFO溢出:
直接会造成丢一个或者多个字节的情况。造成这个问题的直接原因,一般就是CPU处理不及时,来不及从串口FIFO里面读取数据,从而造成FIFO溢出丢数据。一般情况下,串口驱动收数据是采用异步中断的方式来进行,来个中断,然后CPU就巴拉巴拉的去FIFO里面取数据,然后丢到TTY层。但是,如果在串口数据到来,但是CPU中断又来不及响应的时候,就会丢包。
5. Linux 内核驱动层面规避串口丢包
无硬件流控串口丢包发生时机点:
处理当前串口中断的CPU被其他中断抢占
IMX6系列CPU,默认的IRQ中断优先级,是中断号小的,优先级高,可以优先处理。所以,如果当串口的数据已经来临,FIFO接受到的数据,已经达到触发中断的阈值,此时应该是产生串口中断了,但是呢,此时此刻,刚好比其中断号小的其他中断:比如另外一个串口中断,或者MMC中断,刚好也有数据要处理,那么,中断号小的优先。
比如我手头的一台IMX6 4核机器上面的中断列表,有三个串口,中断号分别为:58,60,和62。其中58号中断,就要比60号中断优先处理。如果58号中断狂飙了,导致60号中断一直得不到处理,那么60号中断所在串口,就有可能发生FIFO溢出的情况,数据就丢了。
处理当前串口中断的CPU,内核的其他代码,关闭中断时间太长。
在内核代码里面,不乏有很多加锁的代码,目的是为了保证CPU访问目标代码片段的次序不被打断。当这个代码片段跟中断上下文紧密相关的时候,这个锁就需要关闭中断。如下这个代码片段,在调用__drain_alien_cache() 函数的前后,加上了spinlock_irqsave()和spinlock_irqrestore(),结合了spin_lock和中断关闭的操作。
static void drain_alien_cache(struct kmem_cache *cachep,
struct array_cache **alien)
{
int i = 0;
struct array_cache *ac;
unsigned long flags;
for_each_online_node(i) {
ac = alien[i];
if (ac) {
spin_lock_irqsave(&ac->lock, flags);
__drain_alien_cache(cachep, ac, i);
spin_unlock_irqrestore(&ac->lock, flags);
}
}
}
很显然,在中断关闭的过程当中,IRQ中断是得不到处理得,因为关闭中断得操作,把本地CPU中断给禁用了暂时,不会响应IRQ中断。因此,以这个代码片段为例,如果__drain_alien_cache()执行时间太长,而恰好在这段时间之内,串口来数据了又得不到处理,那么就有可能造成FIFO溢出,从而丢包。