https://blog.csdn.net/fff_ylg/article/details/70255729

摘自互联网

1. IMX6 soc 芯片架构图

163539343_1_20190613061531204

IMX6 SOC

2. 串口的使用情况

IMX6 SOC系列芯片有5个异步串口可以使用,可以用于连接蓝牙,单片机,GPS模块等等外围芯片。串口的作用,就像神经系统一样,连接各个器官。因此串口通信的稳定性,还是非常重要的。

3. 串口接口定义

引用CSDN其他博客

这里要讨论的两点:数据传输和流量控制。

数据传输:

一般使用串口的场景,使用三个引脚就可以进行正常的数据传输,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中断,刚好也有数据要处理,那么,中断号小的优先。

163539343_2_20190613061531438

比如我手头的一台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溢出,从而丢包。

- 规避方案: https://blog.csdn.net/u013095415/article/details/83991859

一个简单暴力直接的方法:将需要避免丢包的串口的中断,绑定到一个CPU上(echo "2" >> /proc/irq/38/smp_affinity),从而避免中断之间的干扰。另外,需要找到关闭中断的代码,确保其关闭中断时间不会太长,不然的话,丢包还是会发生的。

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