Android功耗调试汇总

1. 工具准备

1.1 安装QXDM
1.2 安装QPST(确认DCVS 使能时需要查看efs 文件,下载nv 也需要使用QPST)
1.3 电流源(带GPIB 卡接口)/电流测试软件

测试环境相关 :
◆ 电流表或数字电源本身的电流误差是多少,并保证其工作正常,感觉有问题时,可以换表尝试
◆ 要正确设置DRX、MFRM、T3212等参数,可以参考高通文档80-VE263-8
◆ 综测仪分CMU200、Agilent 8960等多个厂家型号,可以判断一下是否综测仪相关
◆ 在屏蔽房内和屏蔽房外分别进行测试,看是否有所区别

高通文档参考:
◆《80-P0955-1SC_功耗调试通用指南》
  很详细的功耗debug 中文手册,里面有各种case debug的步骤,以及如何来抓取各种 log 。功耗优化的必备资料。
◆《80 -P0956 -1》Android功耗概述
◆《80-N6837-1_M_Power_Consumption_Measurement_MSM_Android_MDM_Devices》
◆《80-NL239-48_POWER CONSUMPTION OPTIMIZATION AND DEBUGGING FOR MSM8916 DEVICES》
◆《80-N9858-1_MODEM POWER CONSUMPTION DEBUGGING METHODS》



2. 测试机设置

2.1 NV 项设置
需要修改的NV项设置如下:
Android功耗调试汇总_第1张图片
2.2 禁掉netstats 功能
To disable the data monitor “Netstats” for Jelly Bean(JB)/Ice Cream Sanwich(ICS):
◆ 打开ADB shell,输入如下命令:
adb shell ndc bandwidth disable
◆ 检查data monitor是否已经关闭:
adb shell iptables -L
显示如下:
Android功耗调试汇总_第2张图片
2.3 编译performance boot 版本
保证禁掉了所有的debug 和logging 功能。在编译release 版本
时内核配置文件应选用“perf_defconfig”替换“defconfig”文件,或者在“defconfig”文件中删
除debug 调试相关的宏定义。
Remove “Debug” features
Double check if “CORESIGHT” config is removed
Double check if “CONFIG_MSM_DEBUG_LAR_UNLOCK” config is removed

2.4 删除不必要的高频率的调试打印日志
设置串口打印等级:
echo 8 > /proc/sys/kernel/printk 并查看是否生效:
cat /proc/sys/kernel/printk
8 6 1 7

2.5 在国内测试电流需要首先排除GMS 的影响
由于国内GMS 连接不上Google 服务,GMS 一直持有wakelock锁不释放,这会导致手机的待机电流偏高。需要在测试前连接专门网络(如CTS/GTS WIFI),同步Google 账号后,查看电流是否降到3mA 左右。VPN 连接成功后,状态栏会显示小锁。

2.6 RBCPR feature
RBCPR feature对功耗非常重要,请确保测试功耗的版本里面没有禁止掉VDD_APC, VDD_CX, VDD_MX, VDD_MODEM CPR feature。具体检查方法请查看《功耗调试通用指南》“ 如何确认CPR 工作状态” 章节。



3. 调试过程

3.1 底电流

3.1.1 分析底电流波形

波形分析对功耗调试至关重要,能够提供问题的本质和正确的调试方向的信息。

底电流波形主要分为以下两个部分:
◆ 基底电流:系统处于XO关闭和VDD最小化时的最小电流,此时XO是关闭的,各路LDO电处于最小化的状态。
◆ 唤醒,例如电量计唤醒和PMIC看门狗唤醒
下图是捕捉自MSM8994芯片组的底电流用例波形的快照。
Android功耗调试汇总_第3张图片
将捕捉的底电流波形与高通的QTI参考波形相比较,从而确定底电流是否较高,并且/或者是否出现异常唤醒。

3.1.2 验证系统是否进入XO关闭和VDD最小化

XO关闭和VDD最小化计数的adb shell命令有如下两种方式:
■ 输入以下命令获取RPM状态数据:
mount -t debugfs none /sys/kernel/debug
cat /sys/kernel/debug/rpm_stats (OR) cat /d/rpm_stats
cat /sys/kernel/debug/rpm_master_stats (OR) cat /d/rpm_master_stats

以下内容是上述命令的输出:计数代表XO关闭和VDD min出现的数量。
RPM Mode:xosd (仅当系统未成功进入VDD min而进入了XO关闭时,XOSD计数才会增加)
count:0
time in last mode(msec):0
time since last mode(sec):791
actual last sleep(msec):0
client votes: 0x00020001

