问题点

发现低温箱关机状态下能充进去电。开机是正常的。

参考

Android 8.0 MTK平台 电池高低温提醒客制化

kernel充电温度保护机制

  • drivers/power/supply/mediatek/charger/mtk_charger.c充电保护线程:
dts:
/* Battery Temperature Protection */
#define MIN_CHARGE_TEMP  0
#define MIN_CHARGE_TEMP_PLUS_X_DEGREE   6
#define MAX_CHARGE_TEMP  50
#define MAX_CHARGE_TEMP_MINUS_X_DEGREE  47static void charger_check_status(struct charger_manager *info)
{bool charging = true;int temperature;struct battery_thermal_protection_data *thermal;if (mt_get_charger_type() == CHARGER_UNKNOWN)return;temperature = info->battery_temp;thermal = &info->thermal;if (info->enable_sw_jeita == true) {do_sw_jeita_state_machine(info);if (info->sw_jeita.charging == false) {charging = false;goto stop_charging;}} else {if (thermal->enable_min_charge_temp) { //温度过低,低于0度if (temperature < thermal->min_charge_temp) {chr_err("Battery Under Temperature or NTC fail %d %d\n",temperature, thermal->min_charge_temp);thermal->sm = BAT_TEMP_LOW;charging = false;goto stop_charging; //小于0°,停止充电} else if (thermal->sm == BAT_TEMP_LOW) {//温度小于0度后,升上来了if (temperature >=thermal->min_charge_temp_plus_x_degree) {//温度大于6度了chr_err("Battery Temperature raise from %d to %d(%d), allow charging!!\n",thermal->min_charge_temp,temperature,thermal->min_charge_temp_plus_x_degree);thermal->sm = BAT_TEMP_NORMAL;} else {charging = false;goto stop_charging;}}}if (temperature >= thermal->max_charge_temp) { //温度太高,高于50度chr_err("Battery over Temperature or NTC fail %d %d\n",temperature, thermal->max_charge_temp);thermal->sm = BAT_TEMP_HIGH;charging = false;goto stop_charging;} else if (thermal->sm == BAT_TEMP_HIGH) {//温度大于50度后,降下来了if (temperature< thermal->max_charge_temp_minus_x_degree) { //现在温度小于47度了chr_err("Battery Temperature raise from %d to %d(%d), allow charging!!\n",thermal->max_charge_temp,temperature,thermal->max_charge_temp_minus_x_degree);thermal->sm = BAT_TEMP_NORMAL;} else {charging = false;goto stop_charging;}}}mtk_chg_get_tchg(info);if (!mtk_chg_check_vbus(info)) {charging = false;goto stop_charging;}if (info->cmd_discharging)charging = false;if (info->safety_timeout)charging = false;if (info->vbusov_stat)charging = false;stop_charging:mtk_battery_notify_check(info);chr_err("tmp:%d (jeita:%d sm:%d cv:%d en:%d) (sm:%d) en:%d c:%d s:%d ov:%d %d %d\n",temperature, info->enable_sw_jeita, info->sw_jeita.sm,info->sw_jeita.cv, info->sw_jeita.charging, thermal->sm,charging, info->cmd_discharging, info->safety_timeout,info->vbusov_stat, info->can_charging, charging);if (charging != info->can_charging)_charger_manager_enable_charging(info->chg1_consumer,0, charging);info->can_charging = charging;
}
  • 过压保护和温度保护通知,往底层节点BatteryNotify写异常标志,同时framework监听该节点并往上层app发送广播事件来显示充电危险。若是关机充电,重启后kpoc_charger程序将读取这个节点的异常值,显示危险断开充电图标。:

不正常状态如下:
/* charging abnormal status */
#define CHG_VBUS_OV_STATUS  (1 << 0)
#define CHG_BAT_OT_STATUS   (1 << 1)
#define CHG_OC_STATUS       (1 << 2)
#define CHG_BAT_OV_STATUS   (1 << 3)
#define CHG_ST_TMO_STATUS   (1 << 4)
#define CHG_BAT_LT_STATUS   (1 << 5)
#define CHG_TYPEC_WD_STATUS (1 << 6)static void mtk_battery_notify_check(struct charger_manager *info)
{if (info->notify_test_mode == 0x0000) {mtk_battery_notify_VCharger_check(info);mtk_battery_notify_VBatTemp_check(info);} else {mtk_battery_notify_UI_test(info);}
}static void mtk_battery_notify_VCharger_check(struct charger_manager *info)
{
#if defined(BATTERY_NOTIFY_CASE_0001_VCHARGER)int vchr = 0;vchr = battery_get_vbus() * 1000; /* uV */if (vchr < info->data.max_charger_voltage)info->notify_code &= ~CHG_VBUS_OV_STATUS;else {info->notify_code |= CHG_VBUS_OV_STATUS;chr_err("[BATTERY] charger_vol(%d mV) > %d mV\n",vchr / 1000, info->data.max_charger_voltage / 1000);mtk_chgstat_notify(info);}
#endif
}
温度过高过低保护:
static void mtk_battery_notify_VBatTemp_check(struct charger_manager *info)
{
#if defined(BATTERY_NOTIFY_CASE_0002_VBATTEMP)if (info->battery_temp >= info->thermal.max_charge_temp) {info->notify_code |= CHG_BAT_OT_STATUS;chr_err("[BATTERY] bat_temp(%d) out of range(too high)\n",info->battery_temp);mtk_chgstat_notify(info);} else {info->notify_code &= ~CHG_BAT_OT_STATUS;  //高温标志}if (info->enable_sw_jeita == true) {if (info->battery_temp < info->data.temp_neg_10_thres) {info->notify_code |= CHG_BAT_LT_STATUS;chr_err("bat_temp(%d) out of range(too low)\n",info->battery_temp);mtk_chgstat_notify(info);} else {info->notify_code &= ~CHG_BAT_LT_STATUS;}} else {
#ifdef BAT_LOW_TEMP_PROTECT_ENABLE //这个宏默认没打开,需要打开if (info->battery_temp < info->thermal.min_charge_temp) {info->notify_code |= CHG_BAT_LT_STATUS;chr_err("bat_temp(%d) out of range(too low)\n",info->battery_temp);mtk_chgstat_notify(info);} else {info->notify_code &= ~CHG_BAT_LT_STATUS;}
#endif}
#endif
}下面这个就是通过uevent往上层发送异常事件,貌似不知道是在干嘛:
static int mtk_chgstat_notify(struct charger_manager *info)
{int ret = 0;char *env[2] = { "CHGSTAT=1", NULL };chr_err("%s: 0x%x\n", __func__, info->notify_code);ret = kobject_uevent_env(&info->pdev->dev.kobj, KOBJ_CHANGE, env);if (ret)chr_err("%s: kobject_uevent_fail, ret=%d", __func__, ret);return ret;
}
  • 改变info->notify_code值其实就是改变sys节点/sys/devices/platform/charger/BatteryNotify的值:
static ssize_t show_BatNotify(struct device *dev,struct device_attribute *attr, char *buf)
{struct charger_manager *pinfo = dev->driver_data;pr_debug("[Battery] show_BatteryNotify: 0x%x\n", pinfo->notify_code);return sprintf(buf, "%u\n", pinfo->notify_code);
}static ssize_t store_BatNotify(struct device *dev,struct device_attribute *attr, const char *buf, size_t size)
{struct charger_manager *pinfo = dev->driver_data;unsigned int reg = 0;int ret;pr_debug("[Battery] store_BatteryNotify\n");if (buf != NULL && size != 0) {pr_debug("[Battery] buf is %s and size is %zu\n", buf, size);ret = kstrtouint(buf, 16, &reg);pinfo->notify_code = reg;pr_debug("[Battery] store code: 0x%x\n", pinfo->notify_code);mtk_chgstat_notify(pinfo);}return size;
}static DEVICE_ATTR(BatteryNotify, 0664, show_BatNotify, store_BatNotify);

frameworks层发送广播

  • vendor/mediatek/proprietary/frameworks/opt/batterywarning/batterywarning.cpp:
uevent事件轮询:
* batterywarn_init* uevent_init()* batterywarn_register_event(uevent_fd, uevent_event) //注册uevent_event如下,如果 type>0,就发送广播sendBroadcastMessage(String16(ACTION), type);
上层会接受这个广播,根据type去提醒系统。#define UEVENT_MSG_LEN 2048
static void uevent_event(uint32_t /*epevents*/) {char msg[UEVENT_MSG_LEN + 2];char *cp;char *status;int n;char *buffer = (char*) malloc(MAX_CHAR * sizeof(char));if (buffer == NULL) {ALOGD("malloc memory failed");return ;}n = uevent_kernel_multicast_recv(uevent_fd, msg, UEVENT_MSG_LEN);if (n <= 0) return;if (n >= UEVENT_MSG_LEN) /* overflow -- discard */return;msg[n] = '\0';msg[n + 1] = '\0';cp = msg;while (*cp) {if (!strncmp(cp, "CHGSTAT=", strlen("CHGSTAT="))) { // This CHGSTAT value will be provided by kernel driverreadType(buffer);break;}/* advance to after the next \0 */while (*cp++);}free(buffer);
}void readType(char* buffer) {FILE * pFile;int file_index;file_index=get_charger_file_path();ALOGD("Inside file_index value : %d\n", file_index);pFile = fopen(charger_file_path[file_index], "r");if (pFile == NULL) {ALOGE("error opening file");return;} else {if (fgets(buffer, MAX_CHAR, pFile) == NULL) {fclose(pFile);ALOGE("can not get the string from the file");return;}}fclose(pFile);int type = atoi(buffer);if (type==0){ALOGD("start activity by send intent to BatteryWarningReceiver to remove notification, type = %d\n", type);sendBroadcastMessage(String16(NORMAL_ACTION), type);}if (type > 0) //如果 type>0,就发送广播{ALOGD("start activity by send intent to BatteryWarningReceiver, type = %d\n", type);sendBroadcastMessage(String16(ACTION), type);}
}static int batterywarn_init() {epollfd = epoll_create(MAX_EPOLL_EVENTS);if (epollfd == -1) {ALOGD("epoll_create failed; errno=%d\n", errno);return -1;}uevent_init();return 0;}int main()
{char *buffer = (char*) malloc(MAX_CHAR * sizeof(char));if (buffer == NULL) {ALOGD("malloc memory failed");return 0;}int ret;/* Read the status to catch the event when batterywarning is not started */readType(buffer);ret= batterywarn_init();if (ret) {ALOGD("Initialization failed, exiting\n");exit(1);}batterywarn_mainloop();free(buffer);return 0;

app接收广播

有人发送广播,就有人接收广播,因此继续跟踪谁接收了这个广播。

  • vendor/mediatek/proprietary/packages/apps/BatteryWarning/src/com/mediatek/batterywarning/BatteryWarningReceiver.java:

分析这里面时,获取发送的广播,然后启动activity(BatteryWarningActivity),并且把type的值放在inten中传递过去。

type含义类型

    private static final int CHARGER_OVER_VOLTAGE_TYPE = 0;private static final int BATTERY_OVER_TEMPERATURE_TYPE = 1;private static final int CURRENT_OVER_PROTECTION_TYPE = 2;private static final int BATTERY_OVER_VOLTAGE_TYPE = 3;private static final int SAFETY_OVER_TIMEOUT_TYPE = 4;private static final int BATTERY_LOW_TEMPERATURE_TYPE = 5;private static final int TYPEC_DETECTION_WATER_GAS_TYPE = 6;CHARGER_OVER_VOLTAGE_TYPE = 0;//充电电压过高
BATTERY_OVER_TEMPERATURE_TYPE = 1;//电池温度过高
CURRENT_OVER_PROTECTION_TYPE = 2;//超过电流保护
BATTERY_OVER_VOLTAGE_TYPE = 3;//电池电压过高
SAFETY_OVER_TIMEOUT_TYPE = 4;//充电时间过长
BATTERY_LOW_TEMPERATURE_TYPE = 5;//电池温度过低

在onCreate()方法中,如果mType类型在0-5之间,就调用showWarningDialog()弹出提醒框。

分析到这里,整体的流程已经弄明白了,那么客制化的实现也很简单了。

MTK充电温度保护机制相关推荐

  1. MTK 方案电池保护机制设计

    我们分Driver .HAL .APP 三层来分别说明 驱动层: 在"kernel-4.4/drivers/power/mediatek/battery_common.c" 文件中 ...

  2. MTK 充电逻辑总结

    相关概念 懒的排版了,直接上图  相关文件关系 再来一发  杂项,电池温度检测原理图 发  充电流程 图样图森破  核心函数特写       /* 概念: ZCV:开路电压OCV: 开路电压VC:闭路 ...

  3. NJR日清纺微理光R5445系列 单节锂电池保护芯片,内置驱动器高位Nch FET开关温度保护

    NJR日清纺微理光R5445系列 单节锂电池保护芯片,内置驱动器高位Nch FET开关温度保护 产品名称:单节锂电池保护芯片 产品系列:R5445(新款) 代理品牌:NISSHINBO(日清纺微电子) ...

  4. 理光R5445系列 单节锂电池保护芯片,内置驱动器高位Nch FET开关温度保护

    产品名称:单节锂电池保护芯片 产品系列:R5445(新款) 代理品牌:NISSHINBO(日清纺微电子),原日本理光微电子 产品封装:WLCSP-8-P4 交期时间:现货一般当天交货,预定需电话详情 ...

  5. 【现货】AP6317 同步3A锂电充电芯片 带短温度保护

    AP6317是一款面向5V交流适配器的3A锂 离子电池充电器.它是采用800KHz固定频率的同 步降压型转换器,因此具有高达92%以上的充电效 率,自身发热量极小. 包括完整的充电终止电路.自动再充 ...

  6. 3.7V锂电池供电系统设计(含充电、保护、供电及电源切换电路器件选型和原理图)

    锂电池供电系统 一.锂电池   锂离子电池的负极为石墨晶体,正极通常为二氧化锂.充电时锂离子由正极向负极运动而嵌入石墨层中.放电时,锂离子从石墨晶体内负极表面脱离移向正极.所以,在该电池充放电过程中锂 ...

  7. spring cloud使用hystrix实现断路保护机制

    断路保护机制:即容错性,在微服务架构中,系统之间都是相互依赖的,如果一个系统出现了异常,就会出现如下情况: 断路保护机制就是为了解决这种情况. hystrix的大致原理如下: spring cloud ...

  8. Linux kernel 学习笔记(1) --分段分页保护机制

    使用80x86处理器进行寻址时牵涉到三种不同的地址,其关系如下所示 逻辑地址------------------->线性地址-------------------------->物理地址 ...

  9. 攻防世界(pwn)--Mary_Morton 利用格式化字符串+栈溢出破解Canary的保护机制

    ctf(pwn) canary保护机制讲解 与 破解方法介绍 程序执行流程 有三个选项,1是利用栈溢出,2是利用格式化字符串,3是退出;可连续输入多次; IDA分析 解题思路 程序存在canary保护 ...

最新文章

  1. python字符串写入excel-python 将数据写入excel
  2. How to create a simple 2D graphics program?
  3. 防火墙及其功能(转)
  4. 小游戏发布云测试工具,中小团队的“小又快”可以这么来
  5. c++中 结构体和类的区别
  6. android开发:input类型
  7. Java语言程序设计(一)选择题
  8. chrome 设置是否缓存
  9. WCF服务部署到IIS上,然后通过web服务引用方式出现错误的解决办法
  10. P1352 没有上司的舞会[树形dp]
  11. python使用逐行读取,出现空行,清楚空行方法
  12. 1.1信息安全基础概念
  13. 多路测温系统C51语言,基于单片机的多路温度检测系统的.docx
  14. 基于Struts2和hibernate的WebSocket聊天室的实现教程五:聊天机制
  15. 计划三年投入十亿资金,统信UOS生态腾飞加速
  16. 解决 Failed to fetch http://172.6.0.2/ubuntu/dists/jammy/main/binary-i386/Packages 404 Not Found问题
  17. veracrypt加密mysql_VeraCrypt使用教程,VeraCrypt文件硬盘加密使用教程
  18. linux machine start,Linux中的MACH定义之MACHINE_START / MACHINE_END
  19. android文件恢复功能,安卓手机恢复删除文件,如何恢复
  20. 这些支付的负面记录,分分钟影响你的贷款

热门文章

  1. Python——基于最小二乘法和最大似然法的回归分析方程中系数的估计
  2. Android 录音实现方法、仿微信语音、麦克风录音、发送语音、解决5.0以上BUG
  3. 我是如何从学渣成为程序员的
  4. 六年前埋雷 佛山照明悲剧隐现外资控股阳谋--宇通客车可参考
  5. 图解国家网信办《生成式人工智能服务管理办法(征)》| 附下载
  6. 如果把谷歌数据中心的数据都用打孔卡存起来
  7. 100个Linux Shell脚本经典案例解析
  8. python掷两个骰子的和_Python创造2个骰子公平地掷骰子并把它们加在一起?
  9. java并发编程3:使用JDK并发包(java.util.concurrent)构建程序
  10. VScode使用教程大全,看完你一定会谢谢我的