目前智能座舱领域的方案中,高通的两大平台8155
/8295
占据了大部分的市场份额,这两个硬件平台都是基于QNX
系统的虚拟化方案实现的,就是说中控域与仪表域都跑在一个系统上了-座舱通常是Android系统,实际是QNX上的一个虚拟机;而仪表通常是运行在QNX侧。跟传统的单Android系统比较来看,QNX
虚拟化平台有很多的变化,比如很多物理驱动与系统服务都跑在了QNX上,而Android上看到的只是一个虚拟的设备,或者压根就去掉了,比如本文要讲到的动态调频与调压功能DCVS(Dynamic Clock and Voltage Scaling)
就是一个例子,这个功能在Android上已经没有了,所有的调频与调压功能都在QNX上实现。
DCVS
也可将其称为DVFS(Dynamic Voltage and Frequency Scaling)
实际都是根据系统负载动态调整CPU/GPU/DDR等工作频率与电压,从而减少功耗
接下来,我们就一起看看高通QNX平台的DCVS
功能是如何实现的,以及如何在QNX平台查看CPU, GPU,UFS,DDR
的频率。
QNX的DCVS实现原理 CPU DCVS DCVS
是一种电源管理的策略,用于根据系统负载状态动态的调整系统核心频率,以减少功耗,节省电能,这个在如手机这样的移动平台使用的最为广泛。下图是CPU DCVS
的的原理框图,其核心的功能都是在一个后台服务dcvs_service
中实现的,该服务负责与其他模块如kernel
, qcore
和io_service
进行交互:
根据系统负载来选择相应频率的算法是在QNX内核实现的;一旦决定选择某个频率,内核会发送请求给qcore
进程来进行频率的设定
如果系统负载过高导致触发高温保护,此时调频策略完全由LMH(Limit Management Hardware)
模块负责执行;而等到系统温度降低到设定的阈值,则DCVS
重新交由内核进行处理;dcvs_service
服务注册热管理模块(Thermal LMH
)的事件回调;在收到开启与关闭事件回调的时间窗口内,会关闭内核的动态调频功能,由LMH
硬件负责管理CPU
的频率
QNX
内核中包含一个负责调皮策略的管理者(governor
), 其负责监控系统负载,一旦某个CPU簇(cluster
, 8285上有两个簇,对应大小两个核心)的负载在一定的时间内持续超过了设定的阈值-高负载(overflow
)或者低负载(underflow
),内核的管理者就会触发一个事件;DCVS
服务收到该事件后,会主动将频率调整为内核推荐的频率
qcore是QNX上的电源管理核心服务
DLPMP(Dynamic power performance levels and multiprocessor control):动态调整性能模式
LMH(Limit Management Hardware): 用于系统高低温保护
如何进行DCVS参数设定 以8295
平台为例,有两个CPU
簇(分别有4个大核,4个小核),每个簇的频率共有10个等级(如下表所示):
SA8295 clusters
Levels
cluster0
10(1017MHZ~2131MHZ)
cluster1
10(1280MHZ~2380MHZ)
QNX
提供了pdbg
接口用于DCVS
的参数设定,每个频点主要有如下4个重要的参数:
up_pct_thr
: 当前频率的CPU使用率上限阈值,对freq10
来说,默认值是90
up_time_thr_ms
: 当前频率的CPU使用率(持续)时间上限阈值,对freq10
来说,默认值是100(ms)
down_pct_thr
: 当前频率的CPU使用率下限阈值,对freq10
来说,默认值是10
down_time_thr_ms
: 当前频率的CPU使用率(持续)时间下限阈值,对freq10
来说,默认值是200(ms)
如果想要更好的性能,尽量将up_pct_thr
的阈值降低点,确保系统负载超过该阈值后可以快速调频;反之,如果更多的考虑是节省功耗,则应该将down_pct_thr
的阈值提高一点,这样可以在系统负载降低时能触发降频,减少能耗。例如,在车载上更多的考虑是性能,我们可以适当提升CPU
调频的上限阈值:
1 2 3 4 echo 80 > /dev/pdbg/qcore/dcvs/kdcvs/cluster0/freq10/up_pct_threcho 80 > /dev/pdbg/qcore/dcvs/kdcvs/cluster1/freq10/up_pct_thr
如果要关闭DCVS
功能,将CPU
设定在最高或者最低的频点,可以通过如下接口设定:
1 2 3 4 5 6 7 echo 1 > /dev/pdbg/qcore/dcvs/force_max_freqencyecho 1 > /dev/pdbg/qcore/dcvs/force_min_freqency
另外,在分析问题时,可以通过slog2info
查看DCVS
的日志信息:
1 2 3 4 5 6 7 8 9 Jan 01 08:00:26.274 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 15, Client ID for adsp dcvs = 7 Jan 01 08:00:26.279 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 14, Client ID for adsp dcvs = 6 Jan 01 08:00:26.279 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 15, Client ID for adsp dcvs = 7 Jan 01 08:00:26.298 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 14, Client ID for adsp dcvs = 6 Jan 01 08:00:26.298 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 15, Client ID for adsp dcvs = 7 Jan 01 08:00:26.322 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 14, Client ID for adsp dcvs = 6 Jan 01 08:00:26.322 frpc_lib.233538 frpc_lib 16135 cdsp_service[fastrpc_farf.c:409]: CDSP:fastrpc_kpower.c:1440:0xdc:6: fastrpc_kpower_set: Request = HAP_power_set_DCVS_v2, Client ID = 15, Client ID for adsp dcvs = 7
GPU DCVS GPU
的DCVS
主要是通过一个工作队列线程来获取GPU
负载信息从而实施DCVS
动态调频-通过当前的负载信息来调整GPU的核心工作频率。与CPU
的频点类似,GPU
的工作频率也分位好几个档次,如SA8155
平台对应的GPU
工作频率有7个档次:
对GPU
的DCVS
来说都是通过内部的算法完成调频策略执行,无需进行调优;不过,QNX
提供了开关DCVS
的接口:
1 2 3 4 5 6 7 echo gpu_perf_governor 1 > /dev/kgsl-controlecho gpu_perf_governor 0 > /dev/kgsl-control
也可以选择将GPU
频点设定在指定的档次:
1 2 3 4 5 echo gpu_perf_governor 1 > /dev/kgsl-controlecho gpu_gfx_core_clock_level 3 > /dev/kgsl-control
如果需要实时查看当前GPU
的工作频率与负载,可以通过设定日志等级,然后通过slog2info
查看:
1 2 3 4 5 6 7 8 9 echo gpu_set_log_level 4 > /dev/kgsl-controlecho gpubusystats 100 > /dev/kgsl-controlslog2info -w |grep -i gsl
QNX中查看系统工作频率 高通平台的QNX
系统中有一个clock.sh
脚本,可以用来读取、设定系统核心的工作频率,比如CPU
, GPU
, DDR
, UFS
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 clock debug tool usage: clock.sh <command > <[arg]> [options] Provides an interface to the qcore clock driver. Results are stored in /tmp/clockdebug_log, which is then printed to stdout.global options: -b,--batch enable batch commands commands: enable <clock || powerdomain || dcvs || avs> disable <clock || powerdomain || dcvs> [--force] getfreq <clock> setfreq <clock> <frequency (min KHz)> setdiv <clock> <div> setflags <clock || powerdomain || top> <mask> setlimit <clock> [--min, --max (default)] <frequency (KHz)> config <clock> <val> reset <clock> [--assert, --deassert, --pulse (default)] info <clock || powerdomain || top || list> [--enabled, --on, --ref, --xovote, --cached] freqplan <clock> maxperf <cluster_name> minperf <cluster_name> perfinfo <cluster_name> gpio [--off] debugmux <clocck_name> getrefcount <clock_name> log
具体查看各个系统的频率的方法如下,这个可以看到所有系统核心域的频率信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 clock.sh info|grep apcs clock.sh info|grep gpu clock.sh info|grep ufs clock.sh info|grep ddr
如果我们要查看某个具体系统时钟的频率信息,可以通过如下命令:
1 2 3 4 5 6 Clock State Freq (Hz) EN RST Flags VDD_CX/MMCX Sources -------------------------------------------------------------------- gpu_cc_gx_gfx3d_clk ON (0) 730995848 1 n/a 0x0 OFF /pmic/client/xo