Прикручиваем к часам на OSA энергосбережение

После публикации статьи про часы из STM8L-Discovery, под управлением OSA, у некоторых читателей возникли вопросы по поводу потребления энергии. Нелогичными эти вопросы считать нельзя, так как серия STM8L является низкопотребляющей. Про попытки снизить энергопотребление часов и мой вариант сопряжение режима Active halt с ОСРВ под катом.

Вступление

Перед тем как приступить к модернизации я немного погуглил. Ничего толкового о применении энергосберегающих режимов работы МК под управлением ОСРВ OSA я не нашел. Ни на самом сайте проекта, ни в интернетах. Не скажу, что я очень хорошо искал, но беглый осмотр не дал результатов. Поэтому снижать энергопотребление часов будем народными методами. И постепенно.
Ниже изложенная информация о полученных значениях потребления, относиться к разряду «приводимой к сведенью» и не является неоспоримым авторитетным заявлением.

Поехали!

Первый логичный метод — снизить рабочую частоту процессора. В предыдущем проекте она выбрана максимальной, так как вопрос энергосбережения не ставился в принципе. Изменение рабочей частоты производиться заданием делителя в макросе CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_х), где х — числа от 1 до 128. Соответствует частотам от 16МГц до 125кГц. Залезать в килогерцовый диапазон, понятное дело, не будем, но до 1МГц опуститься можно.

Пару слов о том, чем буду измерять. Мгновенные значения буду мерить микроамперметром цифрового мультиметра Pro'sKit MT-1232. Производитель заявляет точность измерений ±(1.0%+10d) в диапазоне 400µA/4000µA. Интегрирование значений во времени (в пределах 50мкА) проводится с помощью советских стрелочных микроамперметров с зеркальной шкалой. Такой себе FalseRMS :)

Снижаем рабочую частоту процессора. Сказано — сделано.


* — заявлено компанией ST в DS6372 (Table 20. Total current consumption in Run mode, стр. 66).

Результат, так сказать, на лицо. Без всякого шаманства удалось снизить потребление более чем в 7 раз. В четвертой колонке привожу «эталонные» значение от производителя, для справки. Данное значение получено при условии, что вся периферия отключена и код выполняется из флеш памяти. С учетом того, что у нас включен RTC, Timer4 и LCD контроллер, корреляция между значениями заметна.

Стоит обратить внимание на интересный факт. При значениях потребления ниже 650 мкА (2МГц, 1МГц) часы работали даже со снятым с разомкнутым джампером JP1, который, по идее, подает питание на контроллер. Делаем вывод, что питание пролазит по паразитным цепям или как-то еще :). Ладно, продолжаем...

Следующим пунктом будет увеличение времени системного тика, предложенное камрадом nobody . Во время тестов я увеличил системный тик сначала до 10мс, а потом и до 50мс, но никаких ощутимых изменений в плане энергопотребления не заметил. Это, в принципе, логично, так как никакой разгрузки процессор от этого не получает. Значит, будем предпринимать радикальные решения.

На сайте проекта OSA я не нашел никакого намека на возможные варианты штатного подключения режимов пониженного энергопотребления, так что будем городить свой. Идея: создать дополнительную задачу, которая будет выполняться последней, и содержать в своем теле перевод контроллера в режим Active halt. Вывод с режима останова будет производиться по прерыванию wake up RTC, который, одновременно будет служить системным тиком. После выполнения прерывания, управление передается следующей строке за вызовом halt-режима — туда поставим системную функцию безусловной передачи управления планировщику ОС. Должно сработать. Для ясности, попытался изобразить принцип работы на рисунке:



Теперь будем реализовывать задуманное. Начнем с настройки таймера пробуждения. Так как он будет выполнять функцию системного таймера ОС, ранее используемый для этих целей Timer4 можно (нужно) отключить. Это дополнительно сэкономит нам микроамперы. Для того, чтобы настроить предделитель и включить прерывание wake up от RTC, нужно добавить пару макросов в код Init():

//  set as system clock RTC wake up interrupt 
//  configures the RTC wake up timer_step = RTCCLK/16 = LSE/16 = 488.28125 us
RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div16);
//  enable wake up unit Interrupt
RTC_ITConfig(RTC_IT_WUT, ENABLE);

и сам обработчик прерываний:

INTERRUPT_HANDLER(RTC_IRQHandler, 4)
{
   RTC_ClearITPendingBit(RTC_IT_WUT); 
   OS_Timer(); 
}

Создаем дополнительную задачу, переводящую систему в режим пониженного потребления:

