12. Úsporné režimy, PLL, Watchdog

Cíle cvičení

  • Seznámit se úspornými režimy na ARM procesorech
  • Snížit spotřebu na minimum
  • Nastavit maximální frekvenci jádra MCU (u F401 to je 84 MHz)
  • Ověřit vliv rychlosti a nastavení úsporných opatření na spotřebu MCU
  • Nastavit Watchdog tak, aby hlídal činnost procesoru

Podklady pro cvičení

Sleep a Stop mode

Pro další snížení spotřeby je možné nastavit procesor do některého z úsporných módů. Nejvíce úsporné módy jsou STOP módy, kterých může být i více než 1. Zde záleží na složitosti procesoru. V těchto módech pracují pouze některé periferie a zbytek procesoru je uspaný (včetně jádra) a dá se dosáhnout spotřeby jednotky uA nebo i méně. Přehled těchto možností je v referenčním manuálu v sekci Power Controller včetně možností probuzení.

void sleepModeInit(void){
  RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  SCB->SCR &= ~( SCB_SCR_SLEEPDEEP_Msk );  // low-power mode = sleep mode
}
 
void stopModeInit(void){
  RCC->APB1ENR |= RCC_APB1ENR_PWREN;
  PWR->CR &= ~PWR_CR_PDDS;
  PWR->CR |= PWR_CR_LPDS;
  PWR->CR |= PWR_CR_CWUF;
  PWR->CR |= PWR_CR_LPLVDS;
  PWR->CR |= PWR_CR_MRLVDS;
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
}
 
void sleepModeEnter(void){
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOEEN;
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOHEN;
 
  for(int i=0; i<16; i++){
    GPIOA->MODER |= GPIO_MODE_ANALOG << i*2;
    GPIOB->MODER |= GPIO_MODE_ANALOG << i*2;
    GPIOC->MODER |= GPIO_MODE_ANALOG << i*2;
	GPIOD->MODER |= GPIO_MODE_ANALOG << i*2;
	GPIOE->MODER |= GPIO_MODE_ANALOG << i*2;
	GPIOH->MODER |= GPIO_MODE_ANALOG << i*2;
  }
  RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOAEN;
  RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOBEN;
  RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOCEN;
  RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIODEN;
  RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOEEN;
  RCC->AHB1ENR &= ~RCC_AHB1ENR_GPIOHEN;
 
  PC13_initIRQ();
  stopModeInit();
//  sleepModeInit();
  __WFI();  		// enter low-power mode
  PA5_init();
}
 
void PA5_init(void){
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
  GPIOA->MODER &= ~GPIO_MODER_MODE5_Msk;
  GPIOA->MODER |= 0x01 << 10;
}
 
void PC13_initIRQ(void){
  RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
  RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
 
  GPIOC->MODER &= ~GPIO_MODER_MODE13_Msk;
  GPIOC->PUPDR |= 0x01 << GPIO_PUPDR_PUPD13_Pos;
 
  EXTI->IMR |= EXTI_IMR_IM13;
  EXTI->FTSR |= EXTI_FTSR_TR13;
  SYSCFG->EXTICR[3] |= SYSCFG_EXTICR4_EXTI13_PC;
  NVIC_EnableIRQ(EXTI15_10_IRQn);
}
 
void EXTI15_10_IRQHandler(void){
  EXTI->PR |= EXTI_PR_PR13;
}
 
int main(void){
  PC13_initIRQ();
  PA5_init();
 
  GPIOA->ODR ^= GPIO_ODR_OD5;
  for(volatile int i=0; i<500000; i++);
  GPIOA->ODR ^= GPIO_ODR_OD5;
  for(volatile int i=0; i<500000; i++);
 
  while (1) {
    sleepModeEnter();
    GPIOA->ODR ^= GPIO_ODR_OD5;
    for(volatile int i=0; i<500000; i++);
    GPIOA->ODR ^= GPIO_ODR_OD5;
    for(volatile int i=0; i<500000; i++);
  }
}

Rychlost procesoru 1 MHz

Výchozí hodinový signál pro činnost mikroprocesoru je 16 MHz, který zajišťuje interní RC oscilátor. V případě potřeby snížení spotřeby a tím také výpočetního výkonu, je možné změnit nastavení AHB děličky kmitočtu pro snížení frekvence procesoru. Toto nastavení provedete přes konfigurační registr RCC→CFGR. Detailní diagram najdete v referenčním manuálu v sekci RCC.

void CLK_init_1MHz(void){
  // vyckej nez najede interni 16 MHz RC oscilator
  while(!(RCC->CR & RCC_CR_HSIRDY));
 
  RCC->CFGR |= 0x0B << RCC_CFGR_HPRE_Pos;     // AHB preddelicka na /16 (16/16 = 1 MHz)
}          