RPM Mode:Vdd Min
count:28
time in last mode(msec):8000
time since last mode(sec):475
actual last sleep(msec):233000
client votes: 0x00000000

■ 或者检查以下RPM RAM转储的变量,以确定XO关闭和VDD最小化的计数。
– sleep_stats[0] – XO关闭计数(系统进入XO关闭的次数)
– sleep_stats[1] – VDD min计数

注意: 若系统进入VDD min状态,则只有VDD min计数会增加。VDD min是最低的功耗状态,包含XO关闭。
仅当系统未成功进入VDD min而进入了XO关闭时,XO关闭计数才会增加。


3.1.3 电流问题概分

影响底电流的原因有如下方面:
Android功耗调试汇总_第4张图片
按照上图的分类先定位电流大的原因是软件问题还是硬件导致的,可以先切换到飞行模式,该模式下,射频相关的底层与上层模块均已关闭,没有DRX等操作,所测得的低电流应该很稳定。这样就可以很精确的对手机的低电流相关问题进行分析与调试。可以方便分析AP、modem等子系统是否进入了待机模式来区分大的方向。

3.1.4 检查飞行模式下的各路LDO

参考高通平台提供的飞行模式下的LDO通断以及消耗情况(对应平台的linux_android_current_consumption_data文档),对比测试自己的样机状态,确认有哪些LDO没有关闭,或者是消耗过大;甚至是外围器件的倒灌消耗。以8953为例,参考如下:
Android功耗调试汇总_第5张图片Android功耗调试汇总_第6张图片
Android功耗调试汇总_第7张图片

3.1.5 检查单个子系统的休眠

3.1.5.1 确认APSS是否待机

  APSS不能休眠的原因有如下3个:
  ■ 应用或进程没有结束
  ■ 应用或进程没有释放时钟或者电源的资源(RPM)
  ■ 频繁中断

调试的方式有如下几种:
(1) 查看休眠log
修改kernel 打印等级,查看kernel log,可以确认AP 是否待机,参考如下:

[ 1043.284883] PM: Syncing filesystems ... done.
[ 1043.292613] Freezing user space processes ... 
[ 1043.297018] Error: returning -512 value
(elapsed 0.009 seconds) done.
[ 1043.307019] Freezing remaining freezable tasks ... (elapsed 0.004 seconds) done.
[ 1043.317585] Suspending console(s) (use no_console_suspend to debug)

(2)唤醒锁
查看wakelock,确认是否持有锁:
Android wakelock 分为两层:内核层和应用层

■内核层: 查看linux 的waklock
  cat /sys/power/wake_lock
  PowerManagerService.Display
  PowerManagerService.WakeLocks

PowerManagerService.Display这是屏亮状态下PowerManagerService 对linux 层设的wakelock;PowerManagerService.WakeLocks这是应用层设的wakelock,所有应用程序设的wakelock 在linux 层表现成这个wakelock。PowerManagerService 会维护所有应用程序的一个wakelock 表,当不为空时,向linux 层设置PowerManagerService.WakeLocks;为空时,取消这个PowerManagerService.WakeLocks。

■应用层:查看应用程序 的waklock
确认有PowerManagerService.WakeLocks 后查看应用程序 的waklock,参考如下:
dumpsys power
Wake Locks: size=1
PARTIAL_WAKE_LOCK ‘import_contacts’ (uid=1000, pid=4784, ws=null)
上图显示的是import_contacts应用持有锁。

(3) 检查抑制XO关闭和VDD最小化的时钟
■ 要检查抑制XO关闭/VDD最小化的时钟,输入以下命令以启用时钟调试挂起:
echo 1 > /d/clk/debug_suspend
启用该标记后,系统进入挂起模式后将在dmesg日志中显示已启用的时钟。
■ 按下电源按钮三到四次以挂起并恢复系统,然后输入以下命令获取dmesg日志:
adb shell dmesg
在该日志中,某些(常规)时钟应始终显示为已启用,若常规主要系统时钟之外的时钟显示为已启用,则可能就是抑制电力休眠的原因。以下时钟是不应在该日志中显示的时钟示例:
 外设时钟
 与显示相关的时钟
 与多媒体子系统相关的时钟等
已启用时钟的比较 – 参见下图:
Android功耗调试汇总_第8张图片
可以观察到,如图左侧的时钟日志所示,有27个时钟显示为已启用,但系统却在没有任何问题的情况下进入了XO关闭/VDD最小化。RPM稍后会关闭这些时钟/PLL,这些时钟是BIMC、系统总线和子系统PLL等主要共享资源的一部分。