void to_halt(void)
{
  for (;;)
  {
    //  set time delay ~ 50ms
    RTC_SetWakeUpCounter(102);
    RTC_WakeUpCmd(ENABLE);    
    //  enter Halt mode
    halt();
    RTC_WakeUpCmd(DISABLE);
    //  return control to OS scheduler
    OS_Yield();
  }     
}

Вносим изменения в файл конфигурации OSAcfg.h:

#define OS_TASKS 5

И создаем задачу в main(), последней в очереди:

OS_Task_Create(0, to_halt);

Затем меняем значение аргументов в системных задержках OS_Delay(), с учетом того, что длительность тика теперь 50 мс. И готово! Компилируем, прошиваем и на тест!

Часы тикают — на ЖКИ выводится время, реагирует на нажатие кнопок. Значит, ОСРВ работает. Это уже вин! Теперь подключим мультиметр. Значение колеблется в диапазоне 20.9 — 32 мкА. Даблвин! И последний тест — подключу советский стрелочный микроамперметр. Этот прибор обладает инерционностью, что даст возможность оценить среднее потребление часов. Так как потребление контроллера неравномерное во времени, цифровой мультиметр измеряет амплитудное значение, а стрелочный инерционный — близкое к действующему. Результат: 6.5 — 7 мкА. Как по мне, неплохие показатели.

Хотелось провести ещё серию тестов just for fun, типа питание от яблок, лимонов и ионистора 1Ф, но меня постигла неудача, так как никакими уговорами не удалось подключить питание к контроллеру в обход остальной платы Discovery.

Я модернизировал код, дописывая изменения в #ifdef ENERGYSAVE секции. Так что желающим повторить тесты, достаточно закомментировать строчку #define ENERGYSAVE чтобы получить старые жрущие часы :)
На этом позвольте откланяться!..

UPD: по просьбам трудящихся, провел тесты программы с режимом останова на разных частотах:


У себя оставил рабочую частоту 8 МГц.
  • +4
  • 28 января 2013, 16:25
  • ARMag
  • 1
Файлы в топике: OSA clock energysave.zip

Комментарии (33)

RSS свернуть / развернуть
так как никакими уговорами не удалось подключить питание к контроллеру в обход остальной платы Discovery
Тоже не понял этого момента. По идее можно на средний вывод на джампере JP1(IDD) подать напряжение и всё должно работать. Но у меня не завелось. Может надо было ещё отключить отладчик?
0
Я снимал джамперы с линий, идущих от отладчика к мк — не помогло.
0
я кинул дезу, каюсь. Если снять перемычки с отладчика, плата запускается, но есть нюансы. О них ниже, в комментариях.
0
Результат, так сказать, на лицо. Без всякого шаманства удалось снизить потребление более чем в 7 раз.
Вот вопрос такой. снизив частоту в 16 раз, вы снизили потребление в 7 раз, но при этом увеличили длительность «активной фазы» в 16 раз. На пальцах опишем так:
16 * I1m + (T - 16) * Ilo = 16*I + (T-16)*Ilo = 7*I + (T-16)*Ilo + 9*I = A + 9*I

против
1 * I16m + (T - 1) * Ilo = 7*I + (T-1)*Ilo = 7*I + (T-16)*Ilo + 15*Ilo = A + 15*Ilo

Ввиду того что 9*I >> 15*Ilo получаем, что снижение частоты увеличивает среднее потребление.
Если нет ожидания переферии в активном режиме, то смысл снижать частоту?
0
Вопрос ясен.
В статье описано снижение частоты при постоянной работе планировщика ОС, потому «активная фаза» в конкретном случае равна 100%, так как во время, когда нету готовых задач, планировщик крутится в Idle-режиме ожидания. В случае использования задачи с переходом в режим останова ваше замечание уместно. Завтра, с утра, проведу тесты по повышению частоты и выложу в виде upd к статье.
0
Добавил таблицу с полученными результатами к статье.
0
Благодарю.
Что-то до меня тут дошло. А у вас же на самом деле есть «доступ к переферии». RTC_GetTime и RTC_GetDate будут синхронизироваться с 32кГц кварцем же? Откуда-то читал что доступ к регистрам RTC по тактам низкочастотного кварца. Мне память не изменяет?
0
если я правильно понял Ваш вопрос, то да, перед тем, как считывать регистры RTC, нужно дождаться синхронизации. В коде это реализовано.
while(RTC_WaitForSynchro() == SUCCESS);
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStr);
Show_Time(&RTC_TimeStr)
0
упс, сделал ошибку
while(RTC_WaitForSynchro() != SUCCESS);
0
Ага, любопытно. Но есть вопросы.
Прежде всего — задачи. Если я правильно понимаю, процессор просыпается, выполняет все задачи по одному разу и засыпает. Но ведь скажем задача 4 могла выставить флаг, разблокирующий задачу 2, но получит управление задача 2 только в следущем тике, т.к. после 4-й выполнится задача, усыпляющая МК. По идее, логичней было бы включить приоритеты и выдать высокий приоритет задачам часов и низкий задаче усыпления.
Во вторых — повлияет ли на потребление после добавления спячки повышение тактовой частоты? Судя по табличке, с падением частоты эффективность падает — растет потребление на MIPS, а благодаря спячке программа теперь потребляет не все доступные MIPS'ы, а только реально требуемые.
И в третьих, я не совсем понял код. Он выглядит так, как будто время спячки задается в задаче отправки в сон. Но ведь оно же используется как источник временных интервалов для часов и тогда должна страдать точность хода, т.к. тик получается время_выполнения_задач+таймаут_таймера_пробуждения, а первое время плавает.
При значениях потребления ниже 650 мкА (2МГц, 1МГц) часы работали даже со снятым с разомкнутым джампером JP1
Забавно. Надо поизучать схему дискавери. А ты не проверял, как долго оно работает без джампера? Мож там кондер по питанию стоит достаточный для работы при таком потреблении?
0
  • avatar
  • Vga
  • 28 января 2013, 18:36
