poniedziałek, 12 września 2016

[16] STM32F4 - Discovery - Tryby oszczędzania energii

Tym razem chciałbym przedstawić sposób obsługi trybów oszczędzania energii w mikrokontrolerach z rodziny STM32F4.

Do wyboru są następujące rodzaje trybów oszczędzania energii w STM32:

  • Tryb uśpienia (Sleep Mode)
  • Tryb zatrzymania (Stop Mode)
  • Tryb czuwania (Standby Mode)
  • Tryb Vbat (Vbat Mode)

Rys. 1. Pobór prądu dla mikrokontrolerów [datasheet]

Poniżej przedstawię jakie elementy układu działają dla poszczególnych trybów pracy:

W trybie uśpienia wyłączeniu ulega rdzeń mikrokontrolera, natomiast bloki peryferyjne oraz źródła sygnałów zegarowych są pozostawione jako aktywne. Z tego powodu powrót układu do normalnej pracy jest najszybszy z pozostałych układów. W związku z tym, że zegary są włączone to pobór prądu w tym trybie oraz w przypadku standardowej pracy zależy od częstotliwości taktowania. Jak można zaobserwować na rysunku 1, dla stm32f407 wartość prądu przy maksymalnej częstotliwości wynosi 40mA.

Kolejnym trybem jest tryb zatrzymania. W tym przypadku dane w SRAM oraz rejestrach zostają zachowane. Zegary PLL, HSI oraz HSE zostają zatrzymane, LSE, LSI oraz zegary czasu rzeczywistego, jeśli nie zostały wcześniej wyłączone, pracują nadal. Regulatory napięcia pracują w trybie normalnym albo z obniżonym poborem prądu. Natomiast pamięć flash może zostać skonfigurowana do pracy w trybie zatrzymania albo głębokiego uśpienia. Regulator napięci 1,2V można wprowadzić w tryb obniżonego poboru mocy. Spowoduje to natomiast dłuższy czas wybudzania układu. Dodatkowo układ niezależnego watchdoga może pracować w normalnym trybie.

Tryb czuwania jest najbardziej ekonomiczny, cechuje się najniższą wartością poboru prądu. W tym trybie zegary oraz rdzeń zostały wyłączone. Regulator napięcia oraz domeny 1.2V także są ustawione jako wyłączone. Dane przechowywane w rejestrach zostają utracone, z wyjątkiem danych wprowadzonych do tzw. Backup domain czyli do rejestrów chronionych. Zasilanie Vbat musi być doprowadzone do układu. Układ wraca do normalnej pracy, w przypadku wystąpienia sygnału reset, po przepełnieniu niezależnego watchdoga, w przypadku wystąpienia alarmu na RTC bądź gdy pojawi się sygnał na linii Wakeup. 

Ostatni z trybów tzn. Vbat mode może być używane tylko w przypadku wyłączenia głównego zasilania Vdd. 

Programowanie:


Do obsługi trybów uśpienia służą rozkazy asemblerowe __WFI() (wait for interrup) lub __WFE() (wait for event). Oraz biblioteki stm32f4xx_pwr. Zawiera ona wszystkie funkcje umożliwiające wprowadzanie układów tryby oszczędzania energii.

__WFI() wchodzi w tryb uśpienia wtedy gdy zakończyć wykonywanie wszystkich przerwań. Z trybu uśpienia może go wybudzić wywołanie przerwania.

Wybudzenie będzie szybsze w przypadku zastosowania instrukcji __WFE(), która nie potrzebuje dodatkowo wykonywania obsługi przerwania.

Pierwsza funkcja pozwala na wprowadzenie układu w stan uśpienia, aż do momentu wystąpienia określonego zdarzenia.

  1. void LOWPOWER_GO_SLEEP_INTERRUPT(uint8_t parameter_off_timer)
  2. {
  3.     //parameter_delay_timer, gdy jeden to wylacza timery
  4.     //gdy zero to zostawia je wlaczone
  5.     //Wylaczenie timerow oraz systicka
  6.     if (parameter_off_timer == 1)
  7.     {
  8.         #if defined(TIMER_DELAY)
  9.         //Wylaczenie zdefiniowanego timer dla opoznien
  10.         TIM_Cmd(TM_DELAY_TIM, DISABLE);
  11.         #else
  12.         //Wylaczenie systicka jeśli on służy do opóźnień zamiast zwykłego timera
  13.         SysTick->CTRL &= ~SysTick_CTRL_TICKINT_Msk;
  14.         #endif
  15.     }
  16.    
  17.     __WFI();    //Czekanie na przerwanie
  18.    
  19.     //Mikrokontroler w trybie sleep mode, oczekiwanie na przerwanie
  20.    
  21.     //Wlaczenie timerow
  22.     if (parameter_off_timer == 1)
  23.     {
  24.         #if defined(TIMER_DELAY)
  25.         //Wlaczenie timera
  26.         TIM_Cmd(TM_DELAY_TIM, ENABLE);
  27.         #else
  28.         //Wlaczenie systicka
  29.         SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
  30.         #endif
  31.     }
  32. }

