分类: LINUX
2014-12-11 16:15:59
原文地址:Android无法睡眠调试记录 作者:steven_miao
一.前言
飞凌的开发板Android2.1版本有一个缺陷就是不能够睡眠,而我们的工程需要睡眠,故要不懈的解决问题。解决问题很简单就是,s3c6410_pm_enter函数中的returen 0 屏蔽,从linux2.6.28内核中将arch/arm/mach-s3c6410/pm.c 复制到arch/arm./mach-s3c6410中,同时需要修改arch/arm/plat-s3c/time.c中的s3c2410_timer_setup,就是在该函数最后一句中添加
__raw_writel(__raw_readl(S3C64XX_TINT_CSTAT) | (1<<4), S3C64XX_TINT_CSTAT);说白了就是使能timer。
二.记录
2.1request_suspend_state-> early_suspend-> suspend-> pm_suspend-> enter_state-> suspend_devices_and_enter
也许各位很奇怪上的一连串的函数是什么意思,其实就是系统睡眠的时候的一个函数调用流程。对于Android的睡眠机制,在这里不讲述本文仅仅是记录鄙人调试的过程记录。第一个bug很好看出来就是suspend_ops->enter即调用s3c6410_pm_enter函数时,竟然什么事都没有干就return 0 ,实在是是可忍孰不可忍,把这句话屏蔽后竟然发现最最要紧的几个函数竟然没有实现pm_cpu_prep,pm_cpu_sleep,我查看linux2.6.28的内核,发现这两个函数其实在arch/arm/mach-s3c6410/pm.c中定义,而在Android2.1中的内核中竟然没有,算了,不写了,直接copy过来就可以了。不过这个bug解决了,发现一个更烦人的bug就是睡眠了无法起床了,我也把s3c6410_pm_configure_extint中的唤醒中断改为我的中断就是不行。哎,现在麻烦了,现在连串口也没有办法输出,根本也没有办法解决。就将samsung.c中串口的睡眠和恢复屏蔽掉,同时将suspend_devices_and_enter中的resume_console放在device_resume上面,ok,串口终于又有输出了。古老的调试办法有用了到处加printk就行了,一个一个函数看哪个函数被卡了,device_resume->dpm_resume->resume_device发现在这儿卡住了,打印device的驱动名称发现在resume mmc时出问题,还以为是这个驱动有问题又开始漫长的printk之路,发现一个很奇怪的问题就是竟然是卡在mmc_delay上了,我刚开始也没有想到什么原因,就用傻瓜式的for来实现延时,同样的问题同样出现在fb的驱动上了。这时想想好像不对吧,哪儿有问题了,不过还是没有找到问题点在哪儿还是先用for解决。在所有的设备正常的resume后系统还是无法正常的工作。这时后蓦然发现resume devices的时间为0,因为在suspend_devices_and_enter中有以下几句代码来测试resume设备的时间。
suspend_test_start();
device_resume(PMSG_RESUME);
("resume devices");
static void suspend_test_start(void)
{
= ;
}
这时候发现其是采用一个全局变量来存储当前的,而suspend_test_finish则是在resume设备后将当时的jiffies减去suspend_test_start_time来计算resume设备的时间的。现在就大悟了,前面为什么mdelay不跑了,因为jiffies是不跑的,发现问题了。随后就是找jiffies在自加的,原来在timer_tick中,由该函数一直退到arch/arm/plat-s3c/time.c这个函数中,发现这个timer的resume是s3c2410_timer_setup,这时仔细查看这个函数发现这个函数在设置各个寄存器后并没有使能timer,添加使能,到此解决问题。
2.2 时钟问题在把上述问题解决后,会发现一个比较恶心的问题就是系统不运行了,睡眠前什么点唤醒后还是什么点。在这种情况下不得不去看rtc的驱动,才发现Android2.1下的rtc驱动在suspend的时候仅仅就是保存S3C2410_TICNT和将rtc的tick中断关闭,并没有保存rtc与系统时钟之间的差值,在resume的时候也没有恢复。这就导致了系统时钟在resume后与suspend时没有变化,在这里我们可以采用rtc来保存系统时钟与rtc的差值,在resume的时候重新恢复差值。其系统时钟本质不在运行,运行的只是rtc,只不过将rtc在suspend和resume其后的差值加到系统时钟上去而已。
三.总结
有问题并不可怕,可怕的是有问题不知道问题出在什么地方,这才是很悲剧的一件事。不过有问题发现问题不知道出在什么地方也不可怕,一步一步的确定问题点,一步一步的解决问题,不过也许解决问题的办法就是仅仅添加一两行代码。
发现问题 定位问题 解决问题