вопрос:
Недавно столкнулся с проблемой.Продукт системы android11 rk3566-планшет.Система нормально находится в состоянии энергопотребления,и система будет нормально зависать(это значит что заряда батареи не хватает для вождения нагрузка, чтобы продолжать нормально работать), что мы и говорим. Система принудительно выключается (физическое выключение), но после выключения системы она автоматически перезапускается, а затем перезагружается на полпути, снова зависает, и это было в этом цикле, и заряд батареи был достаточно разряжен для автоматического запуска, он не загружается.
ПРИМЕЧАНИЕ. Это тот случай, когда система питается от аккумулятора, а адаптер не подключен.
анализировать:
Причина, по которой система зависает, определенно заключается в том, что заряда батареи недостаточно для нормальной работы нагрузки системы, что мы называем автоматическим отключением (физическим отключением) при низком заряде батареи и причиной автоматического перезапуска. заключается в том, что когда система выключена, батарея Текущее состояние не нагружено, и батарея, которую я использую, имеет проблемы, и это может быть причиной того, что батарея, которую я использую, слишком расстроена. -нагрузка, напряжение его батареи увеличится примерно на 0,2-0,3 В, и система будет судить об этом значении напряжения.В это время система чувствует, что батарея работает! ! ! Он может поддерживать систему для повторного запуска, а затем автоматически запускается снова.Обнаружено, что батарея не двигается, когда она включается наполовину, а затем зависает. . . . Молодец, это не мошенничество! ! Конечно, автоматический запуск здесь будет упомянут позже, и в коде есть соответствующие суждения. Что моя текущая система должна реализовать, так это отключить зарядку, а не иметь возможность автоматически включать ее при подключении к адаптеру, и решить вышеуказанные проблемы.
Зарядка при выключении и соответствующая обработка загрузки находятся на этапе u-boot, и задействованы следующие файлы:
u-boot/drivers/power/charge_animation.c //Важно, отвечает за управление всем процессом зарядки, он будет получать питание, тип зарядки, ключевые события, инициировать спящий режим с низким энергопотреблением и т. д.
u-boot/include/power/charge_animation.h
u-загрузка/драйверы/мощность/fuel_gauge/fg_rk817.c
u-загрузка/драйверы/мощность/fuel_gauge/fuel_gauge_uclass.c
u-загрузка/драйверы/питание/pmic/rk8xx.c
Важный код, анализ структуры:
Эта структура связана со значением, используемым для управления начислениями, и конкретные функции четко аннотированы.
struct charge_animation_pdata {
int android_charge; /* android charge, 1: enable, 0: disable */
int uboot_charge; /* u-boot charge, 1: enable, 0: disable */
int auto_exit_charge; /* energy enough auto exit uboot charging*/
int exit_charge_voltage;/* lowest voltage allowed to exit charging */
int exit_charge_level; /* lowest soc level allowed to exit charging */
int low_power_voltage; /* below this voltage, force system into charge mode anyway */
int screen_on_voltage; /* lowest voltage allowed to turn on screen */
int system_suspend; /* enter ATF system suspend, 1: enable, 0: disable */
int auto_wakeup_interval;/* timeout seconds to auto wakeup system */
int auto_wakeup_screen_invert;/* auto wakeup system, 1: enable, 0: disable */
int auto_off_screen_interval;/* timeout seconds to auto turn off screen */
};
Разбор файла конфигурации dts:
charge-animation {
compatible = "rockchip,uboot-charge";
status = "okay";
rockchip,uboot-charge-on = <0>; // 是否开启U-Boot充电
rockchip,android-charge-on = <1>; // 是否开启Android充电
rockchip,uboot-exit-charge-level = <5>; // U-Boot充电时,允许开机的最低电量
rockchip,uboot-exit-charge-voltage = <3650>;// U-Boot充电时,允许开机的最低电压
rockchip,screen-on-voltage = <3400>; // U-Boot充电时,允许点亮屏幕的最低电
rockchip,uboot-low-power-voltage = <3350>; // U-Boot无条件强制进入充电模式的最低
rockchip,system-suspend = <1>; // 是否灭屏时进入trust低功耗待机(要压电压ATF支持)
rockchip,auto-off-screen-interval = <20>; // 自动灭屏超时,单位秒,默认15s
rockchip,auto-wakeup-interval = <10>; // 休眠自动唤醒时间,单位秒。如果值为0或没// 有这个属性,则禁止休眠自动唤醒,一般用于 压力测试使用
rockchip,auto-wakeup-screen-invert = <1>;
};
Примечание: их необходимо настроить в соответствии с вашей средой, в частности, вы можете проверить это с помощью мультиметра, а затем настроить его на соответствующее значение.
Все рабочие функции в charge_animation.c реализованы в fg_rk817.c следующим образом:
static struct dm_fuel_gauge_ops fg_ops = { //charge_animatio.c 中的一些回调函数都是都是调用的fg_rk817中的函数实现。
.bat_is_exist = rk817_bat_bat_is_exist,
.get_soc = rk817_bat_update_get_soc,
.get_voltage = rk817_bat_update_get_voltage,
.get_current = rk817_bat_update_get_current,
.get_chrg_online = rk817_bat_update_get_chrg_online,
};
Функция реализации всего процесса зарядки управления uboot — это, в основном, функция charge_animation_show(), которая является относительно важной функцией.Давайте проанализируем ее процесс ниже.
charge_animation_show();
|--fuel_gauge_bat_is_exist();->rk817_bat_bat_is_exist
|--rk817_bat_get_battery_voltage(battery); //读取pmic中的寄存器值获取battery的电量。
|--charge_extrem_low_power(dev); //该函数主要是检测电池低电量(无法满足系统工作的电量)的,且无供电电源时,关闭PMIC 下电。下面会讲一下该函数。
|--fuel_gauge_get_voltage(fg);
|--rk817_bat_update_get_voltage();
|--rk817_bat_get_battery_voltage();
|--fg_charger_get_chrg_online(dev); // --->>>/* PMIC shutdown */ pmic_shutdown(pmic);static int rk8xx_shutdown(struct udevice *dev)
|--rk817_bat_update_get_chrg_online();
|--rk817_bat_dwc_otg_check_dpdm(battery); //检测充电类型
|--autowakeup_timer_init(dev,5); ///* Enable auto wakeup */
|--fuel_gauge_update_get_soc(fg);-->static int rk817_bat_update_get_soc(struct udevice *dev)//该函数设置充电电流,以及外接的充电类,rk817_bat_smooth_charge(struct rk817_battery_device *battery)(每隔5S检测一次,保证是否在平稳的充电)
|--eds_update(dev, soc);
|--system_suspend_enter(dev);/* System suspend */
|--fuel_gauge_get_voltage(fg); //更新电压 |--rk817_bat_update_get_voltage();
|--rockchip_get_boot_mode();//检测充电模式是否有效。
|--fg_charger_get_chrg_online(dev);--->rk817_bat_update_get_chrg_online();rk817_bat_dwc_otg_check_dpdm(battery);//获取充电头类型
/* Not charger online and low power, shutdown */
soc = fuel_gauge_update_get_soc(fg);
voltage = fuel_gauge_get_voltage(fg);
if (soc < pdata->exit_charge_level) {
printf("soc(%d%%) < exit_charge_level(%d%%)\n",
soc, pdata->exit_charge_level);
exit_charge = true;
}
if (voltage < pdata->exit_charge_voltage) {
printf("voltage(%d) < exit_charge_voltage(%d)\n",
voltage, pdata->exit_charge_voltage);
exit_charge = true;
}
if (exit_charge) {
printf("Not charging and low power, Shutdown...\n");
show_idx = IMAGE_LOWPOWER_IDX(image_num);
charge_show_bmp(image[show_idx].name);
mdelay(1000);
pmic_shutdown(pmic);
}
}
//以下是判断:
|--pdata->android_charge // Enter android charge, set property for kernel */
|--if (!pdata->uboot_charge)///* Not enable U-Boot charge, exit */
|--fuel_gauge_get_voltage(fg);
|--if (voltage <= pdata->screen_on_voltage + 50)//charge_show_bmp(NULL);
|-----!!!!!!/* Charging ! */ while (1) 开始充电 //获取电量状态等驱动中利用的是定时器轮询的方式来获取,避免通过i2c来一直读取寄存器的值。在此期间是禁止中断的,而是通过power key产生事件中断。
|--local_irq_disable();
接下来就是充电5个步骤。
|--第一步:检测是否现在充电。
|--charging = fg_charger_get_chrg_online(dev);//如果充电器在此过程中拔出,则会调用rockchip_eink_show_charge_logo(),并关闭PMIC。
|--第二步:获取系统的电量与电池的电压,以及电流。判断目前的电压是否可以退出uboot阶段的充电(pdata->auto_exit_charge)。判断此时电量是否足以打开屏幕。
|--fuel_gauge_update_get_soc(fg);
|--fuel_gauge_get_voltage(fg);
|--fuel_gauge_get_current(fg);
|--下面的一部分就是处理关机充电时,亮屏以及充电图标状态显示的处理。当系统充电到100时则退出充电状态,以引导android 系统。
。。。。。。
|--第三步:主要是显示充电图标的处理。这部分我们不重点关注。
|--第四步:检查按键事件。检测power key :short key event:亮灭屏。长按键:显示logo 图标,引导系统开机继续保持充电状态。
|--key_state = check_key_press(dev);//key_state == KEY_PRESS_DOWN /key_state == KEY_PRESS_LONG_DOWN
|--第五步:主要是检测 ctrl+c 的处理。
Функция charge_extrem_low_power() в основном предназначена для определения текущего значения заряда аккумулятора и необходимости подключения адаптера для зарядки аккумулятора. Если заряд батареи меньше минимального значения мощности, которое мы установили, и адаптер не подключен, pmic будет выключен. Для того, чтобы возникала упомянутая выше ситуация повторных перезапусков.
static int charge_extrem_low_power(struct udevice *dev)
{
struct charge_animation_pdata *pdata = dev_get_platdata(dev);
struct charge_animation_priv *priv = dev_get_priv(dev);
struct udevice *pmic = priv->pmic;
struct udevice *fg = priv->fg;
int voltage, soc, charging = 1;
static int timer_initialized;
int ret;
voltage = fuel_gauge_get_voltage(fg);//获取当前电池电量值
if (voltage < 0)
return -EINVAL;
while (voltage < pdata->low_power_voltage + 50) {
/* Check charger online */
charging = fg_charger_get_chrg_online(dev);//判断是否插入输入源,及适配器。返回输入源类型
if (charging <= 0) {
printf("%s: Not charging, online=%d. Shutdown...\n",
__func__, charging);
/* wait uart flush before shutdown */
mdelay(5);
/* PMIC shutdown */
pmic_shutdown(pmic);//关闭pmic.
printf("Cpu should never reach here, shutdown failed !\n");
continue;
}
/* Enable auto wakeup */
if (!timer_initialized) {
timer_initialized = 1;
autowakeup_timer_init(dev, 5);
}
/*
* Just for fuel gauge to update something important,
* including charge current, coulometer or other.
*/
soc = fuel_gauge_update_get_soc(fg); //获取系统的电量值。
if (soc < 0 || soc > 100) {
printf("get soc failed: %d\n", soc);
continue;
}
/* Update led */
ret = leds_update(dev, soc);
if (ret)
printf("update led failed: %d\n", ret);
printf("Extrem low power, force charging... threshold=%dmv, now=%dmv\n",
pdata->low_power_voltage, voltage);
/* System suspend */
system_suspend_enter(dev);
/* Update voltage */
voltage = fuel_gauge_get_voltage(fg);
if (voltage < 0) {
printf("get voltage failed: %d\n", voltage);
continue;
}
if (ctrlc()) {
printf("Extrem low charge: exit by ctrl+c\n");
break;
}
}
autowakeup_timer_uninit();
return 0;
}
Таким образом, в основном проблемы, которые у нас есть выше, относительно ясны, а остальные требуют от нас только настройки соответствующих параметров.
И у моей текущей платы нет значка выключения зарядки, потому что мой дисплей конвертируется в LVDS через mipi dsi, а чип конвертируется через GM8775C, поэтому мне нужно успешно инициализировать чип в uboot.