Wprowadzenie układu w tryb uśpienia z oczekiwaniem na zdarzenie realizuje się poprzez wywołanie odpowiedniego makra. Nie trzeba w tym przypadku wyłączać systicka i timerów, ponieważ nie mogą one wywołać zdarzenia.

  1. void LOWPOWER_GO_SLEEP_EVENT(void)
  2. {  
  3.     //Oczekiwanie na zdarzenie
  4.     __WFE();
  5. }

Następna opcja umożliwia wprowadzenie układu w tryb czuwania tzw. stand by. W tym przypadku należy wyczyścić flagi, standby oraz wakeup, po czym przejść do funkcji PWR_EnterSTANDBYMode(), która jest zdefiniowana w bibliotekach API. Wprowadza ona układ w omawiany tryb.

  1. void LOWPOWER_GO_STANDBY_MODE(void)
  2. {
  3.     //Czyszczenie flag
  4.     //PWR_CSR_SBF oraz PWR_CSR_WUF
  5.     PWR_ClearFlag(PWR_FLAG_SB | PWR_FLAG_WU);
  6.    
  7.     //Przejście w tryb StandBy
  8.     PWR_EnterSTANDBYMode();
  9. }

Wyczyszczenie flagi dla trybów standby:

  1. uint8_t LOWPOWER_STANDBY_MODE_RESET(void)
  2. {
  3.     //sprawdzenie flagi
  4.     if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)
  5.     {
  6.         //Wyczysc flagi
  7.         PWR_ClearFlag(PWR_FLAG_SB | PWR_FLAG_WU);
  8.     }
  9.    
  10.     return 0;
  11. }

Następnym trybem jest STOP mode. Jego wywołanie wygląda następująco:

  1. void LOWPOWER_GO_STOP_INTERRUPT(void)
  2. {
  3.     //Przejście w tryb zatrzymania
  4.     PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
  5.    
  6.     //Ponowne włączenie wszystkich zegarów
  7.     SystemInit();
  8. }

W odpowiedni tryb wchodzi się poprzez podanie funkcji z biblioteki PWR. Po wyjściu z trybu zatrzymania należy ponownie włączyć wszystkie zegary. 

Tryb zatrzymania do momentu wystąpienia zdarzenia:

  1. void LOWPOWER_GO_STOP_EVENT(void)
  2. {
  3.     //Wejscie w tryb stop
  4.     PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFE);
  5.    
  6.     //Wlaczenie zegarow
  7.     SystemInit();
  8. }


Jeśli chodzi o ograniczenie poboru prądu przez cały układ z mikrokontrolerem, to można tu uzyskać poprzez wykonywanie następujących elementów:
  • ograniczenie częstotliwości taktowania do wartości najmniejszej zadowalającej, czyli takiej która nie wpłynie negatywnie na procesy transmisji danych pomiędzy układami;
  • stosowanie układów z niższym zapotrzebowaniem energetycznym bądź takich które można wprowadzać w odpowiednie stany ograniczające pobór mocy.
  • wyłączenie nie potrzebnych linii zegarowych oraz peryferiów,
  • dodatkowo jeśli urządzenie działa cyklicznie to po dokonaniu pomiarów można wyłączyć wszystkie peryferia (czasami jest to wykonywane samoistnie w trybach uśpienia, w niektórych mikrokontrolerach należy to robić ręcznie) na czas oczekiwania przed dokonaniem kolejnego pomiaru.

Przy projektowaniu systemu wymagającego obniżony pobór mocy należy pamięć o:
  • przeprowadzeniu dokładnych obliczeń poboru prądu, oraz długości życia baterii,
  • dokładnego zbadania możliwości obcięcia poboru energii dla wybranego mikrokontrolera,
  • na jaki okres czasu przy budowanym systemie poszczególne bloki mogą zostać pozbawione zasilania,
  • jak szybko możliwe jest przejście do trybu aktywnego i w jaki sposób to wykonać, tzn. jakie elementy muszą zostać włączone, przy wystąpieniu jakiej sytuacji mikrokontroler się obudzi itp.

Dokumentacja:


[1] Using STM32F4 MCU power modes with best dynamic efficiency