Thermal engine 解析

Posted 我爱一次性

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Thermal engine 解析相关的知识,希望对你有一定的参考价值。

本文所在的平台是安卓10

thermal engine是高通做的一个温度管理守护进程。在4.9后thermal engine不再被维护,推荐用于调试。从ktm+thermal engine 变成 thermal core来监控温度。可是市面上还是有很多手机继续沿用thermal engine去控制温度,而thermal core用于保守控制。可是,仍然有很多手机会继续使用thermal engine作为过温保护的工具。

目录

本文所在的平台是安卓10

一.thermal engine 框架

二. sensor 初始化

三. device初始化

四. thermal_settings配置

五. 持续监控

最后,希望可以帮到大家,如果有用的就收藏一下,白嫖的就点个赞。


一.thermal engine 框架

 

sensor:传感器,获取温度。

device:设备,一些调频的设备。比如当cpu sensor检测到温度过高时,会调用cpu device降频操作。通常就是对cpu的设备节点进行操作。(或者cpu 的cooling device)。

thermal_setting:控温的配置,根据soc型号获取,或者从thermal-engine.conf获取。如今,更多选择后者。作用是配置温控策略。记录温度阈值等。

算法:ss算法,pid算法,monitor等。

源码位置:/vendor/qcom/proprietary/thermal-engine

二. sensor 初始化

....
sensors_init(minimum_mode);/*传感器初始化*/
...

 如果还是ktm + thermal engine管理模式(老kernel)会在init_sensor_alias添加好sensor。

int sensors_init(int minimum_mode)
{
	int ret_val = 0;
	min_mode = minimum_mode;
#ifdef ENABLE_BW_SENSOR
	struct sensor_info *bw_sensor_list = NULL;
#endif /* ENABLE_BW_SENSOR */

	if (!min_mode)
		modem_ts_qmi_init();

    //ktm+thermal engine管理模式则进入init_sensor_alias
	init_sensor_alias(); 
	parse_thermal_zones();

......
}

进入parse_thermal_zones

