Imx8串口故障案例分析

        最近解决一故障——在imx8qxp单板按“上下键”或者粘贴较长命令均会导致系统死机。最后查出来是驱动移植问题。在此做下记录,免得以后忘记,也对以后有类似串口问题提供一个参考。

        故障描述已经比较清楚,只出现在imx8qxp单板,所以跟单板是有关系的。只在“上下键”或其他功能键如“HOME、END”等以及粘贴较长命令情况下出现,而其他普通输入按键没有问题,可以从这几个功能键的差异入手。

        网上查阅资料发现这几个按键都是由一连串字符组成的,不单单是一个ASCII键值,程序段实例如下:

case KEY_CURSOR_UP:       hit |= add("\033[A"); break;

case KEY_CURSOR_DOWN:   hit |= add("\033[B"); break;

case KEY_CURSOR_LEFT:     hit |= add("\033[D"); break;

case KEY_CURSOR_RIGHT:    hit |= add("\033[C"); break;

case KEY_CURSOR_HOME:    hit |= add("\033[1~"); break;

case KEY_CURSOR_END:      hit |= add("\033[4~"); break;

case KEY_PAGE_UP:          hit |= add("\033[5~"); break;

case KEY_PAGE_DOWN:       hit |= add("\033[6~"); break;

case KEY_INSERT:            hit |= add("\033[2~"); break;

case KEY_DELETE:           hit |= add("\033[3~"); break;

case KEY_F1:                hit |= add("\033OP"); break;

       其中‘\033’就是ESC,所以“UP键”就由ESC、[、A三个字符组成,也就是你在串口终端敲击一个“UP键”,实际上是同时送给串口三个字符‘ESC’、‘[’、‘A’。

        在程序中打点调试,发现每当按下“UP键”时,串口驱动程序只能收到‘ESC’、‘[’字符,第三个字符怎么也收不到,更糟糕的是后续所有按键都会丢失。整个串口模块处于“假死”状态。为什么说“假死”,是因为我的整个功能模块是正常运行的,打印这些都是正常的,只是按键没有反应,也就是读不到键值,串口中断都可以正常的收到。

        对比linux驱动,发现imx8系列都用同一个驱动程序,路径在drivers/tty/serial/fsl_lpuart.c。在初始化流程中会对串口的读写中断、FIFO、DMA以及WATERMASK等功能进行设置。我们的系统中为简单起见并没有使能FIFO、DMA及WATERMASK等功能,只用其来实现简单的按键收发而已。我们的初始化流程也并没有问题。

        无赖只能将串口所涉及的寄存器打出来对比,看正常情况和“假死”情况状态寄存器能不能给出一些提示。果然,打寄存器才是发现硬件故障的核心手段。“假死”情况状态寄存器中设置了一个“OR”标志位。手册中对这个标志位是这样描述的:

Imx8串口故障案例分析_第1张图片

       注意其中高亮显示的那句话——当ORflag被置位时,即使数据缓存中有足够的空间,也不会有数据往里面存。

       难怪后面的按键都没有反应,原来是OR这个标志被置位了。那什么情况下,OR标志位会被置位呢?上图中也给出了描述,就是接收数据的寄存器溢出了。

       回想下故障现象,“UP键”会同时给出3个字符、粘贴较长命令也相当于同时发送了较多字符,这让默认只有一个字符的数据寄存器怎么来得急接收。

       找到问题之后,果断将linux中的使能FIFO功能的程序段copy过来,验证一下,OK,问题得到解决。本来还想在OR标志被置位后,来个清除处理的,后来看linux貌似也没有处理,只是将overrun计数器进行了++操作,也就作罢。本来一旦出现OR标志,即使清楚了对后续串口输入不会有影响,但丢失的数据还是找不回来,而且还会隐藏故障现象。那就这么地吧。

你可能感兴趣的:(总线驱动程序)