如图右侧的时钟日志所示,有35个时钟已启用,但少数时钟具有区别性特征。
– APSS请求CXO时钟源。
– MDP(显示子系统)时钟已启用,表明驱动程序抑制了CXO进入电力休眠。

(4)检查中断
中断频率较高会抑制系统进入XO关闭/VDD最小化。

3.1.5.2 确认modem是否待机

可以配置RPM的log查看modem的sleep情况。详细查看《80-nl239-48 power_consumption_optimization_and_debugging_for_msm8916_devices》的2.1.5 Ensuring modem sleep。

3.1.5.3 检查wcnss是否待机

3.1.6 检查异常唤醒

3.1.6.1检查APSS的唤醒

启用适当记录功能的kernel日志能够指示APSS是否从其睡眠状态中唤醒以及唤醒原因(如果唤醒)。可以打开以下调试掩码,以便在kernel日志中记录中断信息:
echo 1 > /sys/module/msm_show_resume_irq/parameters/debug_mask
检查kernel日志中的输出数以确定哪个中断唤醒了APSS。以下代码段显示,是电源键按下中断qpnp_kpdpwr_status唤醒了APSS。

<6>[0414 06:51:27.872744]@0 @0 __qpnpint_handle_irq: 288 triggered [0x0, 0x08,0x0] qpnp_kpdpwr_status
<6>[0414 06:51:27.872751]@0 @0 gic_show_resume_irq: 200 triggered qcom,smd-rpm
<6>[0414 06:51:27.872758]@0 @0 gic_show_resume_irq: 203 triggered 601d0.qcom,mpm
<6>[0414 06:51:27.872765]@0 @0 gic_show_resume_irq: 222 triggered 200f000.qcom,spmi

3.1.7 检查外部器件的电流消耗

如果终端进入VDD最小化后,基底电流仍然大于预期值,则可以判断:终端中存在某个或者多个泄漏源,导致了总电流的消耗。可能有如下原因:
(1)睡眠期间未使用但启用了的SMPS和LDO的泄漏(一般该原因较少)
(2)GPIO的上下拉配置不正确导致的电流消耗
(3)外围器件未进行低功耗模式配置(通过最小系统版本,逐步拆除硬件的方式来逐步排除)

3.2 待机电流(待完善)

待机电流由底电流和唤醒电流平均组成。总的平均待机电流主要依赖于平均底电流的电流消耗。若尚未优化底电流,则待机优化的第一步是优化底电流的电流消耗。理论上,手机待机时,电流应该是比较规则的按照DRX周期进行唤醒。电流消耗捕捉工具提供的波形非常有助于分析寻呼唤醒产生的唤醒损失。
下图展示了DRX寻呼周期中所涉及的不同系统模块的活动阶段的寻呼唤醒波形的关联部分。
Android功耗调试汇总_第9张图片
对比寻呼唤醒周期的波形以确定唤醒的哪一部分消耗了较多时间或电流。
■ 系统唤醒时间
■ RF唤醒
■ RF/协议处理
■ RF睡眠
■ 系统睡眠
从modem侧log上可以查找 "Q6 clk at sleep start"来确认modem Q6 core是否进入休眠:
[lte_ml1_sleepmgr_stm.c 15109] Q6 clk at sleep start

3.3 通话
3.4 数据
3.5 音频
3.6 视频
3.7 游戏
3.8 浏览器
3.9 BT/WIFI
3.10 其他场景


4. 其他电流问题汇总

4.1 某些器件比如天线开关、sensor以及其他第三方元件没有进入低功耗模式
  ★在调试低电流过程中遇到,发现断掉射频SP9T天线开关电源后,手机低电流有明显下降。查看其SPEC,该开关未明确说明有SLEEP模式,也没有提供相应SLEEP模式下的电流,只给出了工作时的电流,大概在0.8mA左右,这与我们将它电源断掉后,手机低电流的下降值基本吻合。可以确认该开关存在一定的待机问题。项目后来改用其他带SLEEP模式的天线开关,问题得到解决 。

4.2 GPIO的上下拉配置
  ★GPIO的使用与配置是我们进行待机调试时的重要方面一定要逐个引脚进行确认,不要形成漏电回路。并注意,不要使引脚处于无上下拉的输入状态。

4.3 qxdm打开导致电流大
  ★现象:连接手机到PC,通过QXDM抓取log信息,之后拔掉数据线,手机不能待机。通过调试,发现此时diag任务阻止了手机的正常休眠。修改,将SLEEP_DIAG_OKTS_SIG从SLEEP_OK_MASK中去掉,该问题解决。