static void parse_thermal_zones(void)
{
	DIR *tdir = NULL;
	struct dirent *tdirent = NULL;
	char name[MAX_PATH] = {0};
	char cwd[MAX_PATH] = {0};
	int cnt = 0, ret = 0;
	if (!getcwd(cwd, sizeof(cwd)))
		return;
	if (sensor_cnt <= 0){
        //如果没有ktm,进入init_space_sensors进行注册sensor
		return init_user_space_sensors();
	}
		
	ret = chdir(THERMAL_SYSFS); /* Change dir to read the entries. Doesnt work
                                 otherwise */
	tdir = opendir(THERMAL_SYSFS);
	if (!tdir || ret) {
		msg("%s: Unable to open %s\\n", __func__, THERMAL_SYSFS);
		return;
	}
	while ((tdirent = readdir(tdir))) {
		char buf[MAX_PATH];

    //获取每个sensor的数据。
......

获取sensor的路径:/sys/devices/virtual/thermal/

到这里为止,就知道能监听的sensor是在哪里。那么,配置thermal-engine.conf有哪些sensor就是从这里选取了。

最后,每个sensor会创建个线程进行持续监控温度:

pthread_create(&(sensor_mgr->monitor_thread), NULL,
			       sensor_monitor, sensor_mgr);

 

三. device初始化

设备初始化,通常就是通过修改设备节点来进行设备管控,保护有cpu,gpu,电池,背光等。

注册一个动作与设备相关联。比如thermal-engine.conf里面action里cpu的动作,就会与cpu设备节点关联。

...
devices_init(minimum_mode);
...

 各种各样的设备进行初始化。

cooling devices属于thermal core的降频方法,也可以操作cooling devices。

可注册分为:普通设备,cooling devices ,热拔插

int devices_init(int minimum_mode)
{
	int ret_val = 0;

	min_mode = minimum_mode;
	gpufreq_init();
	cpufreq_init();
	clusterfreq_init();
	thermal_ioctl_init();

    .......

	/* Functions to execute post devices added to device manager */
	hotplug_init();
	vdd_dig_sw_mode_init();
	vdd_rstr_init();
	opt_curr_req_init();
	profile_switch_init();
	cpr_band_init();
	lcd_device_init();
	battery_mitigation_init();

	/* Add all other kernel cooling devices */
	cooling_devices_init();

	return ret_val;
}

普通设备注册:

static struct tmd_generic_dev_info_t gen_dev_list[] = {
	{
		.name = "wlan",
		.num_of_lvls = MAX_WLAN_MITIGATION_LEVEL + 1,
		.action = wlan_action,
	},
	{
		.name = "profile_switch",
		.num_of_lvls = MAX_PROFILE_LEVEL + 1,
		.action = profile_switch_action,
		.min_lvl = PERF_DEFAULT_PROFILE,
	},
	{
		.name = BATTERY_DEV_NAME,
		.num_of_lvls = MAX_BATTERY_MITIGATION_LEVEL + 1,
		.action = battery_action,
	},
.............

热拔插注册:

static struct tmd_generic_dev_info_t hotplug_dev_list[] = {
	{
		.name = "hotplug_0",
		.num_of_lvls = 2,
		.action = hotplug_action,
		.data   = (void *)0,
	},
	{
		.name = "hotplug_1",
		.num_of_lvls = 2,
		.action = hotplug_action,
		.data   = (void *)1,
	},
	{
		.name = "hotplug_2",
		.num_of_lvls = 2,
		.action = hotplug_action,
		.data   = (void *)2,
	},
......

cooling device注册:

static void init_cooling_device( struct devices_manager_dev *dev)
{
	char cdev_name[DEVICES_MAX_NAME_LEN] = {0};
	char path[DEVICES_MAX_PATH] = {0};
	char freq_buf[DEVICES_MAX_PATH] = {0};
	int cpu_idx = 0;

	dev->dev_info.cooling_dev_id = -1;
	if (!strncmp(dev->dev_info.name, LCD_DEV_NAME,
				strlen(dev->dev_info.name))) {
		snprintf(cdev_name, sizeof(cdev_name),
				LCD_COOLING_DEV_NAME);
		dev->dev_info.cooling_dev_id = get_cdevn(cdev_name);
	} else if (!strncmp(dev->dev_info.name, BATTERY_DEV_NAME,
				strlen(dev->dev_info.name))) {
		snprintf(cdev_name, sizeof(cdev_name),
				BATTERY_COOLING_DEV_NAME);
		dev->dev_info.cooling_dev_id = get_cdevn(cdev_name);
	}

...........

四. thermal_settings配置

配置分为两种:一个是通过soc的id来寻找各个算法的配置,另一种就是读取thermal-engine.conf里填写的配置。

因为thermal engine已经在内核4.9后就不在维护了,那么新的芯片是没有soc的配置的,那就我们就通过thermal-engine.conf进行配置了。

1.soc的id寻找配置

...
pid_init_data(&thermal_settings);
thermal_monitor_init_data(&thermal_settings);
speaker_cal_init_data(&thermal_settings);
ss_init_data(&thermal_settings);
tb_init_data(&thermal_settings);
virtual_sensors_init_data(&thermal_settings);

2.读取thermal-engine.conf

load_config(&thermal_settings, config_file, LOAD_ALL_FLAG);

五. 持续监控

在thermal_settings配置完毕后,就会里面各个配置分到不同算法,并开启各个算法的线程去持续管控好被分配的配置。

pid_algo_init(&thermal_settings);/*pid算法配置,并开启线程监控*/
thermal_monitor(&thermal_settings);/*monitor算法配置,并开启线程监控*/
ss_algo_init(&thermal_settings);/*ss算法配置,并开启线程监控*/

还有speaker_cal和step_wise算法。

比如: 

该配置的ss算法的,则在 ss_algo_init函数里,就会把该配置记录到ss的一个表里面。在开启ss算法的线程后,就会持续读这个配置,看是否需要执行ss算法的动作。

最后,希望可以帮到大家,如果有用的就收藏一下,白嫖的就点个赞。

以上是关于Thermal engine 解析的主要内容,如果未能解决你的问题,请参考以下文章

Android Thermal-engine

HW职责 (Hardware Engineer)

RK3588平台开发系列讲解(Thermal篇)Thermal介绍及用法

片段(Java) | 机试题+算法思路+考点+代码解析 2023

ZOJ 2706 Thermal Death of the Universe (线段树)

无法解析片段中的 findViewById [重复]