Android休眠调试总结

一.无法休眠

               进入休眠后,如果系统不持有锁,将会写mem到/sys/power/state(可参考https://blog.csdn.net/mike8825/article/details/80420213),如果没走到这一步,即打印信息中没有suspend entry,说明系统持有锁,这时可将锁打印出来。内核已经实现了该接口,调用接口,可将下面的代码移植过去,就可找到具体的锁了。

#include <linux/module.h>
#include <linux/wakelock.h>
#include <linux/kthread.h>
#include <linux/suspend.h>
#include <linux/delay.h>

static struct wake_lock messages_wakelock;
static int print_thread_interval = 30;
static int sprd_deep_print_thread(void *data)
{
	unsigned int cnt = 0;
	while (1) {
		wake_lock(&messages_wakelock);
		if (!pm_get_wakeup_count(&cnt, false)) {
			pr_info("PM: has wakeup events in progressing\n");
			pm_print_active_wakeup_sources();
 
		}
		msleep(100);
		wake_unlock(&messages_wakelock);
		set_current_state(TASK_INTERRUPTIBLE);
		schedule_timeout(print_thread_interval * HZ);
	}
	return 0;
}

static int __init deep_sleep_debug_init(void)
{
	struct task_struct *task;
 
	wake_lock_init(&messages_wakelock, WAKE_LOCK_SUSPEND,"pm_message_wakelock");
	task = kthread_create(sprd_deep_print_thread, NULL,"deep_print_thread");
	if (!task)
		pr_info("%s, Failed to create print thread", __func__);
	else
		wake_up_process(task);
	return 0;
}

static void __exit deep_sleep_debug_exit(void)
{	
}

module_init(deep_sleep_debug_init);  
module_exit(deep_sleep_debug_exit);  
MODULE_AUTHOR("www");
MODULE_LICENSE("GPL");

  drivers/base/power/wakeup.c 

void pm_print_active_wakeup_sources(void)
{
	struct wakeup_source *ws;
	int srcuidx, active = 0;
	struct wakeup_source *last_activity_ws = NULL;

	srcuidx = srcu_read_lock(&wakeup_srcu);
	list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
		if (ws->active) {
			pr_info("active wakeup source: %s\n", ws->name);
			active = 1;
		} else if (!active &&
			   (!last_activity_ws ||
			    ktime_to_ns(ws->last_time) >
			    ktime_to_ns(last_activity_ws->last_time))) {
			last_activity_ws = ws;
		}
	}

	if (!active && last_activity_ws)
		pr_info("last active wakeup source: %s\n",
			last_activity_ws->name);
	srcu_read_unlock(&wakeup_srcu, srcuidx);
}
EXPORT_SYMBOL_GPL(pm_print_active_wakeup_sources);

休眠一段时间后,抓取内核信息,然后查找字符"active wakeup source"就可以知道谁持有锁了。

休眠失败(如某个驱动的syspend函数返回值不为0)

[ 1162.993597] PM: suspend entry (deep)
[ 1162.997519] PM: Syncing filesystems ... done.
[ 1163.054265] gnss_pm_notify event:3
[ 1163.057889] sprd-sensor sprd-sensorhub: status=3
[ 1163.062745] [ASoC: PCM ] sprd_pcm_pm_notifier, PM_SUSPEND_PREPARE.
[ 1163.069098] [ASoC: PCM ] sprd_pcm_pm_notifier, PM_SUSPEND_PREPARE.
[ 1163.075503] Freezing user space processes ... 
[ 1163.076758] sec-nfc 1-0027: sec_nfc_poll: info: 96dd3018
[ 1163.078915] PM: Wakeup pending, aborting suspend
[ 1163.086347] Freezing of tasks aborted after 0.010 seconds
[ 1163.091928] OOM killer enabled.
[ 1163.095297] Restarting tasks ... 
[ 1163.096082] sec-nfc 1-0027: sec_nfc_poll: info: 96dd3018
[ 1163.099011] done.

 

二.底电流大 

