Low power run (ще один режим енергозбереження)
Є ще один режим енергозбереження, який я не описав в своїй статті про способи економії енергії в STM8L. Його не можна назвати «сплячим режимом», тому що ядро продовжує працювати. нехай і на низькій частоті. Але шляхом відключення найбільш «ненажерливих» частин МК в цьому режимі можна домогтися споживання близько 4-5мкА. Називається він - Low Power Run Mode. для простоти буду називати його LPR.

У режимі LPR МК продовжує працювати, але завдяки відключенню високошвидкісного тактового генератора, флеш пам'яті та інших непотрібних речей, ми отримуємо споживання в районі 5мкА (LCD при цьому був включений, см. Фото).
Відключати всі «непотрібні речі» доводиться вручну, тому процес переходу в LPR може затягнутися:
1) Відключити весь незадіяний периферію
2) Вимкнути всі переривання
3) Перейти в RAM
4) Переключитися на LSI \ LSE (внутрішній низкоскоростной генератор / зовнішній часовий кварц)
5) Відключити HSI і HSE (високошвидкісні тактові генератори)
6) Відключити живлення флеш і EEPROM пам'яті
7) Переключити внутрішній стабілізатор напруги в низькоспоживаючі режим
Пункти з 1 по 5 можна виконувати в довільному порядку (ну, природно, відключати HSI треба після перемикання на LSI ;-)).
Треба зауважити, що в цьому режимі не можна використовувати АЦП - йому необхідний тактовий сигнал не менш 1МГц. Ні LSE (32.768кГц), ні LSI (38кГц) таку частоту не дадуть. Так-же швидше за все не буде працювати і DAC - йому потрібно близько 370мкА в той час як малопотужний стабілізатор може дати тільки 200мкА
Далі розглянемо процес входу в LPR і виходу з нього більш детально. При цьому я буду дотримуватися тієї послідовності, яку дав вище (пам'ятай, що перші 5 пунктів не обов'язково повинні йти по-порядку).
Перше завдання, яке стоїть перед нами - загнати всі функції, що працюють в LPR, в оперативну пам'ять. У IAR це робиться дуже просто. Перед визначенням функції треба додати модифікатор __ramfunc.
Позначення IN_RAM (void foo (void)) означає абсолютно те-ж саме, а цей IN_RAM прописаний в бібліотеці:
Процес переходу в LPR режим починається з перемикання на низькочастотний генератор (LSI або LSE).
Тут використовується автоматичний режим перемикання між тактовими генераторами. Спочатку піднімаємо біт SWEN в регістрі CLK_SWCR - тим самим дозволяючи перемикання. Потім кладемо в регістр CLK_SWR код того джерела, на який хочемо переключитися: 0x1 - HSI. 0x2 - LSI. 0x4 - HSE. 0x8 - LSE. Після цього піднімається прапор SWBSY і починається перемикання, а ми чекаємо його завершення, поглядаючи на цей прапор.
Детальніше про систему тактирования можна прочитати в цій статті.
Коли перемикання на LSI закінчиться, МК буде працювати на частоті 38кГц / Переддільник. При старті встановлений дільник на 8, а значить тактова частота МК буде 4.75кГц. Через це може не працювати ЖК контролер, який за замовчуванням тактується від LSI (без дільника). Необхідно, щоб частота РК контролера була менше або дорівнює частоті МК.
Після переходу на LSI, треба відключити високошвидкісний генератор - HSI. Якщо цього не зробити, то до споживання додасться сотня мікроампер. Благо, відключається він в одну дію:
Наступним пунктом йде відключення живлення флеш і EEPROM пам'яті:
Природно, після цього спроба звернеться до змінної в EEPROM або flash пам'яті призведе до помилки. При спробі перейти на функцію, розташованих в флеш пам'яті відбудеться те ж саме. Тому функції, які нам знадобляться в LPR треба взяти з собою в оперативку.
Так-таки не варто забувати і про переривання - таблиця з їх векторами живе в пам'яті програм, яка тепер не доступна. Тому все переривання треба відключити. Вибирайте будь-який спосіб на смак:
__disable_interrupts
asm ( «sim»);
Після того, як пам'ять відключена, залишається останній крок - відключити основний стабілізатор напруги (ядро STM8 харчується від 1.8В через внутрішній стабілізатор):
Після установки цього біта стабілізатор перейде в ULP (Ultra low power) режим.
Ласкаво просимо в матрицю LPR
Що в цьому режимі можна робити? Так майже те ж саме, що в звичайному. Крім того, що розмір коду може перевищувати обсягу оперативки (мінус стек, мінус змінні), частота обмежена частотою LSI \ LSE, переривання відсутні, а спроба звернеться до функції з флеш пам'яті призведе до зависання МК.
Можна використовувати майже всю периферію (за винятком ADC - він пролітає по частоті), опитувати сенсорні кнопочки, що-небудь вважати (взагалі-то вважати краще на макс. Частоті), спілкуватися з SPI / UART / I2C, і т.д. До речі, ось ця табличка допоможе прикинути загальне споживання МК з урахуванням запущених периферії:

Майже будь-яку периферію можна налаштувати так, щоб вона споживала мінімум струму. Наприклад контролер LCD після зменшення контрастності і частоти оновлення став їсти на пару микроампер менше.
Замість циклів-затримок або циклів при очікуванні якоїсь події від периферії можна використовувати режим WFE (Wait for event). У ньому ядро МК зупиняється до тих пір, поки вибраних периферія НЕ згенерує подія. Такою подією може бути наприклад прихід байта по SPI або переповнення таймера.
Насамперед треба налаштувати джерело події - у нього має бути дозволено відповідне переривання, хоча використовуватися воно не буде. Потім через регістри WFE_CRx (їх всього 3 штуки) вибираємо джерело події, який розбудить МК. Наприклад так:
Ця подія від таймера №4. Повний список подій я тут наводити не буду, а пошлю вас за ним на 74 сторінку RM0031.
Потім запускаємо джерело події (включаємо таймер, або передаємо біт по SPI) і виконуємо інструкцію
Тепер ядро МК зупинилося до настання події, після чого воно продовжить виконувати код з наступної команди. Після виходу з WFE треба скинути прапор переривання нашого джерела події і скинути біт в регістрі WFE_CRx - інакше переривання не буде спрацьовувати в звичайному режимі.
Насправді, WFE сильно економить енергію, коли МК працює на високих частотах. Але в LPR ядро і так майже нічого не споживає, тому WFE може дати лише пару микроампер економії.
До речі, в halt режим з LPR йти не можна - адже пробудження з нього можливо тільки від переривання, які в LPR заборонені.
Тепер поговоримо про те, як прокинутися і вийти з LPR.
Тут повторюється та-ж процедура, тільки в зворотному порядку. Спочатку включимо основний стабілізатор живлення:
Запускається шарманка не відразу, тому перед тим, як включати все інше, треба почекати, поки стабілізатор увійде в робочий режим. До речі, в ULP режимі цей стабілізатор можения видавати струм до 200мкА, а в звичайному - до 25мА.
Після стабілізатора можна запускати флеш:
Пам'ять теж включається не відразу, а через кілька мікросекунд. Але з огляду на те, що МК все ще працює від низькочастотного генератора, то ці мікросекунди пролетять непомітно, буквально за один такт. Тому цикл очікування можна і прибрати.
Тепер, коли пам'ять програм включена, можна переключиться на HSI:
Таким чином ми повернулися до початкової частоті - 2МГц.
Дозволити переривання і запустити потрібну периферію можна в будь-який момент. Тільки перші два пункти повинні виконуватися по порядку, інші - довільно.
For Example
Для прикладу була створена програма, роботу якої можна спостерігати в цьому ролику:
Пара уточнень для тих, хто вирішить покопатися в коді:
IN_RAM це те ж саме, що __ramfunc
BAR1_ON і схожі конструкції спільно з функцією LCD_bar (); рулять смужкою з правого боку дисплея. BAR0_ON - запалити нижній сегмент, BAR1_ON - другий знизу, і т.д. Вони просто записують значення в масив t_bar. Для того, щоб загасити всю смужку, масив треба обнулити.
Функція LCD_GLASS_Init - стандартна процедура ініціалізації РК - була змінена для зменшення споживання. Я знизив контраст і частоту оновлення.
Функція LCD_bar (); була викинута в оперативну пам'ять, так-як використовується коли флеш відключена.
Корисні посилання
STM8L family power management - корисний аппноут, де описуються не тільки енергозберігаючі режими, а й інші способи зниження споживання МК.
Як використовувати цей режим і використовувати-ли його взагалі - справа розробника, і залежить це в першу чергу від завдання. Я за час написання цієї замітки так і не придумав жодної задачі, де-б цей режим повністю себе виправдовував і його не можна було-б замінити зв'язкою Active Halt + AWU * + Зовнішні переривання.
* AWU - функція, що дозволяє МК автоматично виходити з halt режиму після деякого часу. У STM8L15x реалізована в складі RTC, а в STM8L101 - як самостійний модуль.
P.S. На замітку: Натиснута кнопка, яка підтягнута до + 3V резистором в 20к споживає стільки ж, скільки 30 МК STM8L152C6 працюють в Low Power Run режимі. Так то!