手机功耗基础介绍
做过几个手机和平板项目,负责功耗部分,将功耗大致分为以下几个部分
1.CPU IDLE(系统休眠)
2.Thermal(温升控制)
3.Charger(充电模块)
4.PMIC(供电模块)
CPU IDLE
CPU IDLE是功耗工程师必须要知道的概念,也就是CPU休眠,CPU休眠常常和系统待机挂钩,CPU IDLE会根据系统的状态进入不同的IDLE模式。例如mtk平台分别有suspend,deep idle,sodi(screen on deep idle), sodi3。当然高通也有几个类似的idle模式。系统在灭屏,暗屏,亮屏,飞行模式,wifi模式下都会进入不同的idle状态,不同的idle状态会关闭不同的子系统,降低一些模块的时钟频率,进而达到节省功耗的状态。
CPU IDLE伴随着终端系统的各个场景,如熄屏待机,亮屏home 界面待机,相机预览待机,微信界面待机等。而手机和平板等终端的功耗高低大多都是通过各个场景的待机功耗而评定的。
下面介绍一下终端功耗的基本知识点
无论是什么终端,只要是高耗电移动设备,都涉及到系统功耗,功耗这里就俗称为电量的消耗吧!比如一款终端的电池电量为6400maH,意思就是终端以持续不断的6400mA电流的耗电,终端可以待机1一个小时,所以控制手机的实时耗电非常重要!
功耗的测量是通过power monitor的设备来测量的
power monitor 图
先介绍一个基础词汇待机底电,待机的情况挺多,比如灭屏待机,亮屏待机,wifi待机,蓝牙待机,三方app待机等,场景多得很。下面一一介绍
灭屏待机先附上电流图一张
图一,灭屏飞行模式待机电流图,灭屏飞行待机系统一般会进入suspend的最深度休眠状态,从这张图可以看出待机底电流为6mA(及电流图中最低处的电流,当然这张待机电流图非常平稳,几乎稳定在底电6mA)(一般情况下待机底电流会在1-10mA之间)
灭屏待机高频唤醒问题附上电流图
图二,灭屏待机高频唤醒电流图,这里从图中可以看出在图一的基础上多出了很多的毛刺,这钟毛刺是在系统休眠状态下产生的,称为唤醒,顾名思义,一些子系统的活动或者异将cpu从休眠中唤醒,这些子系统可以包括蓝牙,wifi,sensor,modem,hrtimer等,休眠唤醒的唤醒源多种多样,可以通过mobile log,bugreport,ftrace,systrace,dump log等log工具分析!所以在解决高频唤醒问题的时候多多使用各种log来分析差异!以上工具和具体调试手法后面一一介绍
灭屏待机低电流高问题附上电流图
图三,灭屏待机底电流高电流图,从图三中可以看出比对图一底电流变得更高了,这证明在suspend休眠状态下某些子系统仍然在耗电,如memory,熔断异常等操作都有可能引起待机底电流变高。待机底电流变高的问题可以抓取对比bugreport,dumplog,systrace等log来分析!此类型问题在后面会有实战讲解,哈哈哈,非常有趣!!!
亮屏待机(称为home screen on idle)
图四,亮屏待机电流图,亮屏待机电流底电会随着亮度的不同而发生变化,亮屏待机会进入一种叫home screen on idle的休眠状态,也会关闭一些资源,如cup部分下电等!影响亮屏待机电流的因素也挺多,如ess,aal等feature,一些显示参数都会影响亮屏待机电流,电流图如下,哈哈哈!
三方场景灭屏待机
图五,微信灭屏待机电流图,微信灭屏待机,就是登陆微信后再灭屏待机,系统也会进入休眠,但会被微信相关的应用唤醒,从而出现peak,拉高功耗
图六,多后台应用灭屏待电流图,多后台灭屏待机,就是登陆微信,qq等三方应用然后都切入到后台回到home界面,再灭屏待机,系统最终还是会进入休眠,但会被三方后台应用唤醒,电流图如下
图七,camera场景亮屏待机功耗,开启camera app,亮屏待机,不同的cpu频率,摆核差异,以及镜头特性,算法的差异,功耗差异会比较大,电流图如下
图八,游戏场景功耗,以王者荣耀为例,打开王者荣耀,不同的CPU摆核,CPU频率,FPSGO参数,thermal参数,功耗差异也会比较大,电流图如下
图九,播放视频场景功耗,以优酷视频播放功夫熊猫3为例,打开优酷视频,播放功夫熊猫3,不同的亮度,不同的音量,不同的播放品质,会涉及不同的帧率,不同的cpu摆核,不同的CPU频率等,都会不同程度影响功耗,电流图如下
图十,qq视频通话功耗,qq视频通话是一个设计非常多模块的场景,涉及到三方的qq,本地的camera,算法的编解码,wifi或者5G,4G的通信,刷新率,音量大小等,影响功耗的因素非常多,这里不一一介绍,后面详解,电流图如下
功耗场景多种多样,当然不同的场景会有不同的分析方法,下面一一介绍(高通平台为例)
一.休眠待机底电流高问题
- 某些模块持锁导致AP无法休眠,可以抓取bugreport分析
如下图,可以从bugreport中看出audio的smart pa持锁导致AP无法休眠让底电变高
抓取bugreport的命令
adb shell dumpsys batterystats --enable full-wake-history
adb shell dumpsys batterystats --reset
用上两条命令清除以前的log信息等待几分钟后
使用adb bugreport > bugreport.txt抓取log
最后生成的bugreport 压缩包可以在
https://bathist.ef.lc/网址解析
2.某些模块并没有进入低功耗模式,这个可以和各个模块的owner确认器件是否有低功耗模式且是否进入了低功耗,例如霍尔原件有低功耗模式,但如果并没有配置休眠模式霍尔低功耗,就会多出1mA的耗电
3.休眠GPIO配置是否正常,例如高通sm8250平台,gpio14有一个重映射配置,这个配置会影响待机底电流3mA的差异,还有一些其他模块使用的gpio也需要看休眠gpio状态否存在漏电
4.高通dump log查看子系统是否存在异常
高通平台抓取dump log命令如下
音量减进入dump
adb root
adb shell
cd /sys/kernel/debug/spmi/spmi-0
echo 0x844 > address && echo 1 > count && echo 0x00 > data && echo 0x845 > address && echo 0x00 > data && echo 0x846 > address && echo 0x01 > data && echo 0x847 > address && echo 0x80 > data
If no " /sys/kernel/debug/spmi/spmi-0" node, please use “/sys/kernel/debug/regmap/spmi0-00” or “/sys/kernel/debug/regmap/spmi0-00”
配置power key触发dump:
adb root
adb shell
cd /sys/kernel/debug/spmi/spmi-0
echo 0x840 > address
echo 4 > count
echo 0x00 0x00 0x01 0x80 > data (可分开写入:
echo 0x840 > address && echo 1 > count && echo 0x00 > data && echo 0x841 > address && echo 0x00 > data && echo 0x842 > address && echo 0x01 > data && echo 0x843 > address && echo 0x80 > data
)
发送如下命令后,按power键或者音量键进入dump,通过高通的QPST软件可以抓取dump log
然后就需要解析dump log,需要高通对应的symbol文件,需要用QCAP软件解析,生成类似如下界面可以查看各个子系统状态,除了QCAP解析,还可以用hansei脚本解析出各路PMIC供电是否存在异常
-
电流分解,分解各路buck 到LDO路的供电是否存在漏电情况,这个需要硬件进行灌电流测试
-
设备树配置,dtsi里面配置的差异,也可能引起无法休眠的问题
二 suspend休眠唤醒问题
-
可以通过main log 查看高频唤醒问题,搜索PM关键字,可以看到PM: suspend entry (deep)
PM: suspend entry (exit)关键字,如下图,可以看到是ctn730芯片持锁,导致系统无法休眠
2. 通过bugreport查看唤醒源,bugreport的抓取手法上面已经介绍,这里直接上图,如下图为例,从图中可以看出com.motorola.motocit : MotoTest_CommServer持锁,当然唤醒源很多,需要多多积累经验
3. 通过bugreport log 查看唤醒源, 如下图,用文本打开bugreport.txt搜索top alarms 关键字,既可以看到部分唤醒源,如下图log中可以看出人脸识别相关进程高频唤醒
三 三方场景功耗问题 -
可以通过拆解器件的方式来寻找功耗差异,如lcd视频播放场景,可以摘除LCD来查看LCD是否有功耗异常,如camera场景,可以单独摘掉camera来判断是否有功耗异常,所以三方场景功耗问题的第一部就是可以拆解掉涉及的如LCD,camera等可拆解器件来定位功耗异常的模块
-
通过bugreport可以查看部分功耗差异,如下图,可以看出屏,system UI,andriod system,优酷视频等均有耗电
3. 通过systrace 可以查看cpu 调度,频率等情况,如下图,抓取systrace 需要用脚本,可以网上下载,这里就不一一讲解了
4. 通过Ctrace 解析systrace成xml表格,便于分析cpu 负载,线程负载,进程负载,cpu限频率等(Ctrace是谷歌开源软件需要自行下载修改编译)
通过Ctrace解析systrace出来的xml表格如下,依次有cpu freq, cpu minfreq, cpu maxfreq, cpu load, thread,process,topthreadload等
topthreadload 表格图,可以看到top 前10的线程负载
top 10 线程负载可以通过图表形式呈现,如下图
多个线程负载图表如下
cpu 最小频率限制如下图
CPU各核负载图如下
Ctrace可以帮助我们分析功耗,性能,温升,稳定性问题,感兴趣可以自己深入了解
MTK CPU IDLE框架介绍
CPU进入wfi状态
start_kernel
------------>rest_init
------------>cpu_startup_entry
------------>do_idle
------------>cpuidle_idle_call
------------>cpuidle_select(cpuidle_governor)(menu)
----------->cpuidle_curr_governor->select(drv, dev, stop_tick)
----------->menu_select
------------>call_cpuidle
------------>cpuidle_reflect
系统从uboot进入start_kernel函数最终变成idle进程,idle进程随时可以监控cpu的负载情况,从而判断cpu是否进入WFI状态
当系统进入wfi状态之后,PSCI电源管理会通过系统负载的情况,对cpu和其他模块进行上下电,对某些时钟的开启和禁止,PSCI会通过系统负载的情况判断系统是进入唤醒状态还是deep idle, home idle,suspend等休眠状态,具体内容感兴趣可以自己多多钻研
四.关于CPU 和 GPU的功耗我们可以大致参看项目对应的power_profile.xml文件(这里的配置数据我们可以做一个参考),里面有屏,wifi,cpu等各个模块的功耗理论数据,以CPU为例
如图
对应CPU核的频率
对应CPU核的功耗
Thermal
任何电子设备都会出现发热发烧的症状,尤其是高能耗移动设备,为了让系统处于一个安全稳定的状态,因此大多高速芯片都会有thermal策略,温升传感器作为输入,通过某些算法控制频率,亮度等,例如动态调频调压,手机动态背光,cpu动态开关,动态开关降温装置等,这些策略广泛运用到手机,电脑,游戏,视频等高速场景。
thermal 代码框架(以高通平台为例子)
在/android/kernel/msm-4.19/driver/thermal目录下,有各种thermal相关的文件,下面介绍一下主要的函数
1.thermal初始化函数
/android/kernel/msm-4.19/driver/thermal/thermal_core.c
static int __init thermal_init(void)
{
int result;
result = thermal_register_governors(); // 1.注册五种governors
result = class_register(&thermal_class); // 2.注册 /sys/class/thermal 节点
result = of_parse_thermal_zones(); // 3.解析dts 的"thermal-zones"设备树,并注册
// thermal_zone_device
result = register_pm_notifier(&thermal_pm_nb); // 注册themal notifier
}
2. thermal 设备树
/android/vendor/qcom/proprietary/devicetree-4.19/qcom/kona-thermal.dtsi
下面列出部分代码,详细代码可以自行钻研
thermal-zones {
cpu_thermal: cpu_thermal {
polling-delay-passive = <330>;
polling-delay = <1000>;
thermal-sensors = <&ths 0>;
trips {
cpu_warm: cpu_warm {
temperature = <65000>;
hysteresis = <2000>;
type = “passive”;
};
cpu_hot: cpu_hot {
temperature = <75000>;
hysteresis = <2000>;
type = “passive”;
};
cpu_very_hot: cpu_very_hot {
temperature = <90000>;
hysteresis = <2000>;
type = “passive”;
};
cpu_crit: cpu_crit {
temperature = <105000>;
hysteresis = <2000>;
type = “critical”;
};
};
cooling-maps {
cpu_warm_limit_cpu {
trip = <&cpu_warm>;
cooling-device = <&cpu0 THERMAL_NO_LIMIT 1>;
};
cpu_hot_limit_cpu {
trip = <&cpu_hot>;
cooling-device = <&cpu0 2 3>;
};
cpu_very_hot_limit_cpu {
trip = <&cpu_very_hot>;
cooling-device = <&cpu0 5 THERMAL_NO_LIMIT>;
};
};
};
};
函数详细流程可以自行摸索钻研,下面讲解一个thermal大致流程
thermal初始化会调用
INIT_DEFERRABLE_WORK(&(tz->poll_queue), thermal_zone_device_check);
将thermal_zone_device_check加入工作队列
thermal_zone_device_check()
----->thermal_zone_device_update()
-------->update_temperature()
---------->thermal_zone_get_temp()
----------->store_temperature()
-------->handle_thermal_trip()
----------->handle_critical_trips()
---------->thermal_emergency_poweroff()
---------->kernel_Poweroff()//关闭CPU核
----------->handle_non_critical_trips()
---------->tz->governor->throttle()
---------->set_cur_state() //根据温度设置CPU对应的状态
--------->monitor_thermal_zone()
--------->trace_thermal_handle_trip()
Charger
Charger是用于给系统充电的模块,例如手机里面会有专门的充电IC,Charger IC从充电器抽电流,电流先提供给系统使用,剩下的电流流进电池,如果充电器抽的电流不够系统使用(或者无充电器存在),从电池抽电供系统使用。
PMIC
PMIC是电源管理芯片,是指在电子设备系统中担负起对电能的变换、分配、检测及其他电能管理的职责的芯片,各个子系统的电源都是由PMIC进行管理,因此系统休眠和PMIC息息相关。
粗略介绍了一下CPU IDLE, Thermal, Charger, PMIC,还有很多不懂的地方,请各位大佬指点一二