4.4 gsm联通某些小区比移动电流大
4.5 开机后需要较长时间才进入待机
4.6 热插拔SIM卡不待机
4.7 某些应用导致的待机电流大
4.8 滑屏电流大
4.9 并发场景(游戏+音乐)如:捕鱼达人/天天酷跑电流大
4.10 录音界面亮屏电流大
4.11 上网电流大
4.12 关于对齐唤醒
Android功耗调试汇总_第10张图片
4.13 sensor供电和i2c上拉电源不一致导致的电流问题
4.14 usb otg 控制器没有关闭导致的电流问题
4.15 modem没有正常起来以及模式不对造成的电流异常
4.16 otg的休眠
4.17 某项目在滑屏解锁后再待机电流就大15mA左右(和uart的功能配置有关系)
4.18 9x07某项目未使用的GPIO没有正确配置上下拉导致的底电流大4-5mA
4.19 某项目modem侧定时器造成的100ms的定时唤醒
Android功耗调试汇总_第11张图片

4.20 某项目不插卡待机时,经常唤醒,电流大(和小区不支持IMS紧急呼叫有关系)
Android功耗调试汇总_第12张图片



5. 补充要点

5.1 runtime PM机制参考

系统在非睡眠状态时,设备在空闲时可以进入runtime suspend状态同时不依赖系统wake_lock机制;非空闲时执行runtime resume使得设备进入正常工作状态。

主要代码放在Runtime.c (drivers\base\power)中,同时附带的Runtime_pm.txt (documentation\power)有详细说明。要使得设备可以进入runtime_idle与runtime_suspend必须满足device的2个参数usage_count与child_count同时为0。
①: 操作usage_count参数通常在HOST控制器驱动中,使用辅助runtime函数来完成。
②: 操作child_count通常由子设备来完成父设备child_count的增加与减少。child_count可以理解该设备活跃的子设备的个数。
通常由子设备睡后来让父设备进入休眠,依次递归进行。

简单理解就是:看有几个使用者,如果没有就可以休眠,不依赖于android的wake_lock机制。通常linux中通讯总线都会采用runtime电源管理机制,当I/O非busy时自动休眠,也就是通讯没有数据交互的时候的总线自动进入suspend,电源管理采用不用则停的方略,以此来减少功耗。

RPM的核心机制是这样的:
①为每个设备维护一个引用计数(device->power.usage_count),用于指示该设备的使用状态。

② 需要使用设备时,device driver调用pm_runtime_get(或pm_runtime_get_sync)接口,增加引用计数;不再使用设备时,device driver调用pm_runtime_put(或pm_runtime_put_sync)接口,减少引用计数。

③ 每一次put,RPM core都会判断引用计数的值。如果为零,表示该设备不再使用(idle)了,则使用异步(ASYNC)或同步(SYNC)的方式,调用设备的.runtime_idle回调函数。

④.runtime_idle的存在,是为了在idle和suspend之间加一个缓冲,避免频繁的suspend/resume操作。因此它的职责是:判断设备是否具备suspend的条件,如果具备,在合适的时机,suspend设备。

RPM core会使用异步(ASYNC)或同步(SYNC)的方式,调用设备的.runtime_suspend回调函数,suspend设备,同时记录设备的PM状态;

可以调用RPM core提供helper函数(pm_runtime_autosuspend_expiration、pm_runtime_autosuspend、pm_request_autosuspend),要求在指定的时间后,suspend设备。

⑤pm_runtime_autosuspend、pm_request_autosuspend等接口,会起一个timer,并在timer到期后,使用异步(ASYNC)或同步(SYNC)的方式,调用设备的.runtime_suspend回调函数,suspend设备,同时记录设备的PM状态。

⑥ 每一次get,RPM core都会判断设备的PM状态,如果不是active,则会使用异步(ASYNC)或同步(SYNC)的方式,调用设备的.runtime_resume回调函数,resume设备。

注1:Runtime PM中的“suspend”,不一定要求设备必须进入低功耗状态,而是要求设备在suspend后,不再处理数据,不再和CPUs、RAM进行任何的交互,直到设备的.runtime_resume被调用。因为此时设备的parent(如bus controller)、CPU是、RAM等,都有可能因为suspend而不再工作,如果设备再有任何动作,都会造成不可预期的异常。“Documentation\power\runtime_pm.txt”中有详尽解释供参考。

你可能感兴趣的:(物联网模块,android,待机电流,功耗,电流调试)