2016-1遇到的问题及解决方案

一、上电屏幕闪烁问题的解决


1.  问题描述


       在开发板刚开机瞬间,屏幕会闪烁一下,几秒后开始显示开机LOGO,最后系统启动完成。感觉不爽,所以寻找原因,实施解决方案,本文将介绍解决此问题的方法。


2.  问题分析     


      基于ARM-LINUX的系统的启动流程为:bootloader最先启动,并进行相应初始化,最后把内核拷贝到内存并跳到那运行。通过串口调试信息可知,屏幕在刚开机闪一下的那个时间点为bootloader阶段,这个时候Linux内核还没开始加载。

      那么,为什么在bootloader阶段屏幕会闪烁一下呢,通过观察发现是LCD背光打开了一下,然后关闭了。查看原理图发现LCD背光和LCD屏幕是同一个电源控制,也就是说bootloader的目的并不是要打开背光电源炫耀一下,目的是把LCD打开一下。

      那么,为什么在bootloader阶段会打开LCD电源呢。我们都知道打开LCD电源即要初始化LCD,初始化LCD一般是在linux内核阶段做的工作,这里在bootloader阶段为什么也要做呢。

      通过,分析linux内核源码发现,初始化LCD是在Linux内核源码中进行,但是linux内核并不知道初始化哪种LCD,需要bootloader给它传递参数而确定调用哪个LCD驱动。所以,我们可以初步认为在bootloader阶段打开LCD电源并初始化LCD的过程是为了知道LCD型号,然后把这个型号通过向内核传递参数的方式传递给Linux内核。这就是为什么上电后屏幕会闪烁一下的原因。

     

3.  问题解决


     上述已明确问题并且找到问题产生的原因,这里介绍如何解决这个问题。

     最简单的方法就是在bootloader阶段关闭LCD和背光的电源,这样做不可行,主要原因是官方不提供bootloader源代码,无法修改。


     所以,本文通过软硬件结合的方法解决此问题。

     首先,用一根可用GPIO控制LCD电源(后面把LCD电源和背光电源统称为LCD电源) ,在默认状态下,通过硬件的方式控制LCD电源为关闭状态。这样在bootloader阶段初始化LCD肯定失败,因为LCD电源被强行关闭了。

     但是也不能一直关闭,在Linux内核初始化阶段,还得控制这根GPIO打开LCD电源,以便于初始化LCD。那么在什么地方打开LCD电源呢,肯定是在要显示开机LOGO前就要打开LCD电源,然后再初始化LCD,这样才能正常显示LOGO。

      问题又来了,就算在LOGO显示之前打开LCD电源,Linux内核由于不会收到bootloader传递给它的启动参数而不会初始化LCD,从而导致LCD不能使用。解决方法有如下三种:


(1)修改内核源码,在arch\arm\kernel\setup.c中的setup_arch函数中判断一下,如果bootloader没有给内核传递LCD相关参数,那么在那里加上参数,假装给内核传递参数了。为什么在这里修改可以查看文章《Linux内核启动流程笔记》。


(2)在第一次烧录bootloader、内核、文件系统时通过硬件的方式打开LCD电源,以后使用时可以把那部分硬件电路给去掉。这样做的原因是第一次烧录时bootloader会读取LCD参数,安装到ARM系统时会保存这个参数,以后就算没有接上LCD,bootloader也会给内核传递LCD相关参数。


(3)在用SD卡安装或usb安装ARM软件系统时,在命令行参数后面加上lcd=HD101的字样,这样安装的时候不用打开LCD电源,也会保存LCD相关参数,只是这些参数是固定的。本方法较简单,本文使用此方法。具体方法是修改SD卡烧录文件中的FriendlyARM.ini文件中:

Linux-CommandLine = root=/dev/mmcblk0p1 rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc ctp=2 skipcali=y ethmac=1C:6F:65:34:51:7E

改为:

Linux-CommandLine = root=/dev/mmcblk0p1 rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc ctp=2 skipcali=y ethmac=1C:6F:65:34:51:7E lcd=HD101


      在搭建LCD电源控制电路时,默认情况下LCD电源是关闭的。电源控制GPIO对应EXYNOS4_GPX3(6),当需要打开LCD电源时,此引脚应该设置为低电平,对应代码为:

gpio_set_value(lcd_power_gpios[6],0);


      电源控制的地方是在LCD驱动中的探测函数中,即\drivers\video\s3c-fb.c中的probe函数中打开LCD电源。注意EXYNOS4_GPX3(7)被HDMI的热插拔中断使用,在系统启动过程中没被设置,系统起来后,会被设置,所以如果要在系统启动的过程中要使用这根GPIO需要去掉HDMI的驱动;EXYNOS4_GPX3(1)被USB主控制器使用,这个不能去掉,所以不管是在内核启动过程中还是启动后,都不能使用EXYNOS4_GPX3(1)。

      在内核启动阶段控制GPIO后其稳定性还需要多测试。



、触摸屏卡死问题


独立思考5步:

第一步:抛弃结论和成见,只要事实。 

第二步:定义问题。去掉情绪化,让问题具体而明确。 

第三步:假设性思考。

第四步:反向推证。找到反面的材料证据,做正反两方面的资料比对。 

第五步:小组讨论。


1.  问题描述


      Linux系统启动后,使用触摸屏偶尔会卡死,频率为2-3天一次。PS:LCD显示正常,程序运行正常,只是屏幕触摸没响应。


2.  问题分析   

     触摸屏使用的通信接口是I2C接口,测量卡死时的SCL和SDA信号线的电平状态时发现scl一直为高、SDA一直为低(这样,主机检测到SDA线一直为低,就认为从机一直占用SDA线,所以会等待从机释放SDA线;从机检测到SCL一直为高,会等待主机拉低SCL线后才释放SDA线,即从机检测到scl线为低时才把sda线拉高释放SDA线;在I2C协议中规定,只有scl为低时,SDA线上的电平才能变化,scl为高时,SDA线上电平状态保持),大部分情况下这种问题都是I2C死锁问题,I2C死锁参见文章《I2C死锁原因及解决方法》。

    在本系统中产生I2C死锁的原因是电源纹波太大,恰好达到那个条件后就会产生I2C死锁。


3.  问题解决


     解决的方法有多种:

(1)使用模拟的I2C总线,不使用I2C控制器,因为I2C控制器是通过控制寄存器来操作,无法对SCL和SDA线直接控制,从而无法检测到SDA线是否一直为低。

(2)在I2C总线的SCL线或SDA线上接缓冲器,目的是当一定条件发生,缓冲器能断开总线并给两端发送时钟信号,并给从设备发送scl时钟使之恢复。

(3)重启I2C设备,这也是本文使用的方法。

     通过对触摸屏部分驱动程序的分析,发现如下结论:

     当触摸屏不能用时,串口终端还能打印出I2C读错误信息,并且是点了手指后才打印,不点手指不打印。说明I2C触摸屏的中断引脚还能正常触发,即I2C触摸屏里面的程序还在跑。当触摸屏不能使用时,点击触摸屏屏幕,触摸屏会给主控制器一个中断。主控制器触发中断后去读取I2C设备的触摸数据时,读取失败,所以串口终端就会打印出错信息。

     所以在读取数据错误次数达到一个阈值时,关闭通过主控制器控制一个GPIO以关闭触摸屏电源,然后延时5ms后再打开触摸屏电源,经过测试,卡死后进行这样的操作,触摸屏能恢复。这样做的前提是触摸屏被初始化一遍后,初始化数据存储在内部MCU的flash里面掉电不消失,除非重新配置。如果不是这样,每次给触摸屏断电后需要重新加载一遍驱动程序。

     上述主控制器使用的GPIO控制引脚为EXYNOS4_GPX1(7),经查验,此引脚在Linux内核中和文件系统和各应用程序中没有被使用。注意:在申请这个io资源时,不能在触摸屏驱动的探测函数中申请,如果那样申请会导致上电后触摸屏偶尔不能使用的情况,所以申请资源是在触摸屏卡死的时候申请并控制,因为这个时候整个系统早已启动,早已稳定,不容易引入其他问题。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值