2.0 确认下初始上电的漏电流

接电源,不开机,如果漏电流不在参考范围内,需要进行排查。方法也比较简单,选择VBAT的网络,对该网络的芯片一个接一个进行摘除,如果电流正常了,就是该模块引起的。               

2.1 摘芯片能降低底电流的,一般比较容易排查问题

2.1.1 休眠后电流为30mA,由于audio PA的使能脚配置成高阻,导致使能脚没有拉低,PA仍在工作。

2.1.2 霍尔传感器唤醒后,如果中断脚配置没有配置成输入,也会导致底电流增大,因为传感器仍在工作。

2.1.3 没有关闭相应的LDO,导致芯片漏电(某些共享LDO,代码bug等)。

2.1.4 某些芯片,如果休眠时是断电的,但由于i2c休眠默认也是上拉的,会引起漏电。

2.1.5 某些芯片,就算不没有上拉io,也会漏电,这个不好排查,需要做实验来确认。

2.16 如果摘除了所有外设,只保留了最小系统,电流仍然很大,可以排查下电路的差异部分。比如展讯有32k和非32k(省成本,通过pmic输出32k波形,但功耗会大2mA)晶体方案,如果硬件问题导致软件识别晶体类型出错,就可能导致电流偏大。

2.2 射频部分没有正确配置(开飞行模式底电流正常)

                   cat /sys/kernel/debug/rpm_state vmin的值为0,看内核信息也正常休眠了,原来刷机后,要接sim卡来激活, 这是平台的bug,可通过高通提供的补丁修复。

2.3 功耗优化方法https://blog.csdn.net/mike8825/article/details/55823648

2.4 高通的文档(kba-170221213554_4_高通通用功耗温升优化技术期刊.pdf)

2.5 某些电源没有正确关闭(高通平台,通过ramdump抓取内存信息给高通分析,发现usb电源没有关闭)。 (ramdump抓取方法https://blog.csdn.net/mike8825/article/details/79219913)

2.6 遇到底电流大的情况,软件这边一般可以先用原始代码进行测试,如果底电流正常,一般是修改导致的。

2.7 底电流调试ok后,建议在当前代码打tag(也可保存刷机镜像),后期遇到的底电流异常可用来对比下,是不是主板差异导致的底电流异常,或是提供一个参考节点。遇到底电流为12mA的情况,回退到底电流正常的TAG,底电流也不正常。后来发现是硬件加了电源芯片,也没有通知我们来是适配。

2.8 lcd导致的底电流大https://blog.csdn.net/mike8825/article/details/89291465

2.9 部分机器底电流大,正常底电流2.5mA,异常的机器的底电流范围为2.5mA到4.2mA,因为机器都是进入休眠状态的,软件上无有效分析方法。通过电流拆解(分别将主板上的单路电源接稳压电源,对比分析),发现是DDR物料差异引起的(同一款ddr,待机电流差异)。

2.10 手机调试中,比较常见的是实网电流电流高,确保手机已校准,机器有接天线,信号强度满格(信号弱会导致平均电流高)。还高的话,可以让手机连接仪器(仪器会提供有标准的网络信号)。遇到不同地点,待机电流有差异的情况,最后发现是小区布网有问题。还不行,需要给cpu厂商分析了。

 

 

三.唤醒后硬件无法正常工作

3.1 记一次芯片休眠调试https://blog.csdn.net/mike8825/article/details/51763176

3.2  i2c死锁导致唤醒后,i2c无法正常工作(https://blog.csdn.net/mike8825/article/details/53454400

3.3 打电话过程中,熄屏后过阵子喇叭没有声音,对方手机仍能听到声音,说明射频仍在工作。然来为了省电,打电话的过程中ap侧会休眠,休眠时PA的使能脚被设置成了高阻,导致PA不工作了。让PA的使能脚在休眠的时候上拉,就能保持高电平了。在正常的休眠中,PA的使能脚已经拉低,由于是弱上拉,不会导致芯片漏电,对休眠电流没影响。(展讯)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值