Контроль напряжения в PalmOS
В статье обсуждается что в действительности означает вольтаж и процент зарядки аккумулятора.
Можно уверенно сказать, что батарея является узким местом в современных карманных устройствах. Если старые монохромные КПК жили неделями на двух ААА батарейках, то современные устройства требуют подзарядки раз в 2-3 дня в зависимости от активности использования.
КПК потребляют электроэнергию во всех состояниях: и в включенном и в выключенном. Необходимость сохранения данных в выключенном виде тоже требует питания, поэтому пальма не пытается работать до полного опустошения аккумулятора, а выключается раньше, оставляя часть заряда на сохранение данных “до ближайшего кредла”.
У пальм есть два важных порога разряженности батареи: предупреждающее и критическое. По достижению предупреждающего порога устройсво выдает сообщение пользователю. По достижению критического порога устройство выключается и продолжает сохранять данные.
Пороговые значения железно задаются в прошивке устройств. Как показывает следующее сообщение, http://palmz.4to.info/showpost.php?p=185918&postcount=5 , эти величины берутся с большим запасом, так что уменьшение порогов может продлить время работы устройства.
У любого устройства на PalmOS есть возможность показать пользователю текущее напряжение на аккумуляторе и степень его заряженности. Возникает вопрос - а откуда эти числа берутся? Насколько можно им доверять?
В API PalmOS существует функция, получающая информацию о состоянии батареи. Вот ее прототип:
UInt16 SysBatteryInfo(Boolean set, UInt16 *warnThresholdP, UInt16 *criticalThresholdP, Int16 *maxTicksP, SysBatteryKind* kindP, Boolean *pluggedIn, UInt8 *percentP);
Функция позволяет получить следующие характеристики:
Сразу возникают вопросы: насколько можно верить значени напряжения? Как рассчитывается разряженность батареи? Понятно, что где-то стоит ADC, который преобразовывает напряжение в некоторое число в диапазоне 0-255. А как из этого числа получить вольты с точностью до сотых долей? Понятно, что мини-вольтметру нужна калибрация.
В очень старые времена, когда пальмы были на батарейках AAA, никакой встроенной калибрации не было. Существовал хак, позволявший задать корректирующие значения вручную.
У моделей со встроенным аккумулятором погрешности измерений могли привести к порче батареи, поэтому проблему нужно было решать на уровне производителя. Разработчики PalmOS решили эту задачу следующим образом.
Большая часть системного ROM одинакова у всех экземпляров одной модели, но предусмотрена возможность прошивать индивидуальные данные. Эти данные прописываются в специальном формате и называются ROM Token. Каждый токен представляет из себя четырехбуквенное имя и блок данных. Самый известный токен имеет имя num. В него записывается FlashID устройства.
Для калибрации используется токен с именем adcc. В него записываются замеры двух пар (напряжение, значение ADC). Одно значение измеряется для маленького напряжения, а второе для большого. Из двух значений аппроксимацией можно получить значение напряжения с достаточной точностью.
typedef struct { UInt16 lowCentivolts; UInt16 lowAToDOutput; UInt16 highCentivolts; UInt16 highAToDOutput; } SysAToDCalibrationTokenType;
Такой способ калибрации используется во всех устройствах от PalmOne у которых вместо ROM стоит перезаписываемая флешка.
Процент разряда вычисляется как функция от напряжения. Поскольку зависимость разряда от напряжения нелинейная, то воспользоваться линейной аппроксимацией не получится. Поэтому используются предопределенные значения напряжения в 11 точках, соответствующих 0%, 10%, 20%… 100% заряда. Находится интервал, в который попадает текущее напряжение и уже внутри интервала используется линейная аппроксимация.
Магическое значение “тип батареи” определяет характеристики батарее: предупреждающее и критическое напряжение, выборки кривой разряда итд. Желающие могут поглядеть на данные, которые определяются для каждого типа батарей и аккумуляторов.
typedef struct { Word sysBattDataStructVersion; // rev level of the structure (this one is 1) Word sysBattMildWrngVoltage; // in centivolts-- this is the voltage where the warning dialog appears Word sysBattSevereWrngVoltage; // in cVolts-- this is the voltage where the critical warning dialog appears Word sysBattMildWrngPercent; // Mild warning percentage for 3.2 and newer (rev 2) Word sysBattSevereWrngPercent; // Severe warning percentage for 3.2 and newer (rev 2) Word sysBattShutdownEnVoltage; // in cV-- This voltage causes us to do a software shutdown Word sysBattShutdownDisVoltage; // in cV-- This voltage allows us to wakeup from shutdown Word sysBattMinIRVoltage; // prevents IR from working if below this threshold DWord sysBattMildWrngTimeout; // in ticks-- this is the number of ticks to wait between displaying warning dialogs DWord sysBattSevereWrngTimeout; // in ticks-- this is the number of ticks to wait between displaying critical warning dialogs Word sysBattCritWarnOffDays; // in days-- number of days between mild and severe warnings DWord sysBattCritWarnOnTicks; // in ticks-- number of ticks between mild and severe warnings Word sysBattStepsPerVolt; // for scaling A/D to Voltages SWord sysBattVoltageStepOffset; // for scaling A/D to Voltages DWord sysBattReserved1; // future use DWord sysBattReserved2; // future use Word sysBattVoltageCurve[11]; // in cV; this is the voltage at the specified percentage/10; i.e. if the voltage // with 20% remaining is 2.5 volts, battVoltageCurve[2] = 250. } SysBatteryDataStruct, *SysBatteryDataStructP;
Теперь посмотрим на функционирование системы в целом. При старте (и при смене типа батареи) PalmOS выбирает таблицу параметров батареи и калибровочные значения.
С некоторой периодичностью система считывает значение ADC и с помощью данных из параметров батареи и калибрационных поправок происходит вычисление напряжения. По таблице sysBattVoltageCurve вычисляется степень разряженности батареи.
Когда напряжение падает ниже уровня warning, на экран выдается предупреждение. Когда напряжение падает ниже уровня critical, устройство выключается.
Работа с батареей была в модуле, который писал производитель устройства, но функции и системные данные хранились в данных PalmOS 4, поэтому было можно написать универсальный хак, который позволял корректировать времена выключения вручную.
В PalmOS5 были внесены изменения в идеологию работы с акумулятором. Что было сделано?
На самом верхнем уровне, уровне m68k API (который все программы и используют), никаких изменений не видно. Все также используется функция SysBatteryInfo.
Ниже идет уровень ARM API. Аналог старой функции SysBatteryInfo теперь называется SysBatteryInfoV40, а новая функция SysBatteryInfo вместо сантивольтов возвращает только проценты разрядки. SysBatteryInfoV40 вызывает SysBatteryInfo которая в свою очередь вызывает HALBatteryGetInfo.
Теперь вопрос - как SysBatteryInfoV40 вычисляет напряжение по процентам? Очень просто: cV = percents * 0.5 + 370. Всегда. То есть напряжение, возвращаемое в программы не имеет никакого отношения к реальному напряжению. Скорее это просто показания “идеального аккумулятора” в вакууме.
Функция HALBatteryGetInfo находится в модуле DAL. Этот модуль пишется разработчиками конкретного устройства. Реализация этой функции возвращает информацию в максимально абстрактном виде, в процентах разрядки батареи. Таким образом у ядра PalmOS (у модуля boot.prc) нет никакой возможности узнать реальное напряжение.
Err HALBatteryGetInfo(UInt16 *warnThresholdPercentP, UInt16 *criticalThresholdPercentP, UInt16 *shutdownThresholdPercentP, UInt32 *warnMaxTicksP, SysBatteryKind *kindP, Boolean *pluggedInP, SysBatteryState *stateP, UInt8 *percentP);
Таким образом в PalmOS 5 нет возможности узнать реальное напряжение. Более того, модули DAL могут и не вычислять напряжение вообще, а сразу переводить его из чисел на выходе ADC в проценты. Это усложняет реализацию ручной поправки критических значений. Если раньше было достаточно подкорректировать системную переменную “критическое напряжение”, то теперь такой переменной нет. Есть просто проценты зарядки при которых устройство отключается. А сам модуль DAL использует внутренние переменные для определения момента выключения и коррекция процентов ни к чему не приводит.
Разработчики из Mobile Stream ( http://www.mobile-stream.com/ ) таки раскопали место хранения вольтажа. Программа FullPower позволяет изменять критический порог.
Эта программа залезает в переменные модуля DAL и изменяет пороговые напряжения. Поскольку DALы разных устройств работают по-разному, программа может не работать на некоторых устройствах.
==== Ссылки
http://palmz.4to.info/showthread.php?t=21156 - часть информации была заимствована из обсуждения