Rychlost procesoru 84 MHz

Výchozí hodinový signál pro činnost mikroprocesoru je 16 MHz, který zajišťuje interní RC oscilátor. Většina procesorů s jádrem ARM ale může pracovat i na vyšších kmitočtech v řádu stovek MHz nebo i jednotek GHz. Z důvodu omezené maximální frekvence externího hodinového signálu (u F401 v rozsahu 4–26 MHz) je potřeba využít interní násobičky frekvence v podobě PLL bloku, který je složen z děliček (bloky M a P) a násobičky kmitočtu (blok N). Detailní diagram a použití najdete v referenčním manuálu v sekci RCC.

Z důvodu menší rychlosti vybavení dat z FLASH paměti, je potřeba zařadit do čtení programu čekání v podobě wait cyklů. V případě frekvence 84 MHz postačí nastavit 2 cykly. Další informace lze nalézt v referenčním manuálu v sekci Embedded Flash Memory.

 Distribuce a generovaní hodinového signálu v STM32F401

void CLK_init_84MHz(void){
  // nastav latenci na 2 wait cykly
  FLASH->ACR |= 2 << FLASH_ACR_LATENCY_Pos;      
 
  // vyckej nez najede interni 16 MHz RC oscilator
  while(!(RCC->CR & RCC_CR_HSIRDY));
  // nyni je na vsech periferiich 16MHz
 
  // nastaveni PLL na max. frekvence pro STM32F401 (84 MHz)
  // vymazat predchozi nastaveni
  RCC->PLLCFGR &= ~(RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLQ);    
 
  // nastav M v toleranci 1MHz - 2 MHz, 2 lepsi kvuli jitter efektu
  RCC->PLLCFGR |= ??    << RCC_PLLCFGR_PLLM_Pos;   
 
  // nastav N v toleranci 192-432 MHz
  RCC->PLLCFGR |= ??   << RCC_PLLCFGR_PLLN_Pos; 
 
  // nastav P mene nebo rovno 84 MHz  
  RCC->PLLCFGR |= ?? << RCC_PLLCFGR_PLLP_Pos; 
 
  // nastav Q na /7 (336/7 = 48MHz - mene nebo rovno 48 MHz)
  RCC->PLLCFGR |= 7    << RCC_PLLCFGR_PLLQ_Pos;     
 
  // APB1 preddelicka na /2 (84/2 = 42 MHz - v toleranci do 42 MHz, APB2 ma max. 84MHz)
  RCC->CFGR |= 0x04 << RCC_CFGR_PPRE1_Pos;  
 
  // zapnuti PLL
  RCC->CR |= RCC_CR_PLLON;
  while(!(RCC->CR & RCC_CR_PLLRDY));             // vyckej na nastartovani PLL
 
  RCC->CFGR |= 0x02 << RCC_CFGR_SW_Pos;          // vyber PLL jako zdroje kmitoctu
  while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL);  // vyckej na prepnuti na PLL
}          

Watchdog

Watchdog slouží k hlídání činnosti procesoru, aby běžel v nekonečné smyčce a nikde se nezasekl (typicky při dělení nulou nebo čekání na timeout apod.). Pokud se tomu tak stane, měl by procesor zareagovat (např. restartem procesoru nebo vyřešením problému. Běžné použití watchdogu se používá právě k restartování zacykleného procesoru, aby se vrátil na začátek své činnosti.

V mikroprocesoru lze nalézt několik typů, buď okénkový nebo nezávislý watchdog. V následujícím příkladu se zaměříme na nezávislý (independent watchdog), který má svoje specifické požadavky. Pro nastavení je potřeba zápisu speciální sekvence IWDG→KR

  • 0x5555 - povolení zápisu do PR a RLR
  • 0xCCCC - spuštění WDG
  • 0xAAAA - obnovení WDG, reset časového limitu, nastaví hodnotu čítače WDG na hodnotu v RLR

Vstupní kmitočet pro čítání impulzů je odvozen od interního RC oscilátoru o frekvencí cca. 32 kHz (Low Speed Internal, LSI). Nastavením předděličky a reload registru se poté určuje maximální perioda restartu WDG. Doba do které je potřeba WDG restartovat je v rozmezí cca 125us - 32s. Detailnější informace naleznete v referenčním manuálu v sekci Independent Watchdog.

void IWDG_init(void){
  IWDG->KR = 0x5555;      // enable writing into PR and RLR registers
  IWDG->PR = 0x02;        // prescaler by /16
  IWDG->RLR = 0x0FFF;     // reset value for reload register, 0x0FFF = 4095
  IWDG->KR = 0xCCCC;      // start IWDT
}

courses/b2m37mam/labs/12.txt · Last modified: 2024/12/18 12:45 by nentvond