Да, вы правильно поняли, процессор выполняет все готовые задачи по разу за проход. Затем пауза в 50мс. Я не включал приоритеты по двум причинам: чтобы получить максимально похожий код с предыдущей статьи (по содержанию и по принципу работы); при включении приоритетов работа планировщика значительно усложняется, что затянет «активную фазу», тем более, что в описанном варианте задержка в 50мс не заметна, поверьте.
На второй вопрос ответил выше — результаты будут завтра.
Ответ на третий вопрос: время останова действительно задается в задаче отправки в сон, и это время никоим образом не влияет на точность хода, оно может повлиять только на частоту обновления экрана и время отклика на нажатие кнопки. В описанном варианте время системного тика плавает в диапазоне 50-53 мс, что не вносит заметных изменений в работу часов.
По поводу последнего вопроса: конденсатор по питанию исключен, так как часы проработали всю ночь, а на плате нету конденсаторов достаточной для этого ёмкости.
0
ИМХО, вариант с приоритетами все же корректней. И ты не изучал нутро OSA? Там где-то должен быть idle-цикл, вот в нем и надо в спячку валиться.
и это время никоим образом не влияет на точность хода
Это хорошо. А что служит источником времени? RTC-модуль?
0
Там где-то должен быть idle-цикл, вот в нем и надо в спячку валиться
Категорически поддерживаю
0
В OSA нету функции Idle. Совсем нет. А разобратьться, куда можно воткнуть ее вызов в функцию планировщика, с наскока довольно сложно, к тому же вариантов этой функции там 3, для разных конфигураций ОС.
0
В том или ином виде idle-цикл быть просто обязан. Хотя да, он запросто может быть в виде зацикленного прогона планировщика по задачам. Собственно, я так и сделал в своем велосипеде.
И я не говорил, что найти этот цикл и нужное место в нем обязательно будет просто.
0
Надо поизучать схему дискавери.
Поизучал. Один из пинов МК подтянут к +3.3V резистором на 10к. Плюс еще один вывод подключен через 10к к выходу ОУ, если там при снятом джампере будет высокий уровень — то и оттуда питание тянуть будет. Хотя по идее, при токе 600мкА на резисторе в 10к должно падать 6В.
0
А еще кнопка подтянута к +3.3В через резистор на 4.7к. Причем все эти подтяжки — к питанию до джампера подключены. С них и тянет паразитное питание, видимо.
0
А почему при подаче 3В на средний контакт на JP1 и GND, микроконтроллер не запускается? По схеме из документации на Discovery следует, что мы подаем питание на VDD.

В чем прикол?
0
А ты SWIM-джамперы снял?
0
Я только что перепроверил. При снятых SWIM-джамперах схема действительно стартует, но, как правильно заметил Vga , подтяжка кнопки и пин МК остаются висеть в воздухе, нужно делать свою подтяжку, по крайней мере для кнопки.
0
Для одной отдельно взятой сфероконины в вакуумепрактической задачи вообще не нужен планировщик. А когда задач, желающих разные уровни потребления, более, чем одна, возникает конкуренция — её нужно разруливать. К тому же событиями для побудки могут быть не только истечение вручную заряжаемой паузы, а различные асинхронные воздействия (та же кнопа на pin-change). Если при этом предполагается достаточная независимость задач, то нужно определить, не произошло ли такое событие между «началом его ожидания» одной задачей (отдает управление планировщику и ждет побудки) и готовностью других задач к засыпанию (отработали до передачи управления планировщику и тоже хотят спать, но события для побудки, например, другие) и если любое такое событие произошло, нужно не заснуть. Если такого не делать, то чтобы не потерять в момент засыпания прерывания, можно разве что инкрементировать счетчики необработанных событий в ISR и потом когда-нибудь все их в фоне разгребать, но это далеко не всегда удобно.
0
Для одной отдельно взятой сфероконины в вакуумепрактической задачи вообще не нужен планировщик.
сказано ведь в родительской статье:
Данная статья — результат моих попыток поработать с кооперативной RTOS OSA на STM8L.
Так как просто мигать светодиодом под ОСью уж совсем примитив, неоднократно описанный в интернетах, для себя я решил начинать знакомство с OSA на проекте, более-менее приближенном к реальности. Первое, что пришло в голову, так сказать, в лучших традициях DIY — запилить часы.
0
Стремление само по себе похвально. Просто пытаюсь указать на грабли. Автору порекомендую почитать Use an MCU's low-power modes in foreground/background systems by Miro Samek, ESD, September 2007.
0
Спасибо за замечания.
Как правильно заметил treasure , эта статья — дополнение к предыдущей, о проекте, с которого я начал знакомство с ОСРВ на МК. Я понимаю, что для того, чтобы сделать часы, излишне использовать ОС, достаточно написать программу, построенную на прерываниях и основное время находящейся в режиме останова. Но данные статьи не о оптимальной программе часов, а о варианте реализации с помощью ОС на конкретной платформе и, опять таки, о варианте использования режима пониженного энергопотребления в данной задаче. Я не утверждаю, что он оптимальный и, тем более, что он единственный. Совершенству нет предела! Но я считаю, что в конкретной задаче — его полностью достаточно.
За статью — спасибо! Обязательно прочту.
0
В моем велосипеде в TCB есть поля требуемого уровня потребления и флаговая структура «ожидаемых событий» побудки («запросы на побудку»). При пробеге списка задач после передачи задачей управления шедулеру все «запросы на побудку» собираются буквально по ИЛИ в один общий «запрос на побудку», а с уровнями потребления проводится «аукцион». В обработчиках прерывания выставляются соответствующие флаги в «запрос на отложенное выполнение обработчика» — он же служит источником запрета засыпания при выполнении системного Idle() — в нём выполняется запрет прерываний, затем запросы проверяются по И, затем если запрета нет, выполняется засыпание с уровнем потребления, победившим в аукционе:), естественно с разрешением прерываний, а если есть запрет, то просто разрешаются прерывания. После побудки «запрос на отложенное выполнение обработчика» перегружается в копию (естественно с временным запретом прерываний) — эта копия уже используется как системный месседж.
0
немного попиарюсь. Моё ядро всё ещё работоспособно при замедлении 8х8, т.е., при 250КГц.

У ОПа в таблице данные только для 1МГц. Почему?
0
6-7мка как-то маловато для самого мк, вкупе с жк и ртс. особенно
При значениях потребления ниже 650 мкА (2МГц, 1МГц) часы работали даже со снятым с разомкнутым джампером JP1, который, по идее, подает питание на контроллер. Делаем вывод, что питание пролазит по паразитным цепям или как-то еще :)

у меня был пример, когда самые обычные атмеловские 8ми-битки (без индекса L) тоже полностью работали примерно так-же. было внешнее тактирование, питание физически отключалось перемычками (тестировалось само потребление). вот в таком режиме контроллер запускался, связянный с «внешним миром» одной землёй и ножками в hi-z… проблема отпала только при включении BoD
0
и ножками в hi-z…
Ну, если хоть на одной из них есть высокий логический уровень — то через защитные диоды он попадет на питание МК.
0
ну, сообщением я скорее не задавал вопрос, почему так произошло (тогда разобрался, хотя это неочевидно немного было), а только заметил, что по факту итоговое потребление некорректно измерено. нужно проделать такое-же на отдельной плате, или всё-таки исключить влияние дискавери =)
0
Ну по паразитным цепям питания довольно большое падение напряжения. Если подоткнуть амперметр (внешний или встроенный в дискавери), то падение на нем будет меньше, чем падение на защитных диодах и ток через паразитные цепи не потечет. Так что измерение вполне корректно.
0
Немного не в тему вопрос, но всё же… А в чём рисуют такие диаграммы, как на картике с задачами ОСи?
0
Вот есть бесплатный мощный инструмент.
0
У меня в прошлом длительный опыт работы в пакете CorelDRAW. Поэтому, по-привычке, его и